Study/Javascript

Javascript: canvas 환경 세팅

devyoseph 2021. 9. 28. 01:27

2021 10 24 업데이트

 

HTML 세팅

1) HTML의 기본 골격을 사용한다. html / head /body

2) meta태그는 속성을 세가지를 사용한다 charset / http-equiv / name ="viewport"

3) CSS와 js연결. script 속성으로 type="module"을 추가함으로 import와 export를 이용해 더욱 객체화한다

4) canvas를 HTML에 만들지 않는다

 

<meta http-equiv="X-UA-Compatible" content="IE=Edge">는 서로 호환성이 다른 경우에

인터넷 익스플로러(IE)버전 중 가장 최신으로 보여주게 해준다. 쿼크모드라고도 한다

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=0">

meta viewport는 애플이 디바이스 화면크기에 따라 크기를 조절하기 위해 만들었다.

content 내에 설정값을 적어주며 쉼표(,)로 구분한다. width = device-width를 통해 화면크기를 조절하고

initial-scale을 통해 초기 배율설정을 1배율로 해주고, maximum-scaler과 user-scalable=yes / no (=0)을 통해

배율이 시시각각으로 변하는 것을 막아줄 수 있다

<!DOCTYPE html>
<html>
<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, maximum-scale=1, user-scalable=0">
<link href="style.css" rel="stylesheet">
</head>
<body>
    <script type="module" src="app.js"></script>
</body>
</html>

 

CSS 세팅

1. 텍스트 영역의 드래그를 막아준다 각 버전별로 해준다

user-select: none; (표준 구문)

-ms-user-select: none; (IE10, IE11)

-webkit-user-select: none; (Safari)

 

2. 모든 영역에서 공백과 외곽선 제거 margin, padding, outline

 

3. IOS 웹킷(webkit)에서는 터치할 때마다 하이라이트가 보이는 현상이 있다

제거하기 위해, -webkit-tap-highlight-color: rgba(0, 0, 0, 0);

 

4. html, body, canvas 화면 출력에 연관되는 태그들은 모두 100%의 크기를 설정한다

(body의 overflow: hidden;)

*{
    user-select: none;
    -ms-user-select: none;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
    outline: 0;
    margin: 0;
    padding: 0;
}
html{
    width: 100%;
    height: 100%;
}
body{
    width: 100%;
    height: 100%;
    overflow: hidden;
}
canvas{
    width: 100%;
    height: 100%;
}

 

Javascript: 모듈화

0. HTML의 <script> 내부에 javascript 코드를 적기X. 메인 js파일에 다른 js파일을 연결해 사용

1. 메인 모듈: App을 class로 선언 하고 생성자(constructor) 생성

2. window.onload를 이용해 모든 요소가 준비되었을 때 실행되도록 한다

3. constructor 안에 canvas를 createElement('요소')를 통해 만들어주고

4. getContext('2d')를 연결한 뒤

5. App내에서 만들어준 canvas를 HTML body로 밀어넣는다 appendChild()

6. 윈도우에 리사이즈 이벤트를 추가해 스크린 크기를 가져와 애니메이션을 정의한다

7. App내에서 requestAnimationFrame을 걸어준다

*직접 코드를 쓰면서 이해하시면 좋을 것 같습니다

 

리사이즈를 하는 순간 함수가 발동해 조정된 body의 너비와 높이를 stage로 가져오고

캔버스 크기는 stage너비와 높이의 두배, 그에 따라 ctx도 scale은 2배 2배로 해준다

 

window에서 requestAnimationFrame을 호출할 수 있다 = 객체화, 다루기 쉬워짐

class App{
    constructor(){
        this.canvas = document.createElement('canvas');
        this.ctx = this.canvas.getContext('2d');

        document.body.appendChild(this.canvas);

        window.addEventListener('resize', this.resize.bind(this), false);
        this.resize(); //리사이즈가 이벤트를 거치지 않아도 발동하기 위함

        window.requestAnimationFrame(this.animate.bind(this));
    }
    resize(){
        this.stageWidth = document.body.clientWidth;
        this.stageHeight = document.body.clientHeight;
        //캔버스는 두 배
        this.canvas.width = this.stageWidth * 2;
        this.canvas.height = this.stageHeight *2;
        this.ctx.scale(2,2); //ctx scale 모두 두 배 주의
    }

    animate(t){
        window.requestAnimationFrame(this.animate.bind(this));
    }
}

window.onload = () =>{
    new App();
}

 

모듈 연결

다른 자바스크립트 문서의 객체와 각각 연결하여 다룬다(객체화)

모듈을 정의할 때 class형태로 정의하고 메인 모듈에 연결할 때는 인스턴스로 받는다.

draw할 때는 반드시 메인모듈에서 정의해준 ctx를 가져와야한다

 

아래에 Ball 모듈을 만들었다. 외부로 연결할 모듈이므로 export를 넣어준다

export class Ball{   //외부로 보내줄 모듈이므로 export를 써준다
    constructor(stageWidth, stageHeight, radius, speed){
        this.radius = radius;
        this.vx = speed;
        this.vy = speed;

        const diameter = this.radius*2;
        this.x = this.radius + (Math.random() * (stageWidth - diameter));
        this.y = this.radius + (Math.random() * (stageHeight - diameter));
    }
 //Ball 클래스 내부에 draw메소드를 만들었다 ctx연결은 필수
    draw(ctx, stageWidth, stageHeight){
        this.x += this.vx;
        this.y += this.vy;

        this.bounceWindow(stageWidth,stageHeight);
        ctx.fillStyle = 'blue';
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius, 0, 2*Math.PI);
        ctx.fill();
    }
}

 

만든 Ball 모듈을 메인 모듈인 app.js에 연결해준다(import)

//App.js 최상단, ./는 현재 문서
import{    // import { 모듈명 } form '경로'
    Ball
}from './ball.js';   //자바스크립트 파일이름이 ball.js며 경로를 ' '안에 넣어준다


//생성자 내부에 ball인스턴스를 연결한 모습
constructor(){
this.ball = new Ball(this.stageWidth, this.stageHeight, 60, 15);
}

//animate()에도 ctx.clearRect로 지워주기 반복하며
//this.ball.draw메소드 호출을 통해 그려준다
animate(t){
        window.requestAnimationFrame(this.animate.bind(this));
        this.ctx.clearRect(0,0,this.stageWidth,this.stageHeight);
        this.ball.draw(this.ctx, this.stageWidth, this.stageHeight);
    }

*이 자료는 유튜버 Interactive Developer 분의 강의를 참고했습니다