6. 개발 - 뒤로가기(작업 취소), 앞으로 가기(복구) Z-index 조정 기능

2022. 7. 20. 00:01·프로젝트 회고/이미지편집기 개발

1) 뒤로 가기(작업 취소), 앞으로 가기(복구)

뒤로 가기, 앞으로 가기 기능을 구현하기 위해서 back, front 2개의 스택을 만들었다. back 스택은 작업 실행 전 상태들을 담아놓고, front 스택은 앞으로 가기를 실행했을 때 현재 상태, 즉 복구되기전 상태들을 담아 놓았다.

각 스택에는 편집기의 배경, 이미지, 텍스트 정보가 들어간다. (nodes, background)

매 작업(ex: 배경색 변경, 노드 속성 변경 등)을 실행할 때마다 현재 상태와 이전 상태를 저장했다. (saveHistory, saveNow 메소드 실행) 즉 작업전 상태가 back 스택에 쌓이고 현재 상태는 nowState라는 변수에 담았다. 또, front 스택을 비워서 뒤로 가기 후 다른 작업을 실행할 시 앞으로 가기가 불가능하도록 했다.

뒤로 가기 버튼을 누르면 nodes와 background를 backStack에서 pop한 애로 갱신했다. (직전 상태) 그리고 현재 상태를 그 pop한 애로 바꿨다.

앞으로 가기 버튼을 클릭 시 frontStack에서 pop해와서 nowState , nodes, background를 변경했다.

각 버튼은 front, back 스택의 길이가 0인 경우 disabled 되게 해서 사용자가 혼란을 겪지 않게 했다. 각 스택의 길이는 50으로 고정해서 너무 많은 용량이 낭비되지 않게 했다.

function historyManagerBuilder() {
    
    let backStack = []
    let frontStack = []
    let nowState;
    const SIZE_LIMIT = 50
    
    function pushWithSizeLimit(item) {
        // console.log(this)
        this.push(item)
        if(this.length > SIZE_LIMIT) {
            this.splice(0,1)
        }
    }
    // 오류처리해야됌
    // 뒤로갈거 없을때, 앞으로 갈거 없을때 버튼 비활성화
    backStack.pushWithSizeLimit = pushWithSizeLimit.bind(backStack)
    // console.log(backStack.pushWithSizeLimit)
    frontStack.pushWithSizeLimit = pushWithSizeLimit.bind(frontStack)
    return {
        saveHistory : (beforeState) => {
            backStack.pushWithSizeLimit(beforeState)
            
        },
        saveNow : (_nowState) => {
            nowState = _nowState 
            frontStack.splice(0, frontStack.length)
            // console.log(frontStack)
        },
        goBack : () => {
            if(backStack.length === 0) return []
            const lastState = backStack.pop()
            frontStack.pushWithSizeLimit(nowState)
            nowState = lastState
            // console.log("backStack: ", backStack, "frontStack:", frontStack)
            return lastState
        },
        goFront : () => {
            if(frontStack.length === 0) return []
            const frontLastState = frontStack.pop()
            backStack.pushWithSizeLimit(nowState)
            nowState = frontLastState
            return frontLastState
        },
        isEmptyBackStack : () => {
            // console.log(backStack.length)
            return backStack.length === 0
        },
        isEmptyFrontStack : () => {
            // console.log(frontStack.length)
            return frontStack.length === 0
        },
        flush: () => {
            while(frontStack.length > 0) {
                frontStack.pop()
            }
            while(backStack.length > 0) {
                backStack.pop()
            }
        }
    }
}

const historyManager = new historyManagerBuilder

export default historyManager

 

2) 노드 Z-index 변경

Konva의 경우 jsx에서 컴포넌트 순서대로 그림을 그린다.

즉, nodes.forEach(node => <Node {...node}/> 이 코드는 아래 그림처럼 그려지게 된다.

Konva 그리기 순서

 

여기서 0 노드를 1노드의 앞에 보이게 하고 싶다면 배열에서 두 원소를 서로 교환하면 된다. 

이런 식으로 노드의 Z-index 변경 (맨 앞으로 보내기, 맨 뒤로 보내기, 앞으로 보내기, 뒤로 보내기)를 구현했다.

export function arrayOfObjectReducer(state, action) {
    let newState = state.slice()
    let target = null
    let targetIdx
    let maxId
    if(action.id) {
        target = newState.find(each => each.id === action.id)
    }
    
    // console.log(action)
    switch (action.type) {
        // ...생략
        case 'MOVE__FRONT':
            newState = [...newState.filter(each => each.id !== action.id), target]
            break
        case 'MOVE__REAR':
            newState = [target, ...newState.filter(each => each.id !== action.id)]
            break
        case 'MOVE__FORWARD':
            // 인덱스 한칸 뒤로 +1
            targetIdx = newState.findIndex(each => each.id === action.id)
            // 이미 맨뒤에있으면 안함
            if(targetIdx === newState.length-1) break
            // 서로 바꾸기
            change(newState, targetIdx, targetIdx+1) 
            break
        case 'MOVE__BACKWARD':
            // 인덱스 한칸 앞으로 -1
            targetIdx = newState.findIndex(each => each.id === action.id)
            if(targetIdx === 0) break
            change(newState, targetIdx, targetIdx-1)
            break
        default:
            break
    }
    return newState
}

 

저작자표시 (새창열림)

'프로젝트 회고 > 이미지편집기 개발' 카테고리의 다른 글

7. 정리 - 끝  (0) 2022.07.20
5. 개발 - 상태 관리 리팩토링 - useReducer  (0) 2022.07.18
4. 개발 - 편집기 주 화면 구현, 배경, 노드(이미지, 텍스트) 추가, 편집 기능  (0) 2022.06.30
3. 개발 - 기본 구조  (0) 2022.06.19
2. 액션 정의하기, 앱 구조와 화면 레이아웃 잡기  (0) 2022.06.15
'프로젝트 회고/이미지편집기 개발' 카테고리의 다른 글
  • 7. 정리 - 끝
  • 5. 개발 - 상태 관리 리팩토링 - useReducer
  • 4. 개발 - 편집기 주 화면 구현, 배경, 노드(이미지, 텍스트) 추가, 편집 기능
  • 3. 개발 - 기본 구조
정현우12
정현우12
  • 정현우12
    정현우의 개발 블로그
    정현우12
  • 전체
    오늘
    어제
    • 분류 전체보기 (80) N
      • 프론트엔드 (56)
        • JavaScript, TypeScript (12)
        • 스타일링 (1)
        • React (13)
        • Next.js (4)
        • 개발 환경 (9)
        • 테스트 (3)
        • 성능 최적화 (11)
        • 함수형 프로그래밍 (2)
        • 구조 (1)
      • 프로젝트 회고 (24) N
        • 이미지편집기 개발 (7)
        • 엑셀 다운로드, 업로드 공통 모듈 개발 (4)
        • 사용자 매뉴얼 사이트 개발 (3)
        • 통계자동화 솔루션 개발 (1)
        • 엑셀 편집기 개발 (5)
        • API 플랫폼 (1)
        • 콜센터 솔루션 OB 캠페인 (1)
        • AI 스튜디오 (1)
        • AI 워크플로우 저작도구 (1) N
      • 백엔드 (0)
  • 블로그 메뉴

    • 홈
    • 포트폴리오
    • 태그
  • 인기 글

  • 태그

    성능 최적화
    useReducer
    커스텀 훅
    회고
    Next.js
    memoization
    이미지 편집기
    TypeScript
    로딩 성능 최적화
    라이브러리 선정
    엑셀 에디터
    렌더링 성능 최적화
    사용자 매뉴얼 사이트
    React-boilerplate
    JavaScript
    React
    webpack
    웹 성능 최적화
    Github Actions
    엑셀
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
정현우12
6. 개발 - 뒤로가기(작업 취소), 앞으로 가기(복구) Z-index 조정 기능
상단으로

티스토리툴바