본문 바로가기
JavaScript/Paint JS

[JavaScript] #2.6 Saving the Image (#코딩공부)

by 함께 공부해요 2020. 4. 29.

https://youtu.be/xOxE40I75GM


<복습>

https://wook-2124.tistory.com/108

 

[JavaScript] #2.5 Filling Mode (#코딩공부)

https://youtu.be/2m_WnYeI1pA <복습> https://wook-2124.tistory.com/107 [JavaScript] #2.4 Brush Size (#코딩공부) https://youtu.be/j4cAIJutjVI <복습> https://wook-2124.tistory.com/105 [JavaScript] #2.3..

wook-2124.tistory.com

 

<준비물>

https://code.visualstudio.com/

 

Visual Studio Code - Code Editing. Redefined

Visual Studio Code is a code editor redefined and optimized for building and debugging modern web and cloud applications.  Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows.

code.visualstudio.com

 

<코드기록>

// mouse 오른쪽으로 "click"해서 나오는 "contextmenu"로 저장하는 것을 막음
function handleRightClick(event) {
  event.preventDefault();
}

if (canvas) {
  canvas.addEventListener("contextmenu", handleRightClick);
}


// SAVE button으로 저장하는 기능 만들기
<!-- HTML에서 button을 만들고 -->
 <button id="jsSave">Save</button>;
// JavaScript에서 button을 가져와서
const saveBtn = document.getElementById("jsSave");
// "click" event에 반응해서 handleSaveClick function을 실행함
if (saveBtn) {
  saveBtn.addEventListener("click", handleSaveClick);
}
// HTMLCanvasElement.toDataURL()
// 기본값이 PNG로 설정된 type parameter에 의해 
// 지정된 포맷의 이미지 표현을 포함한 data URL을 반환함
function handleSaveClick() {
  const image = canvas.toDataURL("image/png");
}


// href는 anchor("a") 태그의 attribute(속성)이 되고
// SAVE 버튼을 클릭하면 이 attribute는 browser에게
// 이 link로 가는 대신 URL(그림)을 다운로드 하라고 지시함
// href는 image(URL)이 되고, download는 다운로드한 파일의 이름을 표시함
function handleSaveClick() {
  const image = canvas.toDataURL("image/png");
  const link = document.createElement("a");
  link.href = image;
  link.download = "PaintJS";
  link.click();
}


// 최종 코드
const canvas = document.getElementById("jsCanvas");
const ctx = canvas.getContext("2d");
const colors = document.getElementsByClassName("jsColor");
const range = document.getElementById("jsRange");
const modeBtn = document.getElementById("jsMode");
const saveBtn = document.getElementById("jsSave");

const INITIAL_COLOR = "#2c2c2c";
const CANVAS_SIZE = 700;

canvas.width = CANVAS_SIZE;
canvas.height = CANVAS_SIZE;

ctx.fillStyle = "white";
ctx.fillRect(0, 0, CANVAS_SIZE, CANVAS_SIZE);
ctx.strokeStyle = "INITIAL_COLOR";
ctx.fillStyle = "INITIAL_COLOR";
ctx.lineWidth = 2.5;

let painting = false;
let filling = false;

function stopPainting() {
  painting = false;
}

function startPainting() {
  painting = true;
}

function onMouseMove(event) {
  const x = event.offsetX;
  const y = event.offsetY;
  if (!painting) {
    ctx.beginPath();
    ctx.moveTo(x, y);
  } else {
    ctx.lineTo(x, y);
    ctx.stroke();
  }
}

function handleColorClick(event) {
  const color = event.target.style.backgroundColor;
  ctx.strokeStyle = color;
  ctx.fillStyle = color;
}

function handleRangeChange(event) {
  const size = event.target.value;
  ctx.lineWidth = size;
}

function handleModeClick() {
  if (filling === true) {
    filling = false;
    modeBtn.innerText = "Fill";
  } else {
    filling = true;
    modeBtn.innerText = "Paint";
  }
}

function handleCanvasClick() {
  if (filling) {
    ctx.fillRect(0, 0, CANVAS_SIZE, CANVAS_SIZE);
  }
}

function handleRightClick(event) {
  event.preventDefault();
}

function handleSaveClick() {
  const image = canvas.toDataURL("image/png");
  const link = document.createElement("a");
  link.href = image;
  link.download = "PaintJS";
  link.click();
}

if (canvas) {
  canvas.addEventListener("mousemove", onMouseMove);
  canvas.addEventListener("mousedown", startPainting);
  canvas.addEventListener("mouseup", stopPainting);
  canvas.addEventListener("mouseleave", stopPainting);
  canvas.addEventListener("click", handleCanvasClick);
  canvas.addEventListener("contextmenu", handleRightClick);
}

Array.from(colors).forEach(color =>
  color.addEventListener("click", handleColorClick)
);

if (range) {
  range.addEventListener("input", handleRangeChange);
}

if (modeBtn) {
  modeBtn.addEventListener("click", handleModeClick);
}

if (saveBtn) {
  saveBtn.addEventListener("click", handleSaveClick);
}

1. contextmenu, preventDefault( )

canvas에서 mouse 오른쪽을 누르면 이미지를 다른 이름으로 저장할 수 있는 "contextmenu"가 나오는데 이것을 눌러 저장하면, canvas의 크기대로 저장된다. 이처럼 canvas에서는 pixel을 다뤄 image를 만들어주는 기능을 내장하고 있다.

 

canvas에서 "contextmenu" event가 발생하면 handleRightClick function을 실행하고, console로 출력해서 어떤 event인지 봤다.

 

handleRightClick function에 event.preventDefault()를 넣어주면 mouse의 오른쪽을 눌러도 "contextmenu" event가 발생하지 않는다.


2. SAVE Button으로 저장하기

HTML에서 button으로 id="jsSave"를 갖는 Save 버튼을 생성했다.

 

다음으로 MDN에서 HTMLCanvasElement.toDataURL()에 대해서 공부했다. 오른쪽 예제로 설명하면 canvas.toDataURL("image/jpeg")로 값을 설정한 것은, 기본값이 jpeg로 설정된 type parameter에 의해 지정된 포맷의 이미지 표현을 포함한 data URL을 반환하게 되는 것이다. 즉 jpeg image 파일로 저장이 되는 것이다.


3. href

href는 anchor("a") 태그의 attribute(속성)이 되고, SAVE Button을 "click"하면 이 attribute는 browser에게 link로 가는 대신 URL(그림)을 다운로드하라고 지시하게 된다. 즉 link.href = image로 href는 image(URL)을 반환한다.

 

그리고 link.download는 다운로드될 때의 파일명을 입력하면 된다.

 

console로 출력해보면, SAVE Button을 누르면 a(anchor) href attribute가 console에 출력되고, data로 image/jpeg를 갖는다.

 

기본값을 jpeg에서 png로 바꿔주고 SAVE Button을 누르면 저장된다.

 


 아직 끝나지 않은 코로나19 조심하세요!!

 

댓글