Stack/JavaScript

[JS] Network

7ingout 2022. 6. 17. 15:37

 

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>

 

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() {
        // 파티클의 좌표가 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 Line(from, to, distance).draw();
            }
        })
        this.draw();
    }
}
// * 선 클래스 정의하기
class Line {
    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;
}) 

// window.addEventListener('mousemove', e => {
//         let x = e.pageX;
//         let y = e.pageY;
//         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));
// })

// 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;
})

 

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};