zoaseo
To Infinity And Beyond
zoaseo
전체 방문자
오늘
어제
  • 분류 전체보기 (763)
    • 개발이 좋아서 (381)
      • SAP가 좋아서 (3)
      • Java가 좋아서 (42)
      • Spring이 좋아서 (50)
      • JPA가 좋아서 (0)
      • QueryDSL이 좋아서 (26)
      • Docker가 좋아서 (7)
      • Redis가 좋아서 (7)
      • AWS가 좋아서 (5)
      • CI/CD가 좋아서 (6)
      • Troubleshooting이 좋아서 (4)
      • Kotlin이 좋아서 (7)
      • SQL이 좋아서 (6)
      • HTTP가 좋아서 (21)
      • JavaScript가 좋아서 (30)
      • TypeScript가 좋아서 (6)
      • Vue가 좋아서 (21)
      • Flutter가 좋아서 (61)
      • React가 좋아서 (20)
      • Redux(React)가 좋아서 (2)
      • Angular가 좋아서 (22)
      • HTML이 좋아서 (9)
      • CSS가 좋아서 (15)
      • PHP가 좋아서 (9)
      • Illustrator가 좋아서 (2)
    • 노력이 좋아서 (169)
    • 결과물이 좋아서 (14)
    • 코딩연습이 좋아서 (168)
      • 이론이 좋아서 (62)
      • SQL이 좋아서 (90)
    • 유용한 사이트가 좋아서 (28)
    • Github (2)

인기 글

티스토리

hELLO · Designed By 정상우.
zoaseo

To Infinity And Beyond

<step62>'js_canvas_module'
노력이 좋아서

<step62>'js_canvas_module'

2022. 6. 17. 15:36

1) 

index.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>
        body {
            background-color: #090909;
            display: flex;
            margin: 0;
        }
    </style>
</head>
<body>
    <canvas></canvas>
    <script type="module" src="./main.js"></script>
</body>
</html>

utils.js

// 두 수 사이의 랜덤 실수를 반환해주는 함수
function randomFloatBetween(min, max){
    return Math.random()*(max-min+1) + min;
}
// 두 점 (x1, y1)과 (x2, y2)사이의 거리를 반환하는 함수
function distance(x1,y1,x2,y2){
    const distX = x2 - x1;
    const distY = y2 - y1;
    return Math.sqrt(distX * distX + distY * distY);
}
export default { randomFloatBetween, distance };

main.js

import utils from './utils.js';

console.log(utils.randomFloatBetween(10,15));
// 1. 캔버스 불러오기
const canvas = document.querySelector('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const ctx = canvas.getContext('2d');

// 2. 파티클 클래스 정의
class Particle {
    constructor(x,y,radius,velocity){
        this.x = x;
        this.y = y;
        this.radius = radius;
        this.velocity = velocity;
    }
    draw() {
        //펜 시작
        ctx.beginPath();
        // 호 그리기(x,y,radius,startA,endA,방향)
        ctx.arc(this.x,this.y,this.radius,0,Math.PI*2,false);
        ctx.fillStyle = '#fff';
        ctx.fill();
        ctx.closePath();
    }
    animate() {
        //파티클의 좌표가 0이 되거나 canvas의 크기를 벗어날 때
        //0이 되거나 canvas 크기보다 커질 때
        if(this.x<=0 || this.x>=innerWidth || this.y<=0 || this.y>=innerHeight){
            this.x = utils.randomFloatBetween(0,innerWidth);
            this.y = utils.randomFloatBetween(0,innerHeight);
        } 
        this.x += this.velocity.x;
        this.y += this.velocity.y;

        // 파티클 사이에 선 그리기
        // 선 객체 생성
        particles.forEach(particle=>{
            let distance = utils.distance(particle.x, particle.y, this.x, this.y);
            // 점과 점 사이 거리가 300보다 작으면 선을 생성
            if(distance < 300){
                let from = {x: this.x, y: this.y};
                let to = {x: particle.x, y: particle.y};
                new Lines(from, to, distance).draw();
            }
        })
        this.draw();
    }
}
// * 선 클래스 정의하기
class Lines {
    constructor(from,to,distance){
        this.from = from;
        this.to = to;
        this.distance = distance;
    }
    draw(){
        ctx.beginPath();
        ctx.moveTo(this.from.x,this.from.y);
        ctx.lineTo(this.to.x,this.to.y);
        ctx.strokeStyle = `rgba(215,205,0,0.4)`;
        ctx.lineWidth = 1;
        ctx.stroke();
        ctx.closePath();
    }
}
// 추가 마우스 객체 만들기
let mouse = {
    x: 0,
    y: 0,
    isActive: false,
    radius: 5,
}

// 3. 파티클 만들기
const TOTAL = 50;
let particles = [];
for(let i=0; i<TOTAL; i++){
    let x = utils.randomFloatBetween(0,innerWidth);
    let y = utils.randomFloatBetween(0,innerHeight);
    let radius = utils.randomFloatBetween(0.5,2);
    let velocity = {
        x: utils.randomFloatBetween(-2,2),
        y: utils.randomFloatBetween(-2,2),
    }
    particles.push(new Particle(x,y,radius,velocity));
}

// 4. 매 프레임마다 실행되는 재귀함수
function render(){
    ctx.clearRect(0,0,canvas.width,canvas.height);
    requestAnimationFrame(render);
    particles.forEach(particle=>particle.animate());
    if(mouse.isActive){
        let velocity = {
            x: 0,
            y: 0,
        }
        new Particle(mouse.x, mouse.y, mouse.radius, velocity).animate();
    }
}

// 5. 실행하기
render();

// 6. 윈도우 resize 이벤트 정의(창의 크기가 변하면 canvas 크기도 창의 크기로 변경)
window.addEventListener('resize',()=>{
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
})

// 7. 마우스 이벤트 연결하기
canvas.addEventListener('mouseenter', function(){
    mouse.isActive = true;
})
canvas.addEventListener('mouseleave', function(){
    mouse.isActive = false;
})
canvas.addEventListener('mousemove', function(e){
    mouse.x = e.pageX;
    mouse.y = e.pageY;
})

'노력이 좋아서' 카테고리의 다른 글

<step63>'react_기초구문, event'  (0) 2022.06.20
<step63>'js_wave'  (0) 2022.06.20
<step62>'js_canvas_jumpGame'  (0) 2022.06.17
<step61>'js_canvas'  (0) 2022.06.16
<step60>'js_fetch_shoppinglist'  (0) 2022.06.15

    티스토리툴바