728x90
사용자가 마우스를 눌러 캔버스 위를 움직일 때마다 경로를 따라 선을 그리며,
선이 그려진 부분은 기존의 검정색 배경이 지워지는 지우개 효과를 나타냅니다.

HTML
<body>
<div class="site_content">
<video autoplay muted loop id="video">
<source src="video.mp4" type="video/mp4">
</video>
</div>
<div class="container">
<div class="nav">
<div class="logo">
<a href="">DOINGIN</a>
</div>
<div class="links">
<a href="">menu01</a>
<a href="">menu02</a>
<a href="">menu03</a>
<a href="">menu04</a>
<a href="">menu05</a>
<a href="">menu06</a>
</div>
</div>
<div class="hero_copy">
<h1>POSCO FUTURE M</h1>
<p>미래는 보는 친환경미래 기업</p>
</div>
<div class="footer">
<div class="links">
<a href="">FMenu01</a>
<a href="">FMenu02</a>
</div>
<div class="cta">
<a href="">TEST</a>
</div>
</div>
</div>
<canvas id="draw"></canvas>
<script src="js/main.js"></script>
</body>
SCSS
@import "font";
*{margin: 0; padding: 0; font-family: "SebangGothic", sans-serif; font-weight: 400; letter-spacing: -0.05rem; box-sizing: border-box;}
li{list-style: none;}
a{text-decoration: none;}
img{display: block; max-width: 100%;}
::selection{color:#fff; background: transparent;}
html, body{width: 100vw; height: 100vh; overflow: hidden; background-color: red;}
.site_content{position: absolute;
#video{position: fixed; right: 0; bottom: 0; min-width: 100%; min-height: 100%;}
}
.container{position: relative; z-index: 1; pointer-events: none; width: 100%; height: 100%;
.nav{width: 100%; display: flex; justify-content: space-between; padding: 2rem;
.logo a{text-transform: uppercase; color: #fff; font-weight: 700;}
.links{display: flex; gap: 2rem;
a{color: #fff; pointer-events: auto;}
}
}
.hero_copy{width: 100%; position: absolute; top: 50%; transform: translateY(-50%); text-align: center;
h1{font-size: 8vw; color: #fff; text-transform: uppercase; font-weight: 700;}
p{font-size: 2vw; color: #fff; margin: 0.5rem 0;}
}
.footer{width: 100%; display: flex; justify-content: space-between; padding: 2rem; position: absolute; bottom: 0;}
}
canvas{ position: absolute; top: 0; left: 0; width: 100vw; height: 100vh;}
JS
1) 캔버스와 2D 컨텍스트 설정
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
- document.querySelector("canvas") : HTML 문서에서 <canvas> 요소를 선택합니다.
- canvas.getContext("2d") : 캔버스에서 2D 그래픽 컨텍스트를 가져옵니다. 이 컨텍스트를 사용하여 캔버스에 그림을 그릴 수 있습니다.
2) 캔버스 크기 설정
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
- window.innerWidth와 window.innerHeight를 사용하여 캔버스의 너비와 높이를 브라우저 창의 크기로 설정합니다. 이는 창 크기에 맞게 캔버스가 조정
3) 캔버스 배경 색상 설정
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
- ctx.fillStyle = "black" : 채우기 색상을 검정색으로 설정합니다.
- ctx.fillRect(0, 0, canvas.width, canvas.height) : 캔버스 전체를 검정색으로 채웁니다. (0, 0) 위치에서 시작하여 캔버스의 너비와 높이만큼 사각형을 그립니다.
4) 선 스타일 설정
ctx.lineJoin = "round";
ctx.lineCap = "round";
ctx.lineWidth = 50;
- ctx.lineJoin = "round" : 선이 만나는 부분을 둥글게 설정합니다.
- ctx.lineCap = "round" : 선의 끝 부분을 둥글게 설정합니다.
- ctx.lineWidth = 50 : 선의 너비를 50으로 설정합니다.
5) 합성 작업 설정
ctx.globalCompositeOperation = "destination-out";
- ctx.globalCompositeOperation = "destination-out" : 그린 부분이 기존 내용과 교차할 때 기존 내용을 지우는 효과를 줍니다. 이는 지우개와 같은 효과를 만듭니다.
6) 그리기 상태 변수
let isDrawing = false;
let lastX = 0;
let lastY = 0;
- isDrawing : 사용자가 마우스를 눌러 그리기 상태인지 여부를 저장합니다.
- lastX와 lastY : 마지막 마우스 위치를 저장합니다.
7) 그리기 함수
function draw(e) {
if(!isDrawing) return;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
[lastX, lastY] = [e.offsetX, e.offsetY];
}
- if(!isDrawing) return; : 그리기 상태가 아니면 함수 실행을 중지합니다.
- ctx.beginPath() : 새로운 경로를 시작합니다.
- ctx.moveTo(lastX, lastY) : 마지막 위치로 이동합니다.
- ctx.lineTo(e.offsetX, e.offsetY) : 현재 위치까지 선을 그립니다.
- ctx.stroke() : 선을 그립니다.
- [lastX, lastY] = [e.offsetX, e.offsetY]; : 현재 위치를 마지막 위치로 업데이트합니다.
8) 마우스 이벤트 리스너 설정
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));
- canvas.addEventListener("mousedown", (e) => {...}): 마우스를 눌렀을 때 그리기를 시작하고, 현재 위치를 마지막 위치로 설정합니다.
- canvas.addEventListener("mousemove", draw): 마우스가 움직일 때마다 draw 함수를 호출합니다.
- canvas.addEventListener("mouseup", () => (isDrawing = false)): 마우스 버튼을 떼면 그리기를 중지합니다.
- canvas.addEventListener("mouseout", () => (isDrawing = false)): 마우스가 캔버스를 벗어나면 그리기를 중지합니다.
전체코드
// 캔버스 요소를 선택하고 2D 컨텍스트를 가져옵니다.
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
// 캔버스 크기를 브라우저 창의 크기로 설정합니다.
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// 캔버스 배경을 검정색으로 채웁니다.
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 선의 끝 모양과 연결 부분을 둥글게 설정하고, 선의 너비를 50으로 설정합니다.
ctx.lineJoin = "round";
ctx.lineCap = "round";
ctx.lineWidth = 50;
// 합성 작업을 "destination-out"으로 설정하여 그린 부분을 지우는 효과를 줍니다.
ctx.globalCompositeOperation = "destination-out";
// 그리기 상태를 나타내는 변수와 마지막 위치를 저장하는 변수를 초기화합니다.
let isDrawing = false;
let lastX = 0;
let lastY = 0;
// 그리기 함수입니다. 마우스가 움직이는 동안 선을 그립니다.
function draw(e) {
if(!isDrawing) return; // 그리기 상태가 아니면 함수 종료
ctx.beginPath(); // 새로운 경로를 시작합니다.
ctx.moveTo(lastX, lastY); // 마지막 위치로 이동합니다.
ctx.lineTo(e.offsetX, e.offsetY); // 현재 위치까지 선을 그립니다.
ctx.stroke(); // 선을 화면에 그립니다.
// 마지막 위치를 현재 위치로 업데이트합니다.
[lastX, lastY] = [e.offsetX, e.offsetY];
}
// 마우스 버튼을 눌렀을 때 그리기를 시작하고, 마지막 위치를 설정합니다.
canvas.addEventListener("mousedown", (e) => {
isDrawing = true;
[lastX, lastY] = [e.offsetX, e.offsetY];
});
// 마우스가 움직이는 동안 draw 함수를 호출합니다.
canvas.addEventListener("mousemove", draw);
// 마우스 버튼을 떼거나 캔버스를 벗어났을 때 그리기를 중지합니다.
canvas.addEventListener("mouseup", () => (isDrawing = false));
canvas.addEventListener("mouseout", () => (isDrawing = false));
728x90
'JavaScript' 카테고리의 다른 글
| [BCGD] 비전공자 백엔드 개발 도전기 (33) (1) | 2025.03.21 |
|---|---|
| [BCGD] 비전공자 백엔드 개발 도전기 (32) (0) | 2025.03.19 |
| [JS] 숫자 카운터 스크립트 (1) | 2024.09.13 |
| [JS] Tab 메뉴 만들기(forEach, Id) (0) | 2024.08.11 |
| JavaScript_기초 (0) | 2024.06.16 |