Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

react-konva-image-editor

wormwlrm36MIT0.0.8

๐Ÿ–ผ HTML5 Canvas API Image Editor based on React.js & Konva.js

react, react-konva, react-konva-image-editor

readme

react-konva-image-editor

Subject

  • (๊ตญ๋ฌธ) HTML5 Canvas ๊ธฐ๋ฐ˜ ์˜คํ”ˆ์†Œ์Šค ์ด๋ฏธ์ง€ ์—๋””ํ„ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ฐœ๋ฐœ
  • (์˜๋ฌธ) Opensource Image Editor Library Development based on HTML5 Canvas
  • ๋ณธ ํ”„๋กœ์ ํŠธ๋Š” 2021-2ํ•™๊ธฐ ๊ฒฝํฌ๋Œ€ํ•™๊ต ์บก์Šคํ†ค ๋””์ž์ธ 1 - ์‚ฐ์—…์ฒด ์ฃผ์ œ(๋ชจ๋ฐ”์ผ ์•ฑ๊ฐœ๋ฐœ ํ˜‘๋™์กฐํ•ฉ)๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๊ฐœ๋ฐœํ–ˆ์Šต๋‹ˆ๋‹ค.

Members

  • ์ •์ข…์œค(@wormwlrm)

Abstract

HTML5๋ถ€ํ„ฐ ๋“ฑ์žฅํ•œ Canvas API๋ฅผ ์ด์šฉํ•˜๋ฉด ์›น์—์„œ๋„ ์ด๋ฏธ์ง€ ํŽธ์ง‘์„ ๋น„๋กฏํ•œ ๋‹ค์–‘ํ•œ ๊ทธ๋ž˜ํ”ฝ ๊ธฐ์ˆ ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” API์˜ ์ถ”์ƒํ™” ๋‹จ๊ณ„๊ฐ€ ๋‚ฎ๊ณ , ๊ทธ๋ž˜ํ”ฝ ๋„๋ฉ”์ธ์— ๋Œ€ํ•œ ์ง€์‹์„ ๋ณ„ ๋„๋กœ ํ•™์Šตํ•ด์•ผ ํ•œ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์—๋Š” Canvas API๋ฅผ ์ง์ ‘ ํ™œ์šฉํ•˜๊ธฐ๋ณด๋‹ค๋Š” ์™„์„ฑ ๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ ํƒํ•œ๋‹ค.

๋ณธ ๋…ผ๋ฌธ์—์„œ๋Š” ์ด๋ฏธ์ง€ ํŽธ์ง‘์— ์ดˆ์ ์„ ๋งž์ถ”์–ด, 2D ๊ทธ๋ž˜ํ”ฝ ๊ธฐ๋ฐ˜์˜ Canvas API๋ฅผ ํ™œ์šฉํ•œ ์˜คํ”ˆ์†Œ์Šค ์ด๋ฏธ์ง€ ์—๋””ํ„ฐ๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค. ์ด๋ฏธ์ง€ ์—๋””ํ„ฐ์—์„œ ์ œ๊ณตํ•˜๋Š” ๋‹ค์–‘ํ•œ ํŽธ์ง‘ ๊ธฐ๋Šฅ๋“ค์„ ์–ด๋– ํ•œ Canvas API์™€ ๋””์ž์ธ ํŒจํ„ด์œผ๋กœ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•œ์ง€๋ฅผ ์—ฐ๊ตฌํ•˜๊ณ , ์ด ๊ณผ์ •์—์„œ ๋งˆ์ฃผ์น˜๋Š” ํ•œ๊ณ„์ ๋“ค์„ ๊ทน๋ณตํ•˜๋Š” ๋ฐฉ์•ˆ์— ๋Œ€ํ•ด ์•Œ์•„๋ณธ๋‹ค.

Overview

๋ณ„๋„ ์ œ์ž‘ํ•œ ๋ฐ๋ชจ ํŽ˜์ด์ง€์—์„œ ๋™์ž‘ํ•˜๋Š” ์˜ˆ์‹œ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ณธ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์€ ์•„๋ž˜์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • <input checked="" disabled="" type="checkbox"> ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜•ํƒœ๋กœ ํŒจํ‚ค์ง€ ๋ฆด๋ฆฌ์Šค
  • <input checked="" disabled="" type="checkbox"> ํ˜ธ์ŠคํŠธ ์˜ต์…˜ ์ œ๊ณต
  • <input checked="" disabled="" type="checkbox"> ์ด๋ฏธ์ง€/๋„ํ˜• ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ ๋ฐ ํŽธ์ง‘
  • <input checked="" disabled="" type="checkbox"> ์ˆ˜์ • ๊ฐ€๋Šฅํ•œ ํ…์ŠคํŠธ ์ปดํฌ๋„ŒํŠธ ์ œ๊ณต
  • <input checked="" disabled="" type="checkbox"> ์ปดํฌ๋„ŒํŠธ ๋ณต์ œ/์‚ญ์ œ
  • <input checked="" disabled="" type="checkbox"> ์‹คํ–‰ ์ทจ์†Œ/๋‹ค์‹œ ์‹คํ–‰
  • <input checked="" disabled="" type="checkbox"> ๋“œ๋กœ์ž‰
  • <input checked="" disabled="" type="checkbox"> ์ด๋ฏธ์ง€ ์ €์žฅ
  • <input checked="" disabled="" type="checkbox"> ์บ”๋ฒ„์Šค ํ™•๋Œ€ ๋ฐ ์ถ•์†Œ
  • <input checked="" disabled="" type="checkbox"> Z-index ์กฐ์ •
  • <input checked="" disabled="" type="checkbox"> ์ด๋ฏธ์ง€ ์ €์žฅ
  • <input checked="" disabled="" type="checkbox"> ์ง๋ ฌํ™”๋ฅผ ์ด์šฉํ•œ ์ˆ˜์ • ๋‚ด์—ญ ์ €์žฅ ๋ฐ ๋ณต์› ๊ธฐ๋Šฅ

Motivation

์ง์ ‘ ์ œ์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ๊ฐœ๋ฐœํ–ˆ์Šต๋‹ˆ๋‹ค.

Concept

  • ์ถ”์ƒํ™”
  • ์ƒํƒœ๊ด€๋ฆฌ
  • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

Architecture

๋ณธ ํ”„๋กœ์ ํŠธ์˜ ์•„ํ‚คํ…์ฒ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ตฌ์กฐ๋„

  • Shapes Layer: ์บ”๋ฒ„์Šค์— ๊ทธ๋ ค์ง€๋Š” ๋ชจ๋“  ๋„ํ˜•, ์‚ฌ์šฉ์ž ์ƒํƒœ ๋“ฑ์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์บ”๋ฒ„์Šค์™€ ํŒจ๋„, ํˆด๋ฐ” ์‚ฌ์ด์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ์ค‘์žฌํ•ฉ๋‹ˆ๋‹ค.
    • Snapshot: ํŠน์ •ํ•œ ์‚ฌ์šฉ์ž ์•ก์…˜(๋„ํ˜• ์ƒ์„ฑ, ์ด๋™, ์Šคํƒ€์ผ ์ˆ˜์ • ๋“ฑ)์ด ๋ฐœ์ƒํ•˜์—ฌ ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ์ €์žฅํ•ด์•ผ ํ•  ๊ฒฝ์šฐ, ํ˜„์žฌ ๋„ํ˜•์„ ์Šค๋ƒ…์ƒท์œผ๋กœ ์ €์žฅํ•˜๊ณ  ํžˆ์Šคํ† ๋ฆฌ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • History Layer: ์ €์žฅ๋œ ์Šค๋ƒ…์ƒท ๋ฐฐ์—ด์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์‹คํ–‰ ์ทจ์†Œ ๋ฐ ๋‹ค์‹œ ์‹คํ–‰ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.
  • Canvas Layer: Shapes Layer์— ์ €์žฅ๋œ ๋„ํ˜•๋“ค์„ ์‹ค์ œ 2D ๊ทธ๋ž˜ํ”ฝ์œผ๋กœ ํ‘œํ˜„ํ•˜๊ณ , ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ์ž…๋ ฅ๋ฐ›์€ ์ƒํ˜ธ์ž‘์šฉ์„ Shapes Layer์— ๋„˜๊ฒจ์ค๋‹ˆ๋‹ค.
  • Toolbar Layer: ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ์„ ๋ช…์‹œ์ ์œผ๋กœ ์ž…๋ ฅ๋ฐ›๋Š” ์˜์—ญ์ž…๋‹ˆ๋‹ค.
  • Panel Layer: ํ˜„์žฌ ์„ ํƒ๋œ ๋„ํ˜•์˜ ์†์„ฑ์„ ํ‘œ์‹œํ•˜๋Š” ์˜์—ญ์ž…๋‹ˆ๋‹ค.

Features

๋ณธ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜•ํƒœ๋กœ ํŒจํ‚ค์ง€ ๋ฆด๋ฆฌ์Šค

๋ฐ๋ชจ ํ”„๋กœ์ ํŠธ ํ™•์ธ์„ ์œ„ํ•ด ํ˜„์žฌ๊นŒ์ง€์˜ ๊ฐœ๋ฐœ ์‚ฌํ•ญ์„ node.js ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €์ธ NPM์— ๋ฐฐํฌํ•œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ„ฐ๋ฏธ๋„์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ์„ค์น˜๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

# for this package
$ npm install react-konva-image-editor

# for peer dependencies
$ npm install react react-dom

ํ˜ธ์ŠคํŠธ ์ธก์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// App.js
import { Editor } from 'react-konva-image-editor';

return (
  <Editor />
);

ํ˜ธ์ŠคํŠธ ์˜ต์…˜ ์ œ๊ณต

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ํ˜ธ์ŠคํŠธ์—์„œ ์—๋””ํ„ฐ ๋ ˆ์ด์•„์›ƒ์— ๋Œ€ํ•œ ์˜ต์…˜๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const props = {
  width = window.innerHeight, // Number, ๋ช…์‹œ์ ์œผ๋กœ ๋„ˆ๋น„ ์„ค์ •
  height = 500, // Number, ๋ช…์‹œ์ ์œผ๋กœ ๋†’์ด ์„ค์ •
  responsive = false, // Boolean, ๋ฐ˜์‘ํ˜• ์„ค์ •
  aspectRatio = 1, // Number, ๋ฐ˜์‘ํ˜• ์„ค์ • ์‹œ ๋„ˆ๋น„์™€ ๋†’์ด ๋น„์œจ ์„ค์ •
}

return (
  <Editor {...props} />
);

์ด๋ฏธ์ง€/๋„ํ˜• ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ ๋ฐ ํŽธ์ง‘

์บ”๋ฒ„์Šค์— ์ด๋ฏธ์ง€์™€ ๋„ํ˜• ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๋„ํ˜•์€ ๋“œ๋ž˜๊ทธ ๊ฐ€๋Šฅํ•˜๋ฉฐ(Draggable), ์ž์ฒด์ ์œผ๋กœ ํšŒ์ „, ๋ฆฌ์‚ฌ์ด์ง•์ด ๊ฐ€๋Šฅ(Transformable)ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€ ๋ฐ ๋„ํ˜• ์ธ์Šคํ„ด์Šค๋Š” Shape Layer์—์„œ ๊ด€๋ฆฌ๋˜๋ฉฐ, ๊ฐ ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•œ ์†์„ฑ ์ •์˜๋Š” components ํด๋”์— ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ์—๋Š” ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ Base64๋กœ ์ธ์ฝ”๋”ฉํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์‹คํ–‰ ์ทจ์†Œ/๋‹ค์‹œ ์‹คํ–‰

์‹คํ–‰ ์ทจ์†Œ์™€ ๋‹ค์‹œ ์‹คํ–‰ ๊ธฐ๋Šฅ์„ ์œ„ํ•ด ๋ฉ”๋ฉ˜ํ†  ํŒจํ„ด์„ ์ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฉ”๋ฉ˜ํ†  ํŒจํ„ด์€ ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ์ €์žฅํ•˜๋Š” Caretaker ์—ญํ• , ๊ทธ๋ฆฌ๊ณ  ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ธ๋ฑ์Šค๋ฅผ ๋„์›Œ์ฃผ๋Š” Originator ์—ญํ• ์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ Caretaker ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์ด History Layer์ž…๋‹ˆ๋‹ค. ๋„ํ˜•์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ(๋“œ๋ž˜๊ทธ, ํšŒ์ „, ๋ฆฌ์‚ฌ์ด์ง• ๋“ฑ)์ด ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค History Layer๋Š” ํ˜„์žฌ Shapes Layer์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์Šค๋ƒ…์ƒท์„ ์ƒ์„ฑํ•˜๊ณ  ๋ฐฐ์—ด๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

History Layer์—๋Š” ํŠน์ • ์Šค๋ƒ…์ƒท์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ธ๋ฑ์Šค๊ฐ€ ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์‹คํ–‰ ์ทจ์†Œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ์—๋Š” ์ธ๋ฑ์Šค๋ฅผ 1๋งŒํผ ๊ฐ์†Œ์‹œํ‚ค๋ฉฐ, ๋‹ค์‹œ ์‹คํ–‰ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ์—๋Š” ์ธ๋ฑ์Šค๋ฅผ 1๋งŒํผ ์ฆ๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค.

Shapes Layer๋Š” ํ˜„์žฌ History Layer์—์„œ ๊ฐ€๋ฆฌํ‚ค๋Š” ์Šค๋ƒ…์ƒท์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. Canvas Layer๋Š” Shapes Layer์˜ ์ธ์Šคํ„ด์Šค ๋ฐฐ์—ด์— ์ข…์†์ ์ด๊ธฐ ๋•Œ๋ฌธ์—, ์ €์žฅ๋œ ์ธ์Šคํ„ด์Šค๋ฅผ ์บ”๋ฒ„์Šค์— ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

๋“œ๋กœ์ž‰

๋“œ๋กœ์ž‰์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ๊ณผ ๋™์ผํ•œ ์ž…๋ ฅ์„ ๋ฐ›์ง€๋งŒ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํˆด๋ฐ”์—์„œ ๋“œ๋กœ์ž‰ ๋ชจ๋“œ๋ฅผ ์„ ํƒํ•˜๊ฒŒ ๋˜๋ฉด, ์บ”๋ฒ„์Šค์— ์žˆ๋Š” ๋„ํ˜•๋“ค์€ ๋” ์ด์ƒ ๋“œ๋ž˜๊ทธ ๊ฐ€๋Šฅํ•˜์ง€ ์•Š๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋„ํ˜• ์œ„์—์„œ ๋“œ๋กœ์ž‰์„ ์‹œ์ž‘ํ–ˆ์„ ๋•Œ, ๋„ํ˜•์ด ๋“œ๋ž˜๊ทธ ๋˜๋Š” ํ˜„์ƒ์„ ๋ง‰๊ธฐ ์œ„ํ•ด์„œ์ž…๋‹ˆ๋‹ค.

๋งˆ์šฐ์Šค ์ปค์„œ๋ฅผ ๋ˆ„๋ฅด๋ฉด onmousedown ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด๋•Œ x, y ์ขŒํ‘œ๋ฅผ ๊ตฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด ์ขŒํ‘œ๋ฅผ ์ด์‚ฐ์ ์œผ๋กœ ๋ง๋ถ™์ด๋ฉด์„œ ๋ผ์ธ ์ปดํฌ๋„ŒํŠธ์˜ ๊ฒฝ๋กœ๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ผ์ธ ์ปดํฌ๋„ŒํŠธ ์—ญ์‹œ ๋„ํ˜• ์ธ์Šคํ„ด์Šค๋กœ ์ทจ๊ธ‰๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋“œ๋ž˜๊ทธ์™€ ๋ณ€ํ™˜์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋งˆ์šฐ์Šค๋ฅผ ๋–ผ๊ธฐ ์ „๊นŒ์ง€ ๋ผ์ธ ์ปดํฌ๋„ŒํŠธ๋Š” ์•„์ง ์ƒ์„ฑ๋œ ์ƒํƒœ๊ฐ€ ์•„๋‹ˆ์ง€๋งŒ, ํ˜„์žฌ๊นŒ์ง€์˜ ๊ฒฝ๋กœ๋ฅผ ์บ”๋ฒ„์Šค์— ํ‘œ์‹œํ•ด์ฃผ์–ด์•ผ ํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋งˆ์šฐ์Šค๋ฅผ ๋–ผ๊ธฐ ์ „๊นŒ์ง€ ์ขŒํ‘œ ๋ฐฐ์—ด์„ ์ž„์‹œ๋กœ ์ €์žฅํ•˜๊ณ , ๋งˆ์šฐ์Šค๋ฅผ ๋—„ ๋•Œ ์ €์žฅ๋œ ์ขŒํ‘œ ๋ฐฐ์—ด์„ ์ด์šฉํ•ด Shape Layer์— ์ƒˆ ๋ผ์ธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ˆ˜์ • ๊ฐ€๋Šฅํ•œ ํ…์ŠคํŠธ ์ปดํฌ๋„ŒํŠธ ์ œ๊ณต

HTML5 ์ŠคํŽ™์— ๋”ฐ๋ฅด๋ฉด, ์บ”๋ฒ„์Šค์—์„œ ํ…์ŠคํŠธ๋ฅผ ๋ Œ๋”ํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ์บ”๋ฒ„์Šค ๋‚ด์—์„œ ์ž…๋ ฅ๊ฐ’์„ ์ง์ ‘ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ธํ’‹(input) ํ˜•ํƒœ๋กœ๋Š” ์ œ๊ณต๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•ด๋‹น ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค๋ฉด Canvas API๋ฅผ ์ ์ ˆํžˆ ์šฐํšŒํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ˆ˜์ • ๊ฐ€๋Šฅํ•œ ํ…์ŠคํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” Canvas API์™€ ์™ธ๋ถ€ DOM ์—˜๋ฆฌ๋จผํŠธ ๊ฐ„ ์Šคํƒ€์ผ ๋ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋™๊ธฐํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค. ์šฐ์„  ์บ”๋ฒ„์Šค์— ํ…์ŠคํŠธ๋ฅผ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋Š” ํ…์ŠคํŠธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ์—ญ์‹œ ๋„ํ˜• ์ธ์Šคํ„ด์Šค๋กœ ์ทจ๊ธ‰๋˜๋ฏ€๋กœ ๋“œ๋ž˜๊ทธ์™€ ๋ณ€ํ™˜์ด ๊ฐ€๋Šฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ ํ…์ŠคํŠธ ์ปดํฌ๋„ŒํŠธ์— ๋”๋ธ” ํด๋ฆญ์ด๋‚˜ <kbd>enter</kbd>ํ‚ค ๋“ฑ์˜ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ํ•ด๋‹น ์œ„์น˜์— <textarea> ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ ์บ”๋ฒ„์Šค์˜ ์คŒ, ํ…์ŠคํŠธ ์ปดํฌ๋„ŒํŠธ์˜ ํšŒ์ „, ์ค„๋ฐ”๊ฟˆ์„ ๊ณ ๋ คํ•˜์—ฌ ์–ด์ƒ‰ํ•จ์ด ์—†๋„๋ก ์Šคํƒ€์ผ์„ ์ ์ ˆํžˆ ์กฐ์ •ํ•ด์ค๋‹ˆ๋‹ค.

<kbd>enter</kbd>ํ‚ค ์ž…๋ ฅ ์‹œ ๊ฐ’์„ ์ €์žฅํ•˜๊ณ , <kbd>shift</kbd> + <kbd>enter</kbd>ํ‚ค๋ฅผ ๋ˆ„๋ฅผ ๋• ์ค„๋ฐ”๊ฟˆ์ด ์ผ์–ด๋‚˜์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํฌ์ปค์Šค๋ฅผ ์žƒ์—ˆ์„ ๋•Œ์—๋Š” ์ž๋™์œผ๋กœ <textarea> ๊ฐ€ ์‚ญ์ œ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์บ”๋ฒ„์Šค ํ™•๋Œ€ ๋ฐ ์ถ•์†Œ

์คŒ ๋ฐฐ์œจ์„ ์ง€์ •ํ•˜๋Š” ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ณ , ์ด๋ฅผ ์บ”๋ฒ„์Šค ๋ ˆ์ด์–ด์— ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

Z-index ์กฐ์ •

๋„ํ˜• ๊ฐ„ z-index ์กฐ์ •์€ Shape Layer์˜ ๋„ํ˜• ์ธ์Šคํ„ด์Šค ๋ฐฐ์—ด์˜ ์ˆœ์„œ๋ฅผ ๋ฐ”๊พธ๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€ ์ €์žฅ ๋ฐ ์ง๋ ฌํ™” ๊ธฐ๋ฐ˜ ์ €์žฅ ๋ฐ ๋ณต์› ๊ธฐ๋Šฅ

์ด๋ฏธ์ง€ ์ €์žฅ ๊ธฐ๋Šฅ์€ ํ˜„์žฌ ๋ Œ๋”๋œ ํ™”๋ฉด์„ ์ด๋ฏธ์ง€ ํŒŒ์ผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” Canvas API์˜ toDataURL() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋„ํ˜•์„ ์ธ์Šคํ„ด์Šคํ™”ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ํ˜„์žฌ๊นŒ์ง€์˜ ํŽธ์ง‘ ๋‚ด์—ญ์ด ๋‹ด๊ธด Shape Layer์˜ ๋„ํ˜• ์ธ์Šคํ„ด์Šค ๋ฐฐ์—ด์„ ์ง๋ ฌํ™”ํ•˜์—ฌ JSON ํŒŒ์ผ๋กœ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ดํ›„ JSON ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ, Shape Layer ๋ฐฐ์—ด์— ์ ์ ˆํžˆ ๋งค์นญ์‹œํ‚ค๋Š” ๊ธฐ๋Šฅ๊นŒ์ง€ ๊ตฌํ˜„๋œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.

Conclusion & Limitations

  • HTML5์˜ Canvas API๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€ ์—๋””ํ„ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ œ์ž‘ํ•˜๊ณ , ๊ฐ ๊ธฐ๋Šฅ๋“ค์˜ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•๊ณผ ํ•œ๊ณ„์ ์— ๋Œ€ํ•ด ์—ฐ๊ตฌํ•˜๊ณ  ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๊ณต๊ฐœํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ ˆ๋ฒจ์—์„œ ์ ํ•ฉํ•œ ๊ณ ์ˆ˜์ค€์˜ ์ถ”์ƒํ™”๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜๊ณ , ์ƒํ™ฉ์— ๋งž๋Š” ๋””์ž์ธ ํŒจํ„ด์„ ์‚ฌ์šฉํ•จ์œผ๋กœ์„œ ์ด๋ฏธ์ง€ ์—๋””ํ„ฐ์˜ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  • Canvas API์˜ ๋ฒ”์œ„๋ฅผ ๋„˜์–ด์„œ๋Š” ์š”๊ตฌ์‚ฌํ•ญ์— ๋Œ€ํ•ด์„œ๋Š” ๊ธฐ์ˆ ์ ์œผ๋กœ ์šฐํšŒํ•˜๋ฉด์„œ๋„ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ํ•ด์น˜์ง€ ์•Š์•˜๋‹ค๋Š” ์ ์—์„œ ์˜์˜๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ๋‹ค๋งŒ ์‹œ๊ฐ„์  ์—ฌ์œ  ์ƒ ๊ธฐ๋Šฅ์„ฑ ๋‹ค์–‘ํ™” ๋ฐ ์‚ฌ์šฉ์ž ํŽธ์˜๋ฅผ ์œ„ํ•œ ๋ถ€๊ฐ€์ ์ธ ๊ธฐ๋Šฅ๋“ค(ํ‚ค๋ณด๋“œ ๋‹จ์ถ•ํ‚ค ์ง€์› ๋“ฑ)์— ๋Œ€ํ•ด์„œ๋Š” ๊ตฌํ˜„์ด ์™„๋ฃŒ๋˜์ง€ ์•Š์€ ๋ถ€๋ถ„์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋˜ํ•œ ๋ณต์žกํ•œ ์ƒํƒœ ๊ด€๋ฆฌ ๋ฐ UI ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ ์šฉ์œผ๋กœ ์ธํ•ด ์ฝ”๋“œ ๊ฐ€๋…์„ฑ ๋ฐ ์„ฑ๋Šฅ ์ตœ์ ํ™” ๋ฉด์—์„œ ๋‹ค์†Œ ๋ถ€์กฑํ•œ ๋ถ€๋ถ„์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ–ฅํ›„ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ๋ฐ ์œ ์ง€๋ณด์ˆ˜๋ฅผ ํ†ตํ•ด ์„ฑ๋Šฅ๊ณผ ํŽธ์˜๋ฅผ ๊ฐœ์„ ํ•ด ๋‚˜๊ฐˆ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

References

ํ”„๋กœ์ ํŠธ ๊ฐœ๋ฐœ ์ค‘ ์ฐธ๊ณ ํ•œ ์ž๋ฃŒ์ž…๋‹ˆ๋‹ค.

Papers

Others

๋ณด๊ณ ์„œ

ํ•ด๋‹น ๋…ผ๋ฌธ์€ 2021 ํ•œ๊ตญ์ •๋ณด๊ณผํ•™ํšŒ ํ•™๋ถ€์ƒ ๋…ผ๋ฌธ๊ฒฝ์ง„๋Œ€ํšŒ ๋ณธ์„  ์ง„์ถœ์ž‘์ž…๋‹ˆ๋‹ค.