본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


Html 캔버스/Html 캔버스 에니메이션

Html Canvas mosaic, Html 캔버스 모자이크 기능 제작

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2020. 8. 27.

 

* 게시글 하단의 제 깃허브 주소를 통해 실제 구현된 모습을 볼 수 있습니다

 

웹에서 이미지를 가져와서 다양하게 꾸미는 기능은 여러 라이브러리가 이미 존재합니다.

선 긋기, 명도, 채도 변경 및 이미지 추가 등 아주 다양한 기능을 제공 합니다.

그런데 이번에 작업 도중 사용자의 요구사항이 모자이크가 원하는 크기와 간격에 맞추어서 동작했으면 좋겠다고 하여\기존의 좋은 라이브러리를 사용 할 수가 없었습니다.

그리하여 제작해본 기능은 특정 영역안의 이미지를 크기와 간격을 조절하여 모자이크 처리하는 기능이였습니다.

 

이미지를 변경하고 적용하려면 div태그나 image테그를 활용하여 구현하는 것은 어렵습니다.

간단한 예로 선긋기 기능을 만든다고 한다면 사실 무엇을 어떻게 해야될 지 모르기 때문 입니다.

하지만 Html에서 제공하는 canvas는 다양한 그래픽과 관련된 기능을 제공합니다.

선긋기, 이미지추가, 사각형 그리기 등등..이미지와 관련된 작업을 하려면 캔버스를 활용 할 수 밖에 없었습니다.

 

기능 구현을 위해서 먼저 이미지를 가져오는 기능을 추가하였습니다.

캔버스에서 이미지를 가져오는 기능은 매우 쉽습니다.

var canvas = document.getElementById('canvas');  
var ctx = canvas.getContext('2d');
var img = new Image();   //이미지
img.src = 'img/test.png';
img.onload = function() {
    ctx.drawImage(img, 0 , 0, img.width, img.height);//이미지, 시작점x, 시작점y,넓이,높이
};

 

이미지를 가져온 다음에 모자이크와 관련하여 고려했던점이 4가지 입니다.

1. 모자이크 영역 가져오기

2. 모자이크 해주고 적용하기

3. 모자이크 한 곳에 지우개 기능 적용하기

4. 마우스가 움직 일 때 모자이크 되는 영역 보여주기

 

이렇게 하고 나니 사실 캔버스 1개로는 작업이 어려웠습니다.

마우스가 움직이면서 클릭할 때 영역을 보여주는 캔버스 1개,

마우스가 클릭하면 모자이크를 그려줄 캔버스 1개,

원본 이미지가 존재하는 캔버스 1개,

지우개 처리를 위해 존재하는 캔버스 1개

 

총 4개의 캔버스를 스타일 속성값 position absolute를 부여한 다음에 1개의 엘리먼트로 보이게 하였습니다.

이벤트로 x값과 y값을 가져오는 부분은 아래 방식을 사용하였습니다.

var canvas = document.getElementById('canvas');  
canvas.addEventListener('이벤트종류', function (event) {
    var x1 = event.clientX - offset().left-minusPosition;
    var y1 = event.clientY - offset().top-minusPosition;
});

function offset(){
    return $('캔버스를감싸고있는 테그').offset();
}

 

이미지를 선택하는 영역의 크기를 정해주고 난 뒤에 캔버스 객체에서 제공하는 getImageData를 활용하여 해당 영역의 이미지 정보값을 가져왔습니다.

해당 정보는 엄청난 크기의 이미지 값을 픽셀로 한 데이터가 존재합니다.

픽셀데이터 입니다.

 

또한 이미지데이터에는 넓이와 높이값이 존재합니다.

해당 값을 사용자가 정의한 값으로 나누어 준 다음에, 가져온 픽셀데이터 값을 putImageData 함수를 통해 변경해 주면 나름 그럴싸한 모자이크 기능이 완성이 됩니다.

 

var imageData  = ctx.getImageData(x, y, 선택한x영역, 선택한y영역);
var pixels = imageData.data;
var rows = imageData.width / 사용자정의_나눌값;
var cols = imageData.height / 사용자정의_나눌값;

for (var r = 0; r < rows; r++) {
    for (var c = 0; c < cols; c++) {
        //픽셀값 조정 계산식(생략)
    }
}

ctx.putImageData(imageData, x, y);

 

이러한 행위는 배열을 1개 선언하여 계속해서 담아둡니다.

담아둔 배열에는 지우는 형태인지, 모자이크를 하는 형태인지를 기록하여 둡니다.

var workingArray = [];  //그리고 지우는 행위를 담는 배열

hover.addEventListener('click', function (event) {
    if(그리는조건이라면){
        drawing(event);        
    } else {
        clearDrawing(event);
    }
});

//지우기 함수
function clearDrawing(event){
    var x1 = event.clientX - offset().left;
    var y1 = event.clientY - offset().top;
    ctx.save();
    ctx.clearRect(x1, y1, box_size, box_size);
    workingArray.push({x:x1, y:y1, type:'clear', box_size : box_size});
    ctx.restore();
}

//그리는 함수
function drawing(event){
    var x1 = event.clientX - offset().left;
    var y1 = event.clientY - offset().top;
    mosaic(x1, y1);  //모자이크 함수
    workingArray.push({x:x1, y:y1, type:'draw', box_size : box_size});
}

 

마지막에 사용자가 이미지 출력을 누르면, 배열에 저장된 행위를 출력할 캔버스에 엎어주면 비로소 완성 입니다.

이를 정리하여 보면,

 

#1번 캔버스 : 마우스가 움직이면서 클릭할 때 영역을 보여주는 캔버스를 작성합니다.

 - 해당 캔버스에서 마우스이동, 마우스클릭등 이벤트를 받도록 합니다.

 - 해당 캔버스는 마우스가 움직 일 때 영역을 보여주는 역할만 합니다.

 - 마우스가 클릭되면 해당 이벤트 정보를 바탕으로 #2번 캔버스에게 작업내용을 전달하여 줍니다.

 

#2번 캔버스 : 마우스가 클릭하면 모자이크를 그려줄 캔버스를 작성합니다.

 - #1번 캔버스의 클릭이벤트가 발생하면 이벤트 값에서 x좌표, y좌표를 받습니다.

 - 받은 좌표값에서 크기와, 지우기형태인지 아니면 그리기 형태인지를 판단 합니다.

 - 지우는 경우라면 clearRect 함수를 호출하여 본인의 영역에 지워 줍니다.

 - 그리는 경우라면 #3번 캔버스의 이미지 정보를 가져와서 모자이크를 한 뒤에 본인의 영역에 모자이크를 추가 합니다.

 

#3번 캔버스 : 원본 이미지가 존재하는 캔버스를 작성 합니다.

 - 해당 캔버스는 #2번 캔버스에게 정보를 제공합니다.

 - 이미지 출력을 하는 경우, 작업 행동이 모여있는 배열에서 정보를 가져와 그리기와 지우기를 하여 줍니다.

 - 그리는 경우는 본인의 이미지 정보를 제공하여 모자이크를 하여 줍니다.

 - 지우는 경우는 #4번 캔버스의 이미지 정보를 가져와서 채워주도록 합니다.

 - #4번 캔버스의 정보를 가져오는 이유는 본인의 데이터를 clearRect하면 회색 구멍이 생기기 때문 입니다.

 

#4번 캔버스 : 지우개 처리를 위해 존재하는 캔버스를 작성 합니다.

 - #3번 캔버스에게 정보만 제공합니다.

 - z-Index 값이 가장 낮으면서 먼저 생성이 되어야 합니다.

 

위 내용을 토대로 구현한 모습 입니다.

나름 괜찮았던 작업이였습니다. ^^

 

사용자가 지정한 나누는 값과, 사이즈등을 조절하면 위의 모양처럼 모자이크의 간격과 크기를 조정할 수 있습니다.

아래 제 깃허브를 통해서 기능을 확인 할 수 있습니다.

https://taeseungryu.github.io/sample/sampleView/mosaic/index.html

 

index

 

taeseungryu.github.io

 

이상으로 Html 캔버스를 활용하여 모자이크 기능제작에 대한 내용을 마치도록 하겠습니다.

문의사항이나 궁금한 점은 댓글 또는 메일로 연락주세요 :)

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글