그림판 만들기 - 5 실행 취소 기능

정영찬·2022년 7월 20일
0

프로젝트 실습

목록 보기
10/60

사용자가 그림을 그리다가 만약 실수를 했다면 그 이전의 상태로 돌아갈수 있는 기능을 구현한다.

사용자가 그린 그림을 url 형태로 저장해놨다가 실행 취소 기능을 누르면 이전에 저장된 그림 url을 불러와서 캔버스에 보여준다.

먼저 실행 취소 버튼 query 선택, 이벤트 목록 추가, 이벤트 생성

  assignElement() {
   
    this.undoEl = this.toolbarEl.querySelector("#undo");
  }
  
  addEvent() {
    
    this.undoEl.addEventListener("click",this.onClickUndo.bind(this));
  }

 onClickUndo() {}

onClickUndo 를 작성하기 전에, 현재 그림을 저장하는 메소드를 작성한다. 데이터가 들어갈 배열을 하나 선언하고, 그 배열에 데이터를 집어넣는 saveState메소드를 만든다

saveState(){
    this.undoArray.push(this.canvasEl.toDataURL());
    console.log(this.undoArray);
  }

이 메소드는 실행 취소를 위해서 현재 그림보다 "이전" 의 상태가 저장되어있어야 하므로 사용자가 그림을 그리는순간, 다시 말해서 브러쉬를 고르고 캔버스에 그림을 그리기 위해 클릭하는 순간에 캔버스의 그림 데이터가 저장되어야한다. 따라서 onMouseDown이벤트에 saveState를 추가해야 한다.

이 상태에서 다시 실행하여 콘솔을 확인해보면

사용자가 그림을 그리기 위해 마우스를 클릭할 때마다 그리기 전의 캔버스 상태의 데이터가 저장되는 모습을 볼 수 있다.
그럼 이 데이터를 불러오기만 하면 실행 취소 기능의 구현은 완료된다.

 onClickUndo() {
    if (this.undoArray.length === 0) return;
    let previousDataUrl = this.undoArray.pop();
    let previousImage = new Image();
    previousImage.src = previousDataUrl;
    previousImage.onload = () => {
      this.context.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);
      this.context.drawImage(
        previousImage,
        0,
        0,
        this.canvasEl.width,
        this.canvasEl.height,
        0,
        0,
        this.canvasEl.width,
        this.canvasEl.height
      );
    };
  }

undoArray의 길이가 0일 경우에는 종료된다.
undoArray의 마지막 데이터를 사용해야 이전의 상태로 돌아올수 있기 때문에 pop을 사용해서 데이터를 가져온다(previousDataUrl). 새로운 Image를 선언하고 onload에서 캔버스를 지우고 다시 그림을 그리는 것이다. 이때의 그림은 previousImage의 src 인 previousDataUrl을 사용한다. 해당 그림의 좌표, width,height도 동일하게 그림을 그리게 만들면 캔버스에서 이전의 상태가 나타나게 되는 것이다.

이제 실행해보면

이렇게 실행 취소 버튼을 누를 때마다 이전의 그림으로 돌아가는 모습을 볼수 있다.

끝?

사용자가 그린 그림을 마냥 다 저장하지 말고, 5개만 저장되어서 이전상태를 되돌릴수 있는 횟수에 제한을 두게 해보자. 사용자의 그림에 대한 최근 기록을 5개로 제한하고, 지속적으로 그림을 그리게 될 경우에는 가장 먼저 저장된 데이터를 제거한뒤 가장 최근의 데이터가 다시 저장되는 방식으로 구현한다.

 saveState() {
    if (this.undoArray.length > 4) {
      this.undoArray.shift(); // 맨 처음의 데이터를 제거한다.
      this.undoArray.push(this.canvasEl.toDataURL());
    } else {
      this.undoArray.push(this.canvasEl.toDataURL());
    }    
  }

undoArray의 길이가 5를 넘었을 경우에는 처음의 데이터를 제거하고 최근의 데이터를 저장함으로써 5개를 유지시킨다!

이렇게 하면 실행 취소를 최대 5번까지만 가능하게 된다.

추가적으로 만약 더이상 실행 취소를 할수 없을 때(undoArray의 길이가 0일때) 사용자가 클릭을 다시 하면, 알림이 나오게 해보자.

onClickUndo메소드에서 undoArray의 길이가 0일때 alert를 사용해서 알림문구가 나타나가 하면 된다.

  onClickUndo() {
    if (this.undoArray.length === 0) {
      alert("더 이상은 실행 취소를 할 수 없어요!");
      return;
    }
    let previousDataUrl = this.undoArray.pop();
    let previousImage = new Image();
    previousImage.src = previousDataUrl;
    previousImage.onload = () => {
      this.context.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);
      this.context.drawImage(
        previousImage,
        0,
        0,
        this.canvasEl.width,
        this.canvasEl.height,
        0,
        0,
        this.canvasEl.width,
        this.canvasEl.height
      );
    };
  }

성공적으로 알림 문구가 출력되는 모습을 볼 수 있다.

profile
개발자 꿈나무

0개의 댓글