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};
'Stack > JavaScript' 카테고리의 다른 글
[JS] Wave (0) | 2022.06.20 |
---|---|
[JS] JumpGame (0) | 2022.06.17 |
[JS] 모듈 (0) | 2022.06.17 |
[JS] canvas (0) | 2022.06.16 |
[JS/JSON] ShoppingList (0) | 2022.06.15 |