์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- ์ฝ๋ฉ์ผ๊ธฐ
- ๋ฐ๋๋ผ JS๋ก ํฌ๋กฌ ์ฑ ๋ง๋ค๊ธฐ
- canvas js
- canvas image
- ๋ ธ๋ง๋์ฝ๋
- ์น ๋ธ๋ผ์ฐ์ ๊ตฌ์กฐ
- next.js
- ์ฝ์ฝ์ํก ํด๋ก ์ฝ๋ฉ
- ๋ ธ๋ง๋ ์ฝ๋
- clone coding
- axios-mock-adapte
- typescript
- canvas
- tanstack-query
- queryprovider
- ๋ฐ๋๋ผ JS๋ก ๊ทธ๋ฆผํ ๋ง๋ค๊ธฐ
- tailwindcss
- ํ๋ก ํธ์๋
- JS
- ์น ๋ธ๋ผ์ฐ์ ๋ ๋๋ง
- HTML ํ์ผ๊ตฌ์กฐ
- HTML
- negative margin
- react
- JAVA Script
- ์ฝ๋ฉ๋ ํ
- CSS
- javascript
- jest
- ์ํ์ฝ๋ฉ
- Today
- Total
Coding Archive
๋ ธ๋ง๋ ์ฝ๋ - ๋ฐ๋๋ผ JS๋ก ๊ทธ๋ฆผํ ๋ง๋ค๊ธฐ ๋ณธ๋ฌธ
๋ ธ๋ง๋ ์ฝ๋ - ๋ฐ๋๋ผ JS๋ก ๊ทธ๋ฆผํ ๋ง๋ค๊ธฐ
์ฝ๋ฑ์ด 2022. 7. 22. 01:54#1 SETUP + STYLES
0. Project Setup
github ๊ณ์ ์ ๋ค์ด๊ฐ์ ์๋ก์ด repository๋ฅผ ๋ง๋ ๋ค.
์ด๋ initialize this repository with์์ "Add a README file"์ ์ฒดํฌ, gitignore์ "node"๋ฃ์ด์ค๋ค.
(Add .gitignore์์ .gitignore template: node๋ก ๋ฐ๊ฟ์ค๋ค.)
์ ์ฅํ ๊ณต๊ฐ์ ํฐ๋ฏธ๋์์ ์ด์ด์ git clone https://github.com/seoye0ng/paint-js(์์ฑ๋ repository ์ฃผ์)๋ฅผ ์ ๋ ฅํ๊ณ ๊น ํด๋ก ํ๋ฉด ๋๋ค. → ๋ด๊ฐ ์ ์ฅํ ๊ณต๊ฐ์ paint-jsํ์ผ์ด ์์ฑ๋๋ค.
ํ์ผ์ vsc์์ ์ด๊ณ html, css, js๋ฌธ์๋ฅผ ๋ง๋ค์ด ์ค๋ค.
1. Styles part One
html
(canvas์ ํ๋ ํธ ๋ง๋ค๊ธฐ)
<!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="styles.css" />
<title>PaintJS</title>
</head>
<body>
<canvas id="jsCanvas" class="canvas"></canvas>
<div class="controls">
<div class="controls__colors" id="jsColors">
<div class="controls__color" style="background-color: #2c2c2c"></div>
<div class="controls__color" style="background-color: white"></div>
<div class="controls__color" style="background-color: #ff3b30"></div>
<div class="controls__color" style="background-color: #ff9500"></div>
<div class="controls__color" style="background-color: #ffcc00"></div>
<div class="controls__color" style="background-color: #4cd963"></div>
<div class="controls__color" style="background-color: #5ac8fa"></div>
<div class="controls__color" style="background-color: #0579ff"></div>
<div class="controls__color" style="background-color: #5856d6"></div>
<!--๋ณด๊ธฐ์ฝ๊ฒ html์์ background-color๋ฅผ ์ง์ ํด์ค๋ค-->
</div>
</div>
<script src="app.js"></script>
</body>
</html>
reset.cssํ์ผ์ ์ถ๊ฐํด ๋ธ๋ผ์ฐ์ ์ ๋ํดํธ ๊ฐ์ผ๋ก ์ค์ ๋ ๋์์ธ์ ๋ชจ๋ ์์ ์ค๋ค.
css
@import "reset.css";
body {
background-color: #f6f9fc;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
display: flex;
flex-direction: column;
align-items: center;
padding-top: 80px;
}
.canvas {
width: 800px;
height: 800px;
background-color: white;
border-radius: 3%;
box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
}
.controls {
margin-top: 80px;
}
.controls .controls__colors {
display: flex;
}
.controls__colors .controls__color {
width: 50px;
height: 50px;
border-radius: 100%;
box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
cursor: pointer;
margin: 0 5px;
}
2. Styles part Two
html
(๋ธ๋ฌ์ฌ ๊ตต๊ธฐ ์กฐ์ ๋ฐ์ ์ ์ฑ์ฐ๊ธฐ, ์ ์ฅํ๊ธฐ ๋ฒํผ ๋ง๋ค๊ธฐ)
<div class="controls">
<div class="controls__range">
<input
type="range"
id="jsRange"
min="0.1"
max="5"
value="2.5"
step="0.1"
/>
<!--์ต์ 0.1๊น์ง/ ์ต๋ 5๊น์ง/ ๊ธฐ๋ณธ๊ฐ์ 2.5/ ์กฐ์ ์ 0.1์ฉ-->
</div>
<div class="controls__btns">
<button id="jsMode">Fill</button>
<button id="jsSave">Save</button>
</div>
css
.controls {
margin-top: 80px;
display: flex;
flex-direction: column;
align-items: center;
}
.controls .controls__range {
margin-bottom: 30px;
}
.controls__btns {
margin-bottom: 30px;
}
.controls__btns button {
all: unset;
background-color: white;
padding: 5px 0;
width: 80px;
text-align: center;
border-radius: 5px;
box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08);
border: 1.5px solid rgba(0, 0, 0, 0.2);
color: rgba(0, 0, 0, 0.7);
font-size: 12px;
font-weight: 800;
text-transform: uppercase;
cursor: pointer;
}
.controls__btns button:active {
transform: scale(0.96);
}
#2 PAINTJS
0. Canvas Events
js
const canvas = document.getElementById(jsCanvas);
let painting = false;
//ํด๋ฆญํ๊ธฐ ์ ์๋ ํ์ธํ
๋์ง ์๊ธฐ ๋๋ฌธ์ false๋ก ์ค์
function stopPainting() {
painting = false;
}
function onMouseMove(event) {
const x = event.offsetX;
const y = event.offsetY;
}
function onMouseDown(event) {
painting = true;
}
//onMouseDownํ์ ๊ฒฝ์ฐ์๋ง painting์ด true๊ฐ ๋จ
function onMouseUp(event) {
stopPainting();
}
if (canvas) {
canvas.addEventListener("mousemove", onMouseMove);
canvas.addEventListener("mousedown", onMouseDown); //mousedown์ ๋ง์ฐ์ค๋ฅผ ํด๋ฆญํ์ ๋๋ฅผ ์๋ฏธ
canvas.addEventListener("mouseup", onMouseUp); //mouseup์ ํด๋ฆญ์ ๋ผ์์ ๋๋ฅผ ์๋ฏธ
canvas.addEventListener("mouseleave", stopPainting); //๋ง์ฐ์ค๊ฐ canvas์์ mouseleave๋๋ฉด painting์ด false๊ฐ ๋๋๋ก ์ค์
}
offset์ ์บ๋ฒ์ค ๋ถ๋ถ๊ณผ ๊ด๋ จ ์๋ ๊ฐ์ด๋ค.
clientX, Y๋ ์๋์ฐ ์ ์ฒด์ ๋ฒ์ ๋ด์์ ๋ง์ฐ์ค ์์น ๊ฐ์ ๋ํ๋ด๋๋ฐ,
์ฌ๊ธฐ์๋ ์๋์ฐ ์ ์ฒด ๋ฒ์ ๋ด์ ์ขํ๋ฅผ ์๊ณ ์ถ์ ๊ฒ ์๋๋ผ ์บ๋ฒ์ค ๋ด์์์ ์ขํ๋ง ์์ผ๋ฉด ๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ event ์์ offsetX, Y๋ฅผ ์ฌ์ฉํ๋ค.
1. 2D Context
js
const canvas = document.getElementById(jsCanvas);
const ctx = canvas.getContext("2d");
ctx.strokeStyle = "#2c2c2c"; //์ฒซ ๋ฒ์งธ์(๊ฒ์ ์)์ผ๋ก ์์ํ๋๋ก ์ค์
ctx.lineWidth = 2.5; //๋๊ป๋ฅผ 2.5๋ก ์์ํ๋๋ก ์ค์
let painting = false;
function stopPaninting() {
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 onMouseDown(event) {
painting = true;
}
if (canvas) {
canvas.addEventListener("mousemove", onMouseMove);
canvas.addEventListener("mousedown", startPainting);
canvas.addEventListener("mouseup", stopPaninting);
canvas.addEventListener("mouseleave", stopPaninting);
}
canvas๋ context๋ฅผ ๊ฐ๊ณ ์๋ html ์์์ด๋ฉฐ, context๋ canvas ์์์ ํฝ์ ์ ๋ค๋ฃจ๋ ๊ฒ์ด๋ค.
const ctx = canvas.getContext('2d'); ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ด๊ฐ ํ ์ ์๋ context๋ ๋ชจ๋ ๊ฐ๊ฒ ๋๋ค.
ex)
ctx.lineWidth → context๋ก ๋ผ์ธ ๋๊ป๋ฅผ ์กฐ์ ํ ์ ์์
ctx.strokeRect → ์ฌ๊ฐํ์ ๊ทธ๋ฆด ์ ์์
ctx.fillRect → ์น ํด์ง ์ฌ๊ฐํ์ ๊ทธ๋ฆด ์ ์์
ctx.moveTo → context๋ฅผ ์ด๋๊ฐ ๋ค๋ฅธ ๊ณณ์ผ๋ก ์ฎ๊ธธ ์ ์์
ctx.lineTo →๋ค๋ฅธ ๊ณณ์ ๋ผ์ธ์ ๊ทธ๋ฆด ์ ์์
context๊ฐ ๊ฐ์ง ๊ฒ ์ค์ Path๋ ์๊ณ , Path๋ ๊ธฐ๋ณธ์ ์ธ ์ ์ด๋ค.
์ฐ๋ฆฌ๋ beginPath()๋ฅผ ์ฌ์ฉํด Path๋ก ์์ํ๊ณ , moveTo()๋ก Path๋ฅผ ์์ง์ด๊ณ , closePath()๋ก Path๋ฅผ ๋ซ์ ์ ์๋ค.
'๐ฅ๏ธ Clone Coding' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ ธ๋ง๋ ์ฝ๋ - ๋ฐ๋๋ผ JS๋ก ๊ทธ๋ฆผํ ๋ง๋ค๊ธฐ(2) (0) | 2022.07.23 |
---|---|
๋ ธ๋ง๋ ์ฝ๋ - ๋ฐ๋๋ผ JS๋ก ํฌ๋กฌ ์ฑ ๋ง๋ค๊ธฐ(10) (0) | 2022.06.19 |
๋ ธ๋ง๋ ์ฝ๋ - ๋ฐ๋๋ผ JS๋ก ํฌ๋กฌ ์ฑ ๋ง๋ค๊ธฐ(9) (0) | 2022.06.14 |
๋ ธ๋ง๋ ์ฝ๋ - ๋ฐ๋๋ผ JS๋ก ํฌ๋กฌ ์ฑ ๋ง๋ค๊ธฐ(8) (0) | 2022.06.13 |
๋ ธ๋ง๋ ์ฝ๋ - ๋ฐ๋๋ผ JS๋ก ํฌ๋กฌ ์ฑ ๋ง๋ค๊ธฐ(7) (0) | 2022.06.11 |