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 |