배움 __IL/TIL 1기

TIL : 25번째- 230102 [1-1-월]

Mo_bi!e 2023. 1. 2. 22:09

I. INTRO

지금은 언어만 배우는 것이여

 

게임 구현능력은 부족하지만 구조는 가능함 

만들고자 하는것을 생각하고, 게임은 못만들지만 구조는 만들기가능

how? 말하는것으로

 

지난시간 이미지 그리기로 함수를 이용했음

 

 

II.  drawImage 이용하기

1. 이미지 이해하기

var img = this.document.querySelector("img");

    var img = new Image();
    img.src = "./image/boy.png";
    img.onload = function(){
       
       
        ctx.drawImage(img,0,300,105,148.24,
             100,300,105,148.24)
             //위가 이미지, 아래가 캔버스 위치두기
 }

위의 경우 img에서 위 4개는 img에 대한 설정이다.

 

좌측 상단부터 x,y축 지정하고(0,300) / 105,148.24 사이즈 만큼 잘라준다

이후 캔버스 위에 x,y축 지정하고(100,300) / 105,148,24만큼 크기로 붙여준다.

 

2. 이미지  자세 바꾸기

       	var boy1 = new Boy();
    	boy1.draw(ctx);
        
        var sw = 106;
        var sh = 148.25;
        
        
        var ix = 1;
        var iy = 3;
        
        var sx = sw * ix;
        var sy = sh * iy;
            
        ctx.drawImage(img,sx,sy,sw,sh,
            0,100,105,148.24)

위와 같은 값에 ix,iy값을 변경하면 상기 boy에서 12개의 이미지 중에 행동을 설정할 수있다.

 

 

3. 캐릭터 두개를 동시에 띄우고 자세 다르게하기

       	var boy1 = new Boy();
    	boy1.draw(ctx);
    
    	var boy2 = new Boy();
    	boy2.draw(ctx);
       
       
        var sw = 106;
        var sh = 148.25;
        
        
        var ix = 1;
        var iy = 3;
        
        var sx = sw * ix;
        var sy = sh * iy;
            
        ctx.drawImage(img,sx,sy,sw,sh,
            0,100,105,148.24)

 

 

but. 각자 다른 객체로 해야할 필요존재.

 

 

4. 이미지 마다 구조화 캡슐화

(1)구현

구현해보자

 

(2) 안나옴

this 에 대해서 알아보자

function Box(){
   
}

Box.prototype = {
    test : function(x,y){
        console.log("this머임?" + this);
        console.log(x);
        console.log(y);
    }

};

var box1 = new Box();
box1.test();
console.log("1------------구분----------");

var f1 = box1.test; // 그러면 누가 나올 것인가?

f1(); //window.f1 이라서 window가 나온다.
console.log("2------------구분----------");

var obj = { kor : 2}; 
obj.onload = box1.test; 
obj.onload(); //함수 호출 함
console.log("3------------구분----------");

1) 1번 구분

본 출력은 Box의 객체를 생성해서 하기때문에 

this의 출력은 Box가 나온다

 

2) 2번 구분

별도의 객체 생성없이 window 객체에다가 f1을 선언해주고, box1참조명의 객체의 메소드를 이용할 수있게끔 하였다.

이 경우 메소드를 호출한 객체는 window이기 때문에 

this의 출력은 window가 나온다.

 

3) 3번 구분

obj 라는 참조명의 객체를 만들어준다.

obj.onload라는 프로퍼티에 box1.text 메소드를 이용할수있게끔 함

이 경우 메소드를 호출한 객체는 obj이기 때문에

this의 출력은 window가 나온다.

 

(3) call() / apply() /bind() : 캡슐화 과정의 문제점

특정객체에 명시적으로 바인딩해주는 기법들로 call, apply, bind 가 있다.

var n1 = {id : 1, title : 'hello'};
obj.onload();
obj.onload.call(n1);
console.log("5------------구분----------");
obj.onload.apply(n1, ['hi','okay']); //위로 별도의 인수를 넣어주기 가능

1) call()

여기서 call은  그냥 onload()할때는 n1의 프로퍼티들이 반영되지않음

그러나 call 을 하면은 출력을 할 때 n1의 객체로 명시적으로 this를 정해준다.

 

이러한 경우 

obj.onload.call(n1, 'hi', 'okay');

hi / okay 를 본 메소드에 인자를 추가해서 넘겨줄 수있다.

 

2) apply()

call과 마찬가지이다.

다만 배열방식으로 인자를 넘겨주는 것을 의미한다.

 

 

3) bind()

앞에서 콜 할때 this 바꿔치기와 다르게

 함수후반에다가 쓰는 것이 bind이다.

Boy.prototype = {

    draw : function(ctx){

        console.log(this); //
        console.log("10------------구분----------");

        var img = new Image();
        img.src = "./image/boy.png";

        img.onload = function(){
            console.log(this); //
            console.log("11------------구분----------");

            ctx.drawImage(img,
                this.sx,this.sy,this.sw,this.sh,
                this.x,this.y,105,148.24)
        // }.bind(this);
        }

}}

<결과>

10번단은 바깥쪽 객체인 Boy에 this 가 바인딩된다

그러나 11번단은 img객체에 this가 바인딩 되었다

 

객체 안에 객체가 있을 경우에 this는 의도치 않게 안쪽에 있는 객체에 바인딩될수있다.

이러한 경우를 미연에 방지하기 위해서 쓰는 것이 bind이다.

 

<해결>

bind가 가장 쓸일 多

 

Boy.prototype = {

draw : function(ctx){

    console.log(this); //

    var img = new Image();
    img.src = "./image/boy.png";

    img.onload = function(){
        console.log(this); //

        ctx.drawImage(img,
            this.sx,this.sy,this.sw,this.sh,
            0,100,105,148.24)
    }.bind(this); 	//여기에다가 이용해준다.
}}

따라서 캡슐화에서 this를 어떻게 쓰냐가 문제인데

bind()가 용이하게 이용 가능함

 

5. 기능 넣기

이제 canvas 나 window에 클릭을 했을 때 캐릭터가 움직이는 것을 만들어보자

(1) 캔버스 요소 찾기와 드로잉 생성

window.addEventListener("load",function(){
    
    var canvas = document.querySelector(".game-canvas"); //캔버스 요소찾기
    
    /**@type {CanvasRenderingContext2D};*/
    var ctx = canvas.getContext("2d"); //드로잉 생성
    

    canvas.onclick = function(){

        boy2.move(2); //방향코드 생각하자.
        boy2.draw(ctx);
        // boy2.move(3); //방향코드 생각하자.
        // boy2.draw(ctx);
        // boy2.move(1); //방향코드 생각하자.
        // boy2.draw(ctx);

    };}

위와 같이 요소찾고, 드로잉 생성을해준다.

 

그리고 onclick 을 이용해서 클릭할 때마다 본 함수가 발생하게끔 할 수있다.

 

(2) move 함수 구현하기

Boy.prototype = {

    draw : function(ctx){

        console.log(this); //
        console.log("10------------구분----------");

        var img = new Image();
        img.src = "./image/boy.png";

        img.onload = function(){
            console.log(this); //
            console.log("11------------구분----------");

            ctx.drawImage(img,
                this.sx,this.sy,this.sw,this.sh,
                this.x,this.y,105,148.24)
        // }.bind(this);
        }

    },


    move : function(dir){
        console.log("move 구분용");

        switch(dir){
            case 1: this.y -= 10; //북
                break;
            case 2: this.x += 10; //동
                break;
            case 3: this.y += 10; //남
                break;
            case 4: this.x -= 10; //서
                break;
            // default : this.x = 0 ;
            //           this.y= 0;

        }
    }


}

아래쪽 move 함수로 구현을 할 수있다.

이 경우 반드시 this를 이용해 주어야한다.

 

(3) Boy 객체 생성

var boy2 = new Boy();

Boy에 대한 boy2객체를 만들어 주었다.

 

6. 윈도우 캔버스

(1) 차이 알기

window.addEventListener("load",function(){

    //윈도우 안윈도우 : 기생윈도우 자식윈도우 임베디드윈도우
    //윈도우란 영역과 입력이 있어야한다.
    //입력불가능한것은 윈도우 아님 도화지에 불과

    //캔버스는 윈도우임 문서에 보이는 모든객체는 윈도우

    window.onclick = function(){
        console.log("window clicked1");
        
    };
    
    var canvas = document.querySelector(".game-canvas");

    canvas.onclick = function(){
        console.log("canvas clicked2");


    };
}

window canvas 등 누가 객체이냐가 따라서 작동인된다

이 두가지가 한번에 onclick이면 두곳이 중첩되는곳에 클릭 되면 두 함수 모두 작동하게 된다.

 

 

 

(2) 자식 안 자식 : 이벤트 버블링

한번 이벤트 함수수십개 버튼 처리 가능

각각 이벤트 달아주는것은 하수/ 고수는 버블링을 잘 이용함

이벤트 함수 적게이용하며, 코드 깔끔하게 이용이 가능 함.

 

윈도우 안 윈도우 (= 기생윈도우 자식윈도우 임베디드윈도우)

 

윈도우란 영역입력이 있어야한다.
입력불가능한것은 윈도우 아님 도화지에 불과

캔버스는 윈도우임 문서에 보이는 모든객체는 윈도우

 

 

 


1. 보충

(1) this 이해

 

1) lexical Scope

What (정의) : 함수의 상위 scope를 결정할 때 static VS lexical(Dynamic) 을 결정한다.\

여기서 렉시컬 스코프란 함수가 어디서 호출되었느냐가 아니라 어디서 선언되었으냐에 따라서 상위스코프가 결정되는 것이다. 반면 static scope는 함수 호출된 곳에 따라서 결정된다

 

Why (존재이유)  : 상위스코프를 예상하기 위해서

How (방법) :

e.g. (예) :

 

2) window (전역)스코프

What (정의) : 함수가 아닌 곳에서 선언 된 경우 상위 객체인 window, 전역스코프(window의 프로퍼티)로 되는 것을 의미한다.

Why (존재이유)  : C / JAVA의 경우 main함수 밖에 선언 된 경우에 전역변수가 되지만, JS는 main함수(특별한 시작점)가 없기 때문이다.

How (방법) :

e.g. (예) :

 

 

3) 메소드 호출 시 this

함수가 객체의 프로퍼티인 경우 메소드가 된다.

이 경우 메소드 내 this는 객체에 바인딩되는 것임

 

 

4) 왜 객체명이 안나옴?

 

(2) 이벤트 버블링

What (정의) : 버블링이란 자식객체(요소)에 사건(이벤트,핸들러)이 발생하면, 부모 요소에 할당된 이벤트가 발생한다.

비단 부모 뿐만 아니라 최상단의 부모요소의 핸들러까지 작동하는 것을 의미한다.

 

반대로 이벤트 캡처링도 있다. 최상에서 내려오는 것을 의미한다.

 

Why (존재이유)  : 함수를 적게 이용하고, 손쉽게 수정하고 다루기 위해서 이다.

How (방법) :

e.g. (예) :

 

 

 

2. 회고 

1) 오늘 다른 것은 쉽게 이해될수 있었다. 그러나 this에서 문제가 봉착하였다 

그래도 this에 대해서 객체가 누구이냐이고 특히 this는 함수를 호출 할때 결정된다고 하는데,

 

그 호출의 주체가 어디 객체에 속해있느냐에 따라서 결정되는것이 점차 이해가 된다.

 

2) 다만 이런경우 또 충돌 되는것이 함수 대입이 계속 충돌한다. 이거에 대해서도 한번 궁리해 보아야겠다.

 

'배움 __IL > TIL 1기' 카테고리의 다른 글

TIL : 27번째- 230104 [1-1-수]  (0) 2023.01.04
TIL : 26번째- 230103 [1-1-화]  (0) 2023.01.03
TIL : 24번째- 221230 [12-5-금]  (0) 2022.12.30
TIL : 23번째- 221229 [12-5-목]  (1) 2022.12.29
TIL : 22번째- 221228 [12-5-수]  (0) 2022.12.28