Fun with HTML5 Canvas
const canvas = document.querySelector('#draw');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.strokeStyle = '#bada55';
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
let isDrawing = false;
let lastX = 0;
let lastY = 0;
function draw(e) {
console.log(e);
}
canvas.addEventListener('mousemove', draw);
마우스를 캔버스 위에서 움직이면 아래와 같이 마우스 이벤트가 찍힌다.
const canvas = document.querySelector('#draw');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.strokeStyle = '#bada55';
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
let isDrawing = false;
let lastX = 0;
let lastY = 0;
function draw(e) {
if (!isDrawing) return; // 마우스를 누르고 있지 않으면 function 실행 중지
console.log(e);
}
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mousedown', () => isDrawing = true);
canvas.addEventListener('mouseup', () => isDrawing = false);
canvas.addEventListener('mouseout', () => isDrawing = false);
이제 마우스를 누른 상태에서만 움직여야 이벤트가 찍히게 된다.
function draw(e) {
if(!isDrawing) return; // 마우스를 누르고 있지 않으면 function 실행 중지
console.log(e);
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
}
draw function에 추가를 한후 테스트를 해보면 왼쪽 상단에서 시작되는 선이 마우스를 따라 생기게 된다.
현재는 항상 0에서 마우스가 실제로 움직이는 곳으로 선이 생겼는데
우리가 하고싶은 것은 마우스를 따라 선을 만드는 것이기 때문에 lastX와 lastY의 값이 계속 업데이트 되어야 합니다.
function draw(e) {
if(!isDrawing) return; // 마우스를 누르고 있지 않으면 function 실행 중지
console.log(e);
ctx.beginPath();
ctx.moveTo(lastX, lastY); // 시작 위치
ctx.lineTo(e.offsetX, e.offsetY); // 이동하는 위치
ctx.stroke();
// lastX = e.offsetX;
// lastY = e.offsetY;
[lastX, lastY] = [e.offsetX, e.offsetY]; // 위의 두줄을 한줄로 정리
}
테스트 시 문제점은 mouseup을 한 지점에서 다시 mousedown을 한 지점이 직선으로 연결된다.
우리가 원하는 것은 자유로운 그림을 그리는 것이기 때문에 연결되어지는 직선이 있어서는 안된다.
그러기 위해서 eventListener들을 수정해준다.
canvas.addEventListener('mousedown', (e) => {
isDrawing = true;
[lastX, lastY] = [e.offsetX, e.offsetY];
});
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', () => isDrawing = false);
canvas.addEventListener('mouseout', () => isDrawing = false);
ctx.lineWidth = 100;
라인의 두께를 조정해 준다.
// ctx.lineJoin = 'round';
// ctx.lineCap = 'round';
lineJoin과 lineCap의 역할을 알아보기 위해 두개를 잠시 주석처리한 후 확인해본다.
이 두개가 없으면 라인이 부드러럽게 나오지 않는다.
let hue = 0;
function draw(e) {
if(!isDrawing) return; // 마우스를 누르고 있지 않으면 function 실행 중지
console.log(e);
ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`;
ctx.beginPath();
ctx.moveTo(lastX, lastY); // 시작 위치
ctx.lineTo(e.offsetX, e.offsetY); // 이동하는 위치
ctx.stroke();
// lastX = e.offsetX;
// lastY = e.offsetY;
[lastX, lastY] = [e.offsetX, e.offsetY]; // 위의 두줄을 한줄로 정리
hue++;
}
라인의 컬러가 계속 변할 수 있게 해준다.
let direction = true;
function draw(e) {
if (ctx.lineWidth >= 100 || ctx.lineWidth <= 1) {
direction = !direction;
}
if (direction) {
ctx.lineWidth++;
} else {
ctx.lineWidth--;
}
}
같은 방식으로 라인의 두께가 계속 변화하도록 해준다.
ctx.globalCompositeOperation = 'multiply';
도형 합성 타입도 넣을수 있다.
multiply를 적용하여 겹쳐지는 부분이 어두운색이 되는걸 확인할수 있다.
최종코드
const canvas = document.querySelector('#draw');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.strokeStyle = '#bada55';
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.lineWidth = 100;
let isDrawing = false;
let lastX = 0;
let lastY = 0;
let hue = 0;
let direction = true;
// ctx.globalCompositeOperation = 'multiply';
function draw(e) {
if(!isDrawing) return; // 마우스를 누르고 있지 않으면 function 실행 중지
console.log(e);
ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`;
ctx.beginPath();
ctx.moveTo(lastX, lastY); // 시작 위치
ctx.lineTo(e.offsetX, e.offsetY); // 이동하는 위치
ctx.stroke();
// lastX = e.offsetX;
// lastY = e.offsetY;
[lastX, lastY] = [e.offsetX, e.offsetY]; // 위의 두줄을 한줄로 정리
hue++;
if (hue >= 360) {
hue = 0;
}
if (ctx.lineWidth >= 100 || ctx.lineWidth <= 1) {
direction = !direction;
}
if (direction) {
ctx.lineWidth++;
} else {
ctx.lineWidth--;
}
}
canvas.addEventListener('mousedown', (e) => {
isDrawing = true;
[lastX, lastY] = [e.offsetX, e.offsetY];
});
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', () => isDrawing = false);
canvas.addEventListener('mouseout', () => isDrawing = false);
HTMLCanvasElement.getContext() : 캔버스의 드로잉 컨텍스트를 반환하는 메서드.
CanvasRenderingContext2D.lineJoin : 두 선이 만나는데 사용되는 모양을 결정하는 Canvas 2D API 속성.
CanvasRenderingContext2D.lineCap : 선의 끝점을 그리는데 사용되는 모양을 결정하는 Canvas 2D API 속성.
JavaScript30 강의를 보고 공부한 글입니다. (https://javascript30.com/)
'JavaScript30 Challenge' 카테고리의 다른 글
[JavaScript30] Day 10 (0) | 2020.04.27 |
---|---|
[JavaScript30] Day 9 (0) | 2020.04.26 |
[JavaScript30] Day 7 (0) | 2020.04.22 |
[JavaScript30] Day 6 (0) | 2020.04.19 |
[JavaScript30] Day 5 (0) | 2020.04.18 |