1. html에 canvas 태그 추가하기
<canvas width="150" height="150"></canvas>
(default width=300px height 150px)
2. JavaScript - getContext()메서드
캔버스의 드로잉 컨텍스트를 반환해줌
1) 사각형 그리기
fillRect(x, y, width, height) 채워진 사각형 그리기
strokeRect(x, y, width, height) 선으로 된 사각형 그리기
clearRect(x, y, width, height) 지정된 사각형 영역을 지움
2) 패스 그리기(Illustrator의 펜툴과 비슷)
beginPath() 새 경로를 만듦
closePath() 마지막 위치에서 시작 위치를 연결
stroke() 윤곽선 그리기
fill() 칠하기
moveTo(x, y) 지정된 위치에서 시작한다. (펜툴의 시작점)
lineTo(x, y) x, y좌표까지 선을 그린다. (다음 점)
3) 호(arc)그리기
arc(x, y, radius, startAngle, endAngle, anticlockwise)
라디안 각도를 이용, Math.PI * 2 ==> 360º (Math.PI = 180º)
4) 선과 면 스타일 지정
lineWidth 선의 두께를 지정
fillStyle 면색을 지정
strokeStyle 선색을 지정
lineCap 선의 끝점 모양을 결정
butt, round, square (default는 butt)
5) 이미지 적용
* 이미지 객체 만들기
const imgElem = document.createElement('img');
const imgElem = new Image();
* 캔버스에 이미지 그리기
ctx.drawImage(image, dx, dy, dWidth, dHeight)
6) 애니매이션 적용
window.requestAnimationFrame() - 비동기 함수
css의 transition으로 처리하기 어려운 애니메이션이나, html5의 canvas, SVG 등의 애니메이션 구현을 위하여 사용됨
모든 애니메이션을 직접 프레임 단위로 계산을 함
setInterval -> 스스로 반복해서 호출(o)
requestAnimationFrame() -> 스스로 반복해서 호출(x)
재귀적으로 window.requestAnimationFrame() 함수를 다시 호출해줘야 함
function frame() {
window.requestAnimationFrame(frame);
}
window.requestAnimationFrame(frame);
cancelAnimationFrame(변수명)
canvas01.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>Document</title>
<style>
canvas {
background-color: lightgray;
}
</style>
</head>
<body>
<canvas width="1000" height="600" id="canvas"></canvas> <!-- 도화지 -->
<script>
let canvas = document.querySelector('#canvas');
let ctx = canvas.getContext('2d');
// 면색상지정
ctx.fillStyle = 'green';
ctx.fillRect(100, 50, 100, 100); // x, y, width, height
ctx.strokeStyle = "red";
ctx.strokeRect(200, 200, 50, 50); // 테두리만
ctx.clearRect(100, 50, 50, 50); // 지우개 역할
</script>
</body>
</html>
canvas02-path.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>Document</title>
<style>
canvas {
background-color: lightcyan;
}
</style>
<script>
function draw() {
let canvas = document.querySelector('#canvas');
let ctx = canvas.getContext('2d');
// 패스를 시작(펜 도구 선택)
ctx.beginPath();
// 시작위치 - 처음 점 찍기
ctx.moveTo(70, 50);
// 선 그리기 - 다음 점 찍기
ctx.lineTo(150, 50);
// 선 그리기 - 다음 점 찍기
ctx.lineTo(150, 150);
// ctx.closePath();
// ctx.stroke();
ctx.fill();
ctx.fillStyle = 'red';
let num = 100;
for(let i = 0; i < 10; i++) {
ctx.fillRect(num+(i*80), 100, 50, 50);
}
}
</script>
</head>
<body onload="draw()">
<canvas width="1000" height="500" id="canvas"></canvas>
</body>
</html>
canvas03-arc.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>Document</title>
<style>
canvas { background-color: lightblue; }
</style>
<script>
function draw() {
let canvas = document.querySelector('canvas');
let ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(100, 100, 100, 0, Math.PI*2, true);
ctx.moveTo(380, 200); // 안주면 이어짐
ctx.arc(300, 200, 80, 0, Math.PI, false);
ctx.stroke();
}
</script>
</head>
<body onload="draw()">
<canvas width="1000" height="500"></canvas>
</body>
</html>
canvas04-arc_ex.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>Document</title>
<style>
canvas {
background-color: lightgoldenrodyellow;
}
</style>
<script>
function draw() {
let canvas = document.querySelector('canvas');
let ctx = canvas.getContext('2d');
// 호와 원 그리기
// ctx.arc(x, y, radius, startAngle, endAngle, true)
// 360도 Math.PI*2
// 1도 Math.PI / 180
for(let i = 0; i < 3; i ++) {
for(let j = 0; j < 3; j ++) {
ctx.beginPath();
let x = 150 + j * 200;
let y = 150 + i *200;
let endA = Math.PI + (Math.PI*j) / 2;
let anticlockwise = i % 2 != 0? true : false;
ctx.arc(x, y, 50, 0, endA, anticlockwise);
if(i>1) { ctx.fill() }
else { ctx.stroke() }
}
}
}
</script>
</head>
<body onload="draw()">
<canvas width="1000" height="1000"></canvas>
</body>
</html>
canvas05-lineWidth.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>Document</title>
<style>
canvas{
background-color: lightblue;
}
</style>
<script>
function draw() {
let canvas = document.querySelector('canvas');
let ctx = canvas.getContext('2d');
let lineCap = ['butt', 'round', 'square'];
for (let i = 0; i < 10; i++) {
ctx.lineWidth = i + 1;
ctx.lineCap= lineCap[i%3];
ctx.beginPath();
ctx.moveTo(5+i*16, 5);
ctx.lineTo(5+i*16, 140);
ctx.stroke();
}
}
</script>
</head>
<body onload="draw()">
<canvas width="1000" height="600"></canvas>
</body>
</html>
canvas_myname.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>Document</title>
<style>
canvas {
background-color: lightgoldenrodyellow;
}
</style>
<script>
function draw() {
let canvas = document.querySelector('canvas');
let ctx = canvas.getContext('2d');
ctx.lineWidth = 5;
ctx.moveTo(60, 30);
ctx.lineTo(120, 30);
ctx.stroke();
ctx.moveTo(40, 50);
ctx.lineTo(140, 50);
ctx.stroke();
ctx.beginPath();
ctx.arc(90, 90, 20, 0, Math.PI*2, true);
ctx.stroke();
ctx.moveTo(70, 120);
ctx.lineTo(70, 150);
ctx.stroke();
ctx.moveTo(110, 120);
ctx.lineTo(110, 150);
ctx.stroke();
ctx.moveTo(40, 150);
ctx.lineTo(140, 150);
ctx.stroke();
ctx.moveTo(200, 30);
ctx.lineTo(260, 30);
ctx.stroke();
ctx.moveTo(258, 30);
ctx.lineTo(200, 80);
ctx.stroke();
ctx.moveTo(235, 50);
ctx.lineTo(260, 80);
ctx.stroke();
ctx.moveTo(290, 20);
ctx.lineTo(290, 100);
ctx.stroke();
ctx.moveTo(210, 110);
ctx.lineTo(210, 150);
ctx.stroke();
ctx.moveTo(207, 150);
ctx.lineTo(300, 150);
ctx.stroke();
}
</script>
</head>
<body onload="draw()">
<canvas width="800" height="800"></canvas>
</body>
</html>
canvas06-image.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>Document</title>
<style>
canvas {
background-color: lightblue;
}
</style>
</head>
<body>
<canvas id="canvas" width="1000" height="500"></canvas>
<div style="display:none">
<img id="source" src="https://images.mypetlife.co.kr/content/uploads/2019/09/09152804/ricky-kharawala-adK3Vu70DEQ-unsplash-1024x679.jpg" alt="" width="300" height="227">
<!-- https://mdn.mozillademos.org/files/5397/rhino.jpg -->
</div>
<script>
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
// const image = document.querySelector('#source');
// image.addEventListener('load', e=> {
// ctx.drawImage(image, 10, 30, 140, 100)
// })
const imgElem = new Image(); // const imgElem = document.createElement('img')
imgElem.src = 'https://images.mypetlife.co.kr/content/uploads/2019/09/09152804/ricky-kharawala-adK3Vu70DEQ-unsplash-1024x679.jpg';
imgElem.addEventListener('load', ()=> {
ctx.drawImage(imgElem, 50, 50, 100, 60);
ctx.drawImage(imgElem, 200, 50, 100, 60);
ctx.drawImage(imgElem, 400, 100, 200, 140, 0, 0, 100, 50);
})
</script>
</body>
</html>
canvas07-event.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>Document</title>
<style>
canvas {
background-color: #eee;
}
</style>
</head>
<body>
<canvas id="canvas" width="1000" height="700"></canvas>
<div id="btns">
<button>red</button>
<button>blue</button>
<button>pink</button>
<button>black</button>
<button>이미지</button>
<button>지우기</button>
</div>
<script>
// const redBtn = document.querySelectorAll('button')[0];
// const blueBtn = document.querySelectorAll('button')[1];
// const pinkBtn = document.querySelectorAll('button')[2];
// const blackBtn = document.querySelectorAll('button')[3];
// const eraseBtn = document.querySelectorAll('button')[4];
// redBtn.addEventListener('click', function() {
// ctx.strokeStyle = 'red';
// })
// blueBtn.addEventListener('click', function() {
// ctx.strokeStyle = 'blue';
// })
// pinkBtn.addEventListener('click', function() {
// ctx.strokeStyle = 'pink';
// })
// blackBtn.addEventListener('click', function() {
// ctx.strokeStyle = 'black';
// })
// eraseBtn.addEventListener('click', function() {
// ctx.clearRect(0, 0, 1000, 700);
// })
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
let brush = 'color';
let imgElem = new Image();
imgElem.src = "img/pica.png";
//버튼지정
const btns =document.querySelector('#btns')
let drawing;
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mousemove', function(e){
console.log(`x좌표는 ${e.pageX}이고 y좌표는 ${e.pageY}이다.`);
console.log('마우스를 움직였습니다.');
})
canvas.addEventListener('mousedown', function(){
console.log('마우스를 눌렀습니다.');
drawing = true;
})
canvas.addEventListener('mouseup', function(){
drawing=false;
console.log('마우스를 뗐습니다.')
})
// 버튼 이벤트 지정하기
btns.addEventListener('click', function(e) {
let btnInner = e.target.innerHTML;
if(btnInner=='지우기') {
ctx.clearRect(0, 0, canvas.width, canvas.height)
} else if (btnInner == '이미지') {
brush = "img";
} else {
brush = "color";
ctx.strokeStyle = btnInner;
}
})
function draw(e) {
// 선의 두께 지정
ctx.lineWidth = 30;
// 선의 끝부분 지정
ctx.lineCap = 'round';
let x = e.pageX;
let y = e.pageY;
if(!drawing) return;
if(brush == "color") {
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x, y);
ctx.stroke();
} else {
ctx.drawImage(imgElem, x, y, 50, 50);
}
}
</script>
</body>
</html>
divMoveInterver.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>Document</title>
<style>
div {
width: 200px;
height: 200px;
position: absolute;
left: 100px;
top: 100px;
background-color: tomato;
transition: 0.5s;
}
</style>
</head>
<body>
<div></div>
<script>
const div = document.querySelector('div');
let divLeft = 100;
setInterval(function(){
div.style.left= divLeft+'px';
divLeft += 100;
if(divLeft>window.innerWidth){
divLeft = -50;
}
}, 500)
</script>
</body>
</html>
divMoveRequest.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>Document</title>
<style>
div {
width: 200px;
height: 200px;
position: absolute;
left: 100px;
top: 100px;
background-color: tomato;
}
</style>
</head>
<body>
<div></div>
<button>정지</button>
<script>
const div = document.querySelector('div');
const btn = document.querySelector('button');
let animation;
let x = 100;
function divMove() {
x += 1;
div.style.left = x+'px';
animation = requestAnimationFrame(divMove); // 재귀함수
}
divMove();
btn.addEventListener('click', ()=> {
cancelAnimationFrame(animation);
})
</script>
</body>
</html>
keydownEvent.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>Document</title>
</head>
<body>
<script>
window.addEventListener("keydown", function(e){
console.log(e);
})
</script>
</body>
</html>
canvas08-interaction.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>Document</title>
<style>
canvas {
background-color: #eee;
}
</style>
</head>
<body>
<h1>Interaction</h1>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
const canvas = document.querySelector("canvas");
const context = canvas.getContext("2d");
const boxes = [];
// 글자 두께 크기 서체 지정
context.font = "bold 24px sans-serif";
class Box {
constructor(index, x, y, speed) {
this.index = index;
this.x = x;
this.y = y;
this.speed = speed;
this.width = 100;
this.height = 100;
this.draw();
}
draw() {
context.fillStyle = "rgba(0, 0, 0, 0.5)";
context.fillRect(this.x, this.y, this.width, this.height);
context.fillStyle="#fff";
// fillText("내용", x, y)
context.fillText(this.index, this.x+30, this.y+30);
}
}
let tempX, tempY, tempSpeed;
for(let i=0; i<10; i++) {
// speed는 1~5 사이의 숫자로 지정
tempSpeed = Math.floor(Math.random()*5)+1;
tempX = Math.random() * canvas.width * 0.8;
tempY = Math.random() *canvas.height * 0.8;
boxes.push(new Box(i, tempX, tempY, tempSpeed))
}
console.log(boxes);
// box이동 시키기
function boxMove() {
context.clearRect(0, 0, canvas.width, canvas.height)
boxes.forEach(box=>{
box.x += box.speed;
if(box.x > canvas.width) {
box.x = -box.x
}
box.draw();
})
requestAnimationFrame(boxMove);
}
boxMove();
</script>
</body>
</html>
'Stack > JavaScript' 카테고리의 다른 글
[JS] Network (0) | 2022.06.17 |
---|---|
[JS] 모듈 (0) | 2022.06.17 |
[JS/JSON] ShoppingList (0) | 2022.06.15 |
[JS] 동기 / 비동기 / 프로미스 (0) | 2022.06.15 |
[JS/JSON] JSON(; JavaScript Object Notaion) (0) | 2022.06.14 |