\(@^0^@)/
[TIL] 바닐라 자바스크립트로 이미지 에디터를 만들어보자. 본문
이미지 에디터 만들기
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
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
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage
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 ]
'TIL' 카테고리의 다른 글
[TIL] 제어 컴포넌트(Controlled Components)와 비제어 컴포넌트(Uncontrolled Components)의 특징 (0) | 2022.07.26 |
---|---|
[TIL] 바닐라 자바스크립트로 글쓰기 에디터를 만들어보자. (2) | 2022.07.22 |
[TIL] CRA를 사용하지 않고, 직접 react, react-dom, babel, webpack, HMR(hot-module-replacement)를 세팅해보자! (0) | 2022.07.09 |
[TIL] vanilla JS에 CustomEvent을 사용해보자! (0) | 2022.07.02 |
[TIL] Figma file의 모든 CSS 변수를 간단하게 추출하는 plugin 사용법! (0) | 2022.06.30 |