본문 바로가기

Vanilla Javascript Effect 구현

Vanilla Javascript Effect 무작정 따라하기 #4.5 canvas에서 무작위 입자 생성 및 변화를 주는 원리 파악

반응형
 

Vanilla Javascript Effect 무작정 따라하기 #4 canvas에서 text 쪼개기

이 글을 쓰며 매주 하기로 했던 나의 야심찬 vanilla javascript effect 무작정 따라하기가 단 3개에서 멈추어있었음을 반성한다. 오늘 HA가 끝나고 힘이 빠져서 자고 싶었지만, 매일 공부를 하다보니 안

bedeveloper.tistory.com

어제는 코드를 보고 스스로 이해하려고 노력하였으나 도저히 불가능했었다. 

 

그래서 설명히 조금 더 친절한 초심자를 위한 동영상을 보고 공부를 시작하기로 했다.

 

동영상 속 언어가 영어라서 설명을 알아듣는데 한참이 걸렸지만 안들리면 들릴때까지 무한 반복을 돌려서 

 

코드의 주석으로 옮겨 보았다. 

 

// 첫번째 파트
//1. 무작위로 입자를 생성
//2. 그리고 캔버스에 뿌려서
//3. 물리를 구현(마찰, 가속, 각 입자에 다른 무게를 적용)

const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let particleArray = []; // 모든 파티클 오브젝트가 포함됨(크기, 색상, 좌표와 같은 정보를 포함함)

//마우스 상호작용을 처리하는 코드

let mouse = {
    x: null,
    y: null,
    radius: 150
}

window.addEventListener('mousemove',function(event){
    mouse.x = event.x;
    mouse.y = event.y;
})

ctx.fillStyle = 'white';
ctx.font = "90px Verdana";
ctx.fillText('A', 20, 60);
// ctx.strokeStyle = 'white';
// ctx.strokeRect(0, 0, 100, 100);
const data = ctx.getImageData(0, 0, 100, 100); //위 영역에서 데이터를 불러온다.

class Particle {
    constructor(x, y){
        this.x = x;
        this.y = y;
        this.size = 3;
        this.baseX = this.x; //this.x와 this.y가 밀렸다가 다시 원래의 자리로 돌아가게 하기위하여 설정했음.
        this.baseY = this.y;
        this.density = (Math.random() * 30) + 1;
    }
    draw(){
        ctx.fillStyle = 'white'
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
        ctx.closePath();
        ctx.fill();
    }
    update(){//입자와 마우스가 가까워지면 움직이게 하는 함수
        let dx = mouse.x - this.x;
        let dy = mouse.y - this.y;
        let distance = Math.sqrt(dx * dx + dy * dy) //피타고라스를 이용하여 점과 마우스 사이의 거리를 계산한다. 
        if(distance < 150){
            this.size = 15; //마우스와 점사이의 거리가 150미만이라면 점의 크기는 커지고
        }else{
            this.size = 3; // 마우스와 점사이의 거리가 150이상이라면 점의 크기는 원래로 돌아간다.
        }
    }
}

function init(){ // 위에서 만든 particle 클래스를 무작위로 생성하기 위하여 만든 임의의 함수. particle 클래스를 여러번 호출하고 이를 particleArray에 넣는다.
    particleArray = [];
    for(let i = 0; i < 500; i++){
        let x = Math.random() * canvas.width;
        let y = Math.random() * canvas.height;
        particleArray.push(new Particle(x, y));
    }
}

init();
console.log(particleArray);

function animate(){ //캔버스를 지웠다가 다시 그려주는 기능을 하는 함수(재귀의 형태를 띈다.)
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    for (let i = 0; i < particleArray.length; i++){
        particleArray[i].draw();
        particleArray[i].update();
    }
    requestAnimationFrame(animate);
}

animate();

 위의 코드를 실행하면 어떠한 화면이 나오느냐 아래 동영상을 참고하자(단, 환공포증 있는 사람은 안보기를 추천한다.)

 

보면 알겠지만 마우스로부터 특정 거리 안에 있는 점들은 커진다! 그리고 멀어지게되면 다시 자신의 크기로 돌아간다. 

 

또한 새로고침을 할때마다 점의 위치가 달라지는 것 도한 확인가능하다. 

 

이를 이용하면 점들이 커지는 대신에 밀려지고 당겨지고 하는 interaction을 구현할 수 있는 것이다. 

 

이제 밀고 당겨지는 interaction + 가속도를 적용하기위해 쓴 코드를 보자. 

 

물론 다 이해하지는 못했다 ㅋㅋㅋㅋㅋㅋ ㅠㅠㅠㅠ

 

해석하면서 보는데도 이게 무슨...ㅋㅋㅋㅋㅋ 그렇지만 어제보다는 익숙했기에 더 많이 이해할 수 있었다.

 

    let mouse = {
    x: null,
    y: null,
    radius: 150
}
    
    
    update(){
        let dx = mouse.x - this.x;
        let dy = mouse.y - this.y;
        let distance = Math.sqrt(dx * dx + dy * dy)
        //마우스에 멀리있는 입자가 마우스로 다가오게 하고(마우스의 끝쪽(150)에서 마우스의 중심점으로 움직이게 만들기 위함)
        //각자의 입자가 그것의 무게에 의해 다른 속도로 움직이게 하기 위한 셋팅 (constructor의 density 속성)
        //마우스의 중심에 가까우면 속도가 빠르게하고 끝쪽으로 갈 수록 느려지게 하기위한 세팅
        let forceDirectionX = dx / distance; 
        let forceDirectionY = dy / distance; 
        let maxDistance = mouse.radius; //이동속도가 0인 거리를 설정하기 위해 만듦
        let force = (maxDistance - distance) / maxDistance;
        let directionX = forceDirectionX * force * this.density
        let directionY = forceDirectionY * force * this.density

        if(distance < mouse.radius){
            this.x -= directionX; 
            this.y -= directionY; 
        }else{//마우스로부터 일정 거리 이상 떨어졌을 시 다시 원래의 자리로 돌아가게 하는 부분
            if(this.x !== this.baseX){
                let dx = this.x - this.baseX;
                this.x -= dx/10; // /10을 하는 것은 천천히 돌아가게 하기 위하여
            }if(this.y !== this.baseY){
                let dy = this.y - this.baseY;
                this.y -= dy/10; // /10을 하는 것은 천천히 돌아가게 하기 위하여
            }
        }
    }

그리고 위를 적용한 동영상

 

 

이 다음에 공부한 것은 무작위로 점을 뿌리지 않고 text의 데이터를 가져와서 canvas위에 나타내고 

 

각각의 particle을 특정 px범위 안에서 선으로 연결해 주는 것이었다. 

 

설명은... 아직 나의 언어로 설명할 수가 없다. 이해하고 적을 수 있도록 노력하겠다.

 

 

 

 

어제 작성한 코드 중 일부를 오늘 공부를 통해서 이해할 수 있었다. 

 

또 한번 보게된다면 더 많은 것을 이해할 수 있겠지....

 

오늘은 솔로데이다. 그래서 하고싶은 것을 하는데 원리를 파악하는 동안 난이도가 갑자기 올라갔다. ㅋㅋㅋㅋ

 

내가 하고 싶은 것들은 왜이렇게 다들 고차원적인지

 

열심히 이해하여 자유자재로 활용할 수 있는 사람이 되도록 해봐야겠다. 

반응형