Canvas - 07

Using images

이미지 불러오기

  • HTMLImageElement
    • img태그와 마찬가지로 image() constructor를 통해 만들어진 이미지
  • SVGImageElement
    • <image> element를 사용해 불러온 이미지
  • HTMLVideoElement
    • HTML video 요소를 이미지 소스로 사용하여 비디오의 현재 프레임을 이미지로 불러옴
  • HTMLCanvasElement
    • 다른 canvas태그 요소를 이미지 소스로 사용

위와 같은 방법으롤 얻은 이미지는 CanvasImageSource를 사용하여 불러 올 수 있다.

이미지 생성자를 통해 이미지를 새로 만들어 불러올 수 있다.

//image 생성자를 통해 img를 새로 만듦
const img = new Image();
//이미지 경로를 지정함
img.src = 'myImage.png';

그러나 위와 같이 바로 이미지를 불러올 준비를 하면 이미지가 로드 되기 전에 캔버스를 그려서 이미지를 불러 올 수 없을 수 있다.
따라서 이미지를 불러올때는 다음과 같은 방법을 사용할 수 있다.

//이미지 생성자로 img를 새로 만들고
const img = new Image();
//이때 바로 img를 캔버스로 그리지 않고 load함수를 이용한다.
img.addEventListener('load', function(){
	// img를 캔버스에 그리는 코드
  ctx.drawImage(img, 0, 0);
})
img.src = 'myImage.png';

이미지의 src는 상대경로, 데이터url, 절대경로를 모두 포함한다.

비디오를 가져오는 방법도 비슷하다.
대신 비디오 태그를 활용하는데 html의 비디오태그를 가져오고 가져온 비디오태그를 이벤트 리스너로 재생 될 수 있을때 이미지를 그리면 된다. drawImage함수의 첫번째 인자에 비디오태그를 담으면 된다.

const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
    //video 소스가 담겨있는 태그를 가져온다.
    const video = document.getElementById('myVideo')
    function getMyVideo(){
        if(canvas.getContext){
            //drawImage를 하면 되는데 바로 비디오 태그를 불러오면 된다.
            ctx.drawImage(myVideo, 0, 0, 300, 300)
       }
    }
    //비디오가 재생될 수 있을때 위의 함수를 실행한다.
    video.addEventListener('canplaythrough', getMyVideo)

이미지 그리기

이미지를 그리는 방법은 앞서 잠시 소개했듯이 아래와 같이 함수를 사용하면 된다.

  • drawImage(image, x, y)
    • 이미지 좌측상단을 기준으로 x, y만큼 이동하여 캔버스에 이미지를 그린다.

      참고
      SVG image는 반드시 <svg>요소에서 너비와 높이를 설정한다.

    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
    const img = new Image();
    img.src = 'https://mdn.mozillademos.org/files/5395/backdrop.png';

    if(canvas.getContext){
        //이미지가 로드되기 전에 캔버스를 그려서 이미지가 안보임
        //draw()
        //이미지 로드가 되면 함수를 실행하여 캔버스에 그려낸다.
        img.addEventListener('load', draw);
    }

    function draw(){
        //이미지를 그림 0,0 위치에 너비 높이는 기본 그림값으로 설정
        ctx.drawImage(img,0,0)
        //선을 그릴 준비
        ctx.beginPath();
        //최초 위치 잡고
        ctx.moveTo(30,96);
        // 해당위치로 선을 이동
        ctx.lineTo(70,66);
        // 해당위치로 선을 이동
        ctx.lineTo(103,76);
        // 해당위치로 선을 이동
        ctx.lineTo(170,15);
        // 선을 그림
        ctx.stroke()
   }

비례 크기 조정

이미지를 위치에 따라 그릴 뿐아니라 너비와 높이를 설정할 수 있다. 2개의 변수만 추가하면 된다.

  • drawImage(image, x, y, width, height)
    • 너비와 높이 매개변수를 추가하면 캔버스를 그릴 때 이미지의 크기와 스케일을 조정할 수 있다.

참고
너비와 높이변수를 추가하면 크기가 조정될때 흐려지거나 이미지가 거칠어질 수 있다. 따라서 텍스트가 있는 이미지 같은 경우 가독성을 유지해야 될 때에는 사용하지 않는 것이 좋다.

    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
    const img = new Image();
    img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';

    if(canvas.getContext){
        //이미지가 로드되기 전에 캔버스를 그려서 이미지가 안보임
        //draw()
        //이미지 로드가 되면 함수를 실행하여 캔버스에 그려낸다.
        img.addEventListener('load', draw);
    }

    function draw(){
        //j가 3번 실행될때 i가 1번 실행
       for(let i = 0; i < 4; i++){
            for(let j = 0; j < 3; j++){
                //이미지의 크기를 조정하고 x축을 j가 변화될때 마다 y축을 i가 변화될때 마다 이미지 크기만큼 이동한다.
                ctx.drawImage(img, j*50, i * 38, 50, 38)
            }
       }
   }

이미지 자르기

위의 이미지를 보면 원 이미지와 원 이미지에서 일부를 추출하여 캔버스에 그린 이미지를 볼 수 있다.
위와 같이 이미지를 자르고 붙이기위해서는 아래의 함수를 사용한다.

  • drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
    • imgage는 이미지 소스를 의미하고 s가 붙은 x,y,너비,높이는 소스이미지를 의미한다. 소스이미지의 sx, sy에서 s너비와 s높이만큼을 가져온다는 것을 말한다. 이렇게 가져온 이미지는 캔버스로 가져오는데 캔버스에 그릴때 마찬가지로 d가 붙은 x,y,너비, 높이로 붙인다는 것이다. 다만 뒤의 d너비와 d높이는 가공되어 가져온 이미지이기 때문에 너비와 높이를 바꾸면 이미지의 스케일과 사이즈가 변경된다.
<body onload="draw();">
        <canvas id="canvas" width="150" height="150"></canvas>

        <!-- 가져온 이미지는 보이지 않게 한다. 캔버스에 그릴꺼기 때문. -->
        <div style="display:none;">
            <!-- 어기서 이미지 소스를 가져온다. -->
          <img id="source" src="https://mdn.mozillademos.org/files/5397/rhino.jpg" width="300" height="227">
          <img id="frame" src="https://mdn.mozillademos.org/files/242/Canvas_picture_frame.png" width="132" height="150">
        </div>
</body>
<script>
    function draw(){
        const canvas = document.getElementById('canvas')
        const ctx = canvas.getContext('2d');
        const img = document.getElementById('source')
        const frame = document.getElementById('frame')

        //그림을 가져온다. 얼굴만 자르고 가져왔다.
        ctx.drawImage(img,37,71,104,124,21,20,87,104)
        //프레임을 붙인다.
        ctx.drawImage(frame,0,0)
   }
</script>

아트 갤러리 예제

<body onload="draw()">
    <table>
        <tr>
            <td><img src="https://mdn.mozillademos.org/files/5399/gallery_1.jpg"></td>
            <td><img src="https://mdn.mozillademos.org/files/5401/gallery_2.jpg"></td>
            <td><img src="https://mdn.mozillademos.org/files/5403/gallery_3.jpg"></td>
            <td><img src="https://mdn.mozillademos.org/files/5405/gallery_4.jpg"></td>
        </tr>
        <tr>
            <td><img src="https://mdn.mozillademos.org/files/5407/gallery_5.jpg"></td>
            <td><img src="https://mdn.mozillademos.org/files/5409/gallery_6.jpg"></td>
            <td><img src="https://mdn.mozillademos.org/files/5411/gallery_7.jpg"></td>
            <td><img src="https://mdn.mozillademos.org/files/5413/gallery_8.jpg"></td>
          </tr>
    </table>
    <img id="frame" src="https://mdn.mozillademos.org/files/242/Canvas_picture_frame.png" width="132" height="150">
</body>
body {
  background: 0 -100px repeat-x url(https://mdn.mozillademos.org/files/5415/bg_gallery.png)
    #4f191a;
  margin: 10px;
}

img {
  display: none;
}

table {
  margin: 0 auto;
}

td {
  padding: 15px;
}

console.log(document.images)

function draw(){
    for(let i = 0; i < document.images.length; i++){
        //frame은 단지 캔버스에 그릴때 필요한 요소임으로 frame을 제외하고 그린다.
        if(document.images[i].getAttribute('id') != 'frame'){

            //canvas에 요소를 추가한다.
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d')
            //설정 값을 넣는다.
            canvas.setAttribute('width', 132)
            canvas.setAttribute('height', 150)
            //이미지 태그 부모요소에서 insertBefore를 한다. 
            //for 반복문을 돌기때문에 그림의 갯수만큼 canvas를 생성할 수 있다.
            document.images[i].parentNode.insertBefore(canvas, document.images[i])
            //각각 생성된 캔버스에 그림을 그린다.
            ctx.drawImage(document.images[i], 15, 20)
            //각 요소마다 frame을 캔버스에 그린다. 
            ctx.drawImage(document.getElementById('frame'),0,0)
        }
        
    }
}

이미지 비율 습성(scaling behavior) 제어하기

imageSmoothingEnabled 속성은 크기 조정 된 이미지가 부드럽게 처리되는지 ( true , 기본값) 그렇지 않은지 ( false )를 결정한다. imageSmoothingEnabled 속성을 가져 오면 마지막으로 설정된 값이 반환

이 속성은 픽셀 아트를 사용하는 게임 및 기타 앱에 유용하다. 이미지를 확대 할 때 기본 크기 조정 알고리즘이 픽셀을 흐리게한다. 픽셀의 선명도를 유지하려면 이 속성을 false 로 설정

다음과 같이 속성을 설정 할 수 있다.

ctx.mozImageSmoothingEnabled = false;
ctx.webkitImageSmoothingEnabled = false;
ctx.msImageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = false;

좋은 웹페이지 즐겨찾기