자바스크립트 비주얼 만들기. -1

심민기·2022년 5월 3일
0

미디어 아트

목록 보기
2/4

강의

캔버스 기본 그리기.

beginpath로 재설정. fill,arc등으로 그리고 stroke로 실현.
<html>
<body>
    
    <canvas width="600" height="600"></canvas>

    <script>

        let canvas = document.querySelector('canvas');
        let context = canvas.getContext('2d');

        //안쪽 사각형.
        context.fillStyle = 'green';
        context.fillRect(100,100,400,400);
        //위치 재설정.
        context.beginPath();
        //테두리
        context.lineWidth = 4;
        context.rect(100,100,400,400);
        //원 그리기.
        context.beginPath();
        context.arc(300,300,100,0, Math.PI * 2);

        //주어진 선들을 긋기.
        context.stroke();

    </script>
</body>
</html>

반복문으로 그리드 생성.

<html>
<body>
    
    <canvas width="600" height="600"></canvas>

    <script>

        let canvas = document.querySelector('canvas');
        let context = canvas.getContext('2d');

        for (let i =0; i < 5; i++){
            for (let j = 0; j < 5; j++){
                let width = 60;
                let height = 60;
                let gap = 20;
                let x = 100 + (width + gap) * i;
                let y = 100 + (height + gap) * j;
                
                context.beginPath();
                context.rect(x,y,width,height);

                context.fillStyle = 'red';
                context.fillRect(x+8, y+8, width-16, height-16);
                context.stroke();

                context.beginPath();
                context.rect(x+8,y+8,width - 16,height-16);

                context.stroke();
            }
        }
    </script>
</body>
</html>

윈도우cmd를 대체하는 conemu

conemu와 nodejs로 브라우저를 쓰지 않고 자체적인 그래픽을 완성하자.

라이브러리 Canvas - sketch사용

캔버스 스케치

npm으로 설치.

그러면 지정한 폴더에 npm이 설치되고 js파일이 나오며
http://172.30.1.34:9966/와 같이 주소가 생성되어 그곳에 파일의 결과물이 연결된다.

이렇게 node.js의 Npm을 쓰면 브라우저 없이도 결과물을 보고 저장할 수 있다.

이동과 회전.

translate,
rotate,

<html>
<body>
    
    <canvas width="800" height="800"></canvas>
    <script>

    let canvas = document.querySelector('canvas');
    let context = canvas.getContext('2d');

    let width = 800;
    let height = 800;

    const x = width / 2;
    const y = height / 2;
    
    const w = width / 3;
    const h = height / 3;

    //저장. 
    context.save();
    //중앙에 45도 돌아간 정사각형 위치.
    context.translate(x,y);
    context.rotate(45 * Math.PI / 180);
    context.beginPath();
    context.fillStyle = 'black';
    context.fillRect(-w/2, -h/2, w, h);
    //복구
    context.restore();    

    context.translate(100,400);
    //공 생성.
    context.beginPath();
    context.arc(0,0,50,0,Math.PI * 2);
    context.fill();

    context.stroke();

    </script>
</body>
</html>

각도의 사용

const degToRad = (degrees) => { return degrees / 180 * Math.PI; }

각도를 반환.
const slice = degToRad(360/num);
const angle = slice * i;에 대해.

context.rotate(angle);에서 사용.

<html>
<body>
   <canvas width="800" height="800"></canvas>
   <script>
   
   //라디안 값으로 반환.
   const degToRad = (degrees) => {
       return degrees / 180 * Math.PI;
   }    
   let canvas = document.querySelector('canvas');
   let context = canvas.getContext('2d');

   let width = 800;
   let height = 800;

   const cx = width * 0.5;
   const cy = height * 0.5;
   
   const w = width * 0.01;
   const h = height * 0.1;
   let x,y;

   const num = 24;
   const radius = width * 0.3;

   for(let i = 0; i < num; i++){

       const slice  = degToRad(360/num);
       const angle = slice * i;

       //수의 사인, 코사인값 반환.
       x = cx + radius * Math.sin(angle); 
       y = cy + radius * Math.cos(angle); 

       context.save();
       context.translate(x, y);
       context.rotate(-angle);

       context.beginPath();
       context.fillStyle = 'black';
       context.fillRect(-w / 2, -h / 2, w, h);
       //복구
       context.restore();    
   }
   </script>
</body>
</html>

각도를 맞춰 num의 수만큼의 막대기가 원형으로 늘어서있다.

크기.

랜덤 범위기능.

    const randomRange = (min,max) =>{
        return Math.random() * (max - min) + min;
    };

랜덤 크기.

context.scale(randomRange(1,3),1);

크기가 범위내의 랜덤 값이 된다.

랜덤한 원들을 그리기

context.arc(0,0,radius * randomRange(0.7,1.3), slice * randomRange(1,-5), slice * randomRange(1, 5));
간격, 크기, 넓이를 모두 랜덤값으로 하여 여러 랜덤한 원들이 겹쳐보이게 함.

클래스, 객체

다른 스크립트를 생성 해보자.
랜덤한 점들이 펼쳐지는 그림이다.

클래스를 사용.
클래스와 생성자.

point클래스로 위치 저장.
agent로 point의 위치를 가져오고 반복적인 점찍기의 과정을 정의함으로
수십개의 점찍기를 agent클래스를 호출하는 것으로 간략화.

<html><body>
    <canvas width="1200" height="1200"></canvas>
    <script>

    let canvas = document.querySelector('canvas');
    let context = canvas.getContext('2d');
    let width = 1200;
    let height = 1200;

    const pointA = { x: 800, y: 400, radius: 10 };
    const pointB = { x: 300, y: 700, radius: 10 };

    const randomRange = (min,max) =>{
        return Math.random() * (max - min) + min;
    };


    class Point{
        constructor(x,y){
            this.x = x;
            this.y = y;
        }
    }

    class Agent {
        constructor(x,y){
            //포인트로부터 x,y를 가져와서 할당.
            this.pos = new Point(x,y);
            this.radius = 10;
        }
        //점을 그리는 작업
        draw(context){
            context.fillStyle = 'white';
            context.beginPath();
            context.arc(this.pos.x, this.pos.y, this.radius, 0, Math.PI * 2);
            context.fill();
        }
    }

    //배경
    context.fillStyle  = 'black';
    context.fillRect(0,0,width,height);

    const agents = [];

    for (let i = 0; i < 40; i ++){
        const x = randomRange(0, width);
        const y = randomRange(0, height);

        agents.push(new Agent(x,y));
    }

    agents.forEach(agent =>{
        agent.draw(context);
    });

</script></body></html>

점에게 애니메이션 부여

랜덤값을 주고, translate를 활용한다.

속도를 주기 위해서 this.vel에 point를 줘야하는데 점이란 건 의미상 맞지 않으니 Point클래스를 벡터라는 이름으로 바꾸자.

class Vector(리팩토링)

애니메이션을 위해 위치에 속도를 더해줘야한다.

update(){
    this.pos.x += this.vel.x;
    this.pos.y += this.vel.y;
}

그러나 이것만으로는 애니메이션이 되지 않음. 업데이트가 단 1프레임만 작용하기 떄문. 이를 보완하자.

requestAnimationFrame
을 사용하면 윈도우로 하여금 애니메이션 함수를 실행하게 할수 있다.

애니메이션 바운스

현재 점들에게는 경계에대한 것이 없으므로 점이 화면 바깥을 나간다. 이를 막고 경계에 다다르면 튕기도록 하자.

     bounce(width,height){
            if(this.pos.x <= 0 || this.pos.x >= width) this.vel.x *= -1;
            if (this.pos.y <= 0 || this.pos.y >= width) this.vel.y *= -1;
        }

경계에 닿으면 속도가 역으로 돌아가 바운스 된다.

라이브러리를 쓰는데에 막혀서 일단 여기까지.

profile
왕초보

0개의 댓글