whatisthis?

Painting App - (app.js) 해결중 본문

PRACTICE/SELF

Painting App - (app.js) 해결중

thisisyjin 2022. 2. 3. 11:50

 

 

GitHub - thisisyjin/paintJS: Painting Board made with vanila JS (ref. NomadCoder)

Painting Board made with vanila JS (ref. NomadCoder) - GitHub - thisisyjin/paintJS: Painting Board made with vanila JS (ref. NomadCoder)

github.com

 

** 깃헙에 업로드 해두었다.

 

 

 

 

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>PaintJS</title>
</head>
<body>
    <canvas id="jsCanvas" class="canvas"></canvas>
    <div class="controls">
        <div class="controls__range">
            <input type="range" id="jsRange" min="0.1" max="5.0" value="2.5" step="0.1"/>
        </div>
        <div class="controls__btns">
            <button id="jsMode">Fill</button>
            <button id="jsSave">Save</button>
        </div>
        <div class="controls__colors" id='jsColors'>
            <div class="controls__color jsColors" style="background-color: #2c2c2c;"></div>
            <div class="controls__color jsColors" style="background-color: #fff;"></div>
            <div class="controls__color jsColors" style="background-color: #FF3B30;"></div>
            <div class="controls__color jsColors" style="background-color: #ff9500;"></div>
            <div class="controls__color jsColors" style="background-color: #FFCC00;"></div>
            <div class="controls__color jsColors" style="background-color: #4CD963;"></div>
            <div class="controls__color jsColors" style="background-color: #5AC8FA;"></div>
            <div class="controls__color jsColors" style="background-color: #0579FF;"></div>
            <div class="controls__color jsColors" style="background-color: #5856D6;"></div>
        </div>
    </div>
    <script src="app.js"></script>
</body>
</html>

style.css

@import "./reset.css";

body {
    background-color: #f6f9fc;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 50px 0px;
}


.canvas {
    width: 700px;
    height: 700px;
    background-color: white;
    border-radius: 15px;
    box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);

}

.controls {
    margin-top: 80px;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.controls .controls__btns {   /*  .controls 의 하위요소를 .controls__btns로 */
    margin-bottom: 30px;
}

.controls__btns button {
    all: unset;        /* 그냥 텍스트처럼 보임 */
    cursor: pointer;
    background-color: white;
    padding: 5px 0px;
    width: 80px;
    text-align: center;
    border-radius: 10px;
    box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
    border: 2px solid rgba(0, 0, 0, 0.2);
    color: rgba(0, 0, 0, 0.7);
    text-transform: uppercase;
    font-weight: 600;
    font-size: 12px;
}

.controls__btns button:active {         /* 가상클래스 ㅡ active시 변형 */
    transform: scale(0.98);
}

.controls .controls__colors {
    display: flex;
}

.controls__colors .controls__color {
    width: 50px;
    height: 50px;
    box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
    border-radius: 25px; 
    cursor: pointer;
    margin-left: 2px;
}

.controls .controls__range {
    margin-bottom: 30px;
}

app.js

const canvas = document.getElementById("jsCanvas");
const colors = document.getElementsByClassName("jsColors");
const range = document.getElementById("jsRange");
const mode = document.getElementById("jsMode");
const save = document.getElementById("jsSave");
const ctx = canvas.getContext("2d");

const INITIAL_COLOR = "#2c2c2c";

canvas.width = document.getElementsByClassName("canvas")[0].offsetWidth;
canvas.height = document.getElementsByClassName("canvas")[0].offsetHeight;

// Default
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = INITIAL_COLOR;
ctx.fillStyle  = INITIAL_COLOR;
ctx.lineWidth = 2.5;

let filling = false;
let painting = 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);
        // console.log('creating path in', x, y);
    } else {
        ctx.lineTo(x, y);
        ctx.stroke();
        // console.log('creating line in', x, y);
    }
}

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

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

function fillColor(event) {
    if(filling) {
        ctx.fillRect(0, 0, canvas.width, canvas.height);
    }
}

function handleModeClick(event) { 
    if(filling === true) {        // filling 모드이면
        filling = false;           
        mode.innerText = "fill"
    } else {
        filling = true;
        mode.innerText = "paint"    // paint 모드이면 ㅡ 맨처음
    }
}

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

function handleSaveClick(event) {
    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', fillColor);
    canvas.addEventListener('contextmenu', handleCM);
}

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

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

if (mode) {
    mode.addEventListener('click', handleModeClick);
}

if (save) {
    save.addEventListener('click', handleSaveClick);
}

 

 

 

 

 

 

 

 


 

 

 

 

🔻🔻 실패는 성공의 어머니(...) 를 보고싶은 분들만

 

 

 

 

 

 

수정하고 싶은 것

 

- 파일명을 사용자가 직접 입력 가능하도록

>> prompt()를 입력할지

 

- prompt로 입력하면 모달창에 스타일을 입히기 힘들고

- 페이지가 일시정지 되기 때문에 잘 쓰지 않는다.

 

 

 

 

1. 첫번째로 생각난 것은

window.open으로 팝업창을 만들고

이름을 입력받아app.js에서 그 이름값으로 저장하는 것이다.

 

처음엔 popup.html과 popup.js 를 추가하여popup.js에서

const form = document.getElementById('name-form');
const input = document.getElementById('name-input');

function onFormSubmit(event) {
    const fileName = input.value;
    export { fileName }
    window.close();
}
        
form.addEventListener('submit', onFormSubmit);

위와 같이export를 해보려했는데(js파일에서 - 다른 js파일로 변수 값 옮기는?)

 

모듈 밖에선 import할 수 없다고 뜬다.

 

export에 대해서 잘 이해를 못하겠어서나중에 시도해보는거로 하고..

 

 


 

 

 

input type text를 사용하면처음엔 그 창이 안보이게 하고,save를 눌렀을 때새 창으로 뜨게 해야할듯.

 

 

>> window.open으로 팝업창 뜨게 해도 될듯?

 

function handleSaveClick(event) {
    const image = canvas.toDataURL("image/png");
    const link = document.createElement("a");
    const popup = window.open('popup.html', 'FileName','width=400,height=200');
    const fileName = popup.document.getElementById('name-input').value;
    link.href = image;
    link.download = fileName;
    link.click();
}

우선 이렇게 한다음에popup.html은

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Save File</title>
</head>
<body>
    <h1>Save Image File</h1>
    <form id="name-form" action="#">
        <input id="name-input" required type="text" placeholder="file name" />
        <button id="name-btn">save</button>
    </form>

    <script src="popup.js"></script>

</body>
</html>

위와 같이 작성했는데,

이런 오류가 발생한다.

 

window.open() 동작을 이용해서

팝업을 띄우고,

window.open()메서드 자체를 popup이라는 변수로 저장하여

getElementById로 가져오려했는데, 동작이 안된다.

 

const form = document.getElementById('name-form');

function onFormSubmit(event) {
    event.preventDefault();
    window.close();
}
        
form.addEventListener('submit', onFormSubmit);

까먹고 있던 event.preventDefault를 해봤다.

 

역시나 해결이 안된다.

 

import- export로 해결하는 것과

window.open()을 통해 연 팝업창에서 정보를 가져오는 것에 대해

알아보고 해결하도록 하겠다.ㅠㅠ