\(@^0^@)/

[TIL] 바닐라 자바스크립트로 이미지 에디터를 만들어보자. 본문

TIL

[TIL] 바닐라 자바스크립트로 이미지 에디터를 만들어보자.

minjuuu 2022. 7. 21. 21:13
728x90

이미지 에디터 만들기

0. 생성자 함수 안에 데이터들을 초기화시켜놓기.

;(function () {
  'use strict'

  const get = (element) => document.querySelector(element)

  class PhotoEditor {
    constructor() {
      this.fileInput = get('.drag_area input')
      this.fileImage = get('.fileImage')
      this.fileEvent()
      this.width = 500
      this.height = 200
      this.targetImage = get('.canvas_wrap')
      this.targetCanvas = document.createElement('canvas')
      this.targetCtx = this.targetCanvas.getContext('2d')
      this.img = new Image()
    }
  }

  new PhotoEditor()
})()

컨스트럭터에 초기 데이터들을 설정해준다.
canvas element를 생성하고, 해당 canvas를 담은 this.targetCanvas를 targetCtx에 할당해준다.
clickEvent에 여러 버튼 이벤트를 넣고, fileEvent에는 file 업로드하는 함수를 생성.

https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext

 

HTMLCanvasElement.getContext() - Web APIs | MDN

The HTMLCanvasElement.getContext() method returns a drawing context on the canvas, or null if the context identifier is not supported, or the canvas has already been set to a different context mode.

developer.mozilla.org


1. 생성한 image 태그에 drag and drop으로 사진 업로드하기.

fileEvent() {
      this.fileInput.addEventListener('change', (event) => {
        const fileName = URL.createObjectURL(event.target.files[0])
        this.img.addEventListener('load', () => {
          this.targetCanvas.width = this.width
          this.targetCanvas.height = this.height
          this.targetCtx.drawImage(
            this.img,
            0,
            0,
            this.targetCtx.canvas.width,
            this.targetCtx.canvas.height
          )
        })
        this.img.setAttribute('src', fileName)
        this.targetImage.appendChild(this.targetCanvas)
      })
    }

코드가 너무 길어서 그냥 fileEvent함수만 넣겠음.
this.fileInput 즉, input에 사진을 첨부할 경우 업로드를 위한 이벤트가 발생한다.
fileName 변수에 드래그하여 첨부한 사진의 파일 url를 받아온다.
초기화해둔 this.img에 load를 시킨다.
또 canvas를 이용하여 다른 기능들을 작동시키기 위해서 this.targetCanvas.width height 초기화해두었던 width, height을 할당하고, this.targetCtx.drawImage를 이용하여 캔버스 이미지를 그려둔다.
해당 이미지의 src에 받아온 url을 넣어주고 컨테이너에 캔버스를 추가하여 업로드시킨다.


https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage

 

CanvasRenderingContext2D.drawImage() - Web APIs | MDN

The CanvasRenderingContext2D.drawImage() method of the Canvas 2D API provides different ways to draw an image onto the canvas.

developer.mozilla.org

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage

 

CanvasRenderingContext2D.drawImage() - Web APIs | MDN

The CanvasRenderingContext2D.drawImage() method of the Canvas 2D API provides different ways to draw an image onto the canvas.

developer.mozilla.org


2. filter기능 추가
2
-1. filp

flipEvent() {
      this.targetCtx.translate(this.targetCtx.canvas.width, 0)
      this.targetCtx.scale(-1, 1)
      this.targetCtx.drawImage(this.img, 0, 0, this.width, this.height)
    }

translate() scale()로 캔버스 x축을 변환하고, 변환한 값을 drawImage()를 통해 뿌려준다.


2-2. sepia, gray

CanvasRenderingContext2D의 filter 요소를 sepia와 gray로 변환해주고,
변환한 값을 drawImage()를 통해 뿌려준다.

sepiaEvent() {
      this.targetCtx.filter = 'sepia(1)'
      this.targetCtx.drawImage(this.img, 0, 0, this.width, this.height)
    }

    grayEvent() {
      this.targetCtx.filter = 'grayscale(1)'
      this.targetCtx.drawImage(this.img, 0, 0, this.width, this.height)
    }


3. download

download() {
      const url = this.targetCanvas.toDataURL()
      const downloader = document.createElement('a')
      downloader.style.display = 'none'
      downloader.setAttribute('href', url)
      downloader.setAttribute('download', 'canvas.png')
      this.container.appendChild(downloader)
      downloader.click()
      setTimeout(() => {
        this.container.removeChild(downloader)
      }, 100)
    }

 

HTMLCanvasElement.toDataURL()를 사용해서 해당 이미지의 url을 받고 a태그를 이용해 href에 url을 넣고, 파일명은 canvas.png로 저장한다.
가장 바깥의 태그에 append 한 후, a태그가 클릭되도록 한다. 그 후, 바로 a태그가 삭제되도록 하면 다운로드 기능이 만들어진다.


내가 본 강의에는 이미지를 crop 하는 기능도 있었는데, 아직 코드들이 이해가 안 가서 우선 이해 가는 곳까지만
나만의 스타일로 구현하였다. 일요일에 시간이 된다면 crop 하는 부분까지 추가해보자.

[ 출처 : 프로젝트로 배우는 JavaScript ]

728x90