[JavaScript] Canvas Totorial(지우개 효과)

2024. 7. 23. 17:57·JavaScript
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
'JavaScript' 카테고리의 다른 글
  • [BCGD] 비전공자 백엔드 개발 도전기 (32)
  • [JS] 숫자 카운터 스크립트
  • [JS] Tab 메뉴 만들기(forEach, Id)
  • JavaScript_기초
PUSH → MERGE → DEPLOY
PUSH → MERGE → DEPLOY
데이터 흐름과 운영 자동화를 설계하는 백엔드 개발자
  • PUSH → MERGE → DEPLOY
    Coding Dongin
    PUSH → MERGE → DEPLOY
  • 전체
    오늘
    어제
    • MEUN
      • 코테(Solved.ac + Programmers)
      • BootCamp(JAVA)
      • JAVA
      • SpringBoot
      • JavaScript
      • JSP
      • DB(SQL)
      • React
      • HTML_CSS
      • jQuery
      • SCSS
      • GSAP
      • 설치 + 꿀팁
      • 정보처리기사 오답노트
      • 정보처리기사 기출문제
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • GIT
  • 공지사항

  • 인기 글

  • 태그

    정처기오답노트
    solved.ac
    기출문제
    자료구조
    시뮬레이션
    dp
    프로그래머스
    수학
    실기
    코딩테스트
    브루트포스
    정보처리기사
    java
    자바
    level1
    level0
    구현
    배열
    정처기
    피보나치
    완전탐색
    정처기실기
    백엔드개발자
    정보처리기사 실기 기출문제
    정렬
    Level2
    백준
    문자열
    springboot
    알고리즘
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.4
PUSH → MERGE → DEPLOY
[JavaScript] Canvas Totorial(지우개 효과)
상단으로

티스토리툴바