2013-10-02 2 views
14

저는 캔버스 요소를 조금 실험 해본 결과 어떻게 효과를 내는지 궁금합니다.캔버스와 자바 스크립트로 이미지를 픽셀 화하는 방법

나는 자습서와 데모 모음에서 찾고있는 것을 얻었지만 나머지 부분은 도움이 필요합니다. 내가 찾고있는 것은 mouseover에 이미지를 pixelate 한 다음 mouseout에 다시 초점을 맞추거나 un-pixelate하는 것입니다. 메인 회전 목마 아래에있는 블록 위로 마우스를 가져 가면 http://www.cropp.com/에서 좋은 효과의 예를 볼 수 있습니다.

여기가 link to a fiddle입니다. 당신이 크로스 도메인 이미지 (womp womp)를 사용할 수 없기 때문에 바이올린은 작동하지 않지만 지금까지는 내 코드를 볼 수 있습니다. 내 캔버스 객체 위에 마우스를 올리면 이미지를 픽셀화할 수 있지만 내가 얻으려고하는 것과는 다소 거꾸로 보입니다. 어떤 도움이나 조언이라도 대단히 감사하겠습니다.

var pixelation = 40, 
    fps = 120, 
    timeInterval = 1000/fps, 
    canvas = document.getElementById('photo'), 
    context = canvas.getContext('2d'), 
    imgObj = new Image(); 

imgObj.src = 'images/me.jpg'; 
imgObj.onload = function() {  
    context.drawImage(imgObj, 0, 0); 
}; 

canvas.addEventListener('mouseover', function() { 
    var interval = setInterval(function() { 
     context.drawImage(imgObj, 0, 0); 

     if (pixelation < 1) { 
      clearInterval(interval); 
      pixelation = 40; 
     } else { 
      pixelate(context, canvas.width, canvas.height, 0, 0); 
     } 
    }, timeInterval); 
}); 

function pixelate(context, srcWidth, srcHeight, xPos, yPos) { 

    var sourceX = xPos, 
     sourceY = yPos, 
     imageData = context.getImageData(sourceX, sourceY, srcWidth, srcHeight), 
     data = imageData.data; 

    for (var y = 0; y < srcHeight; y += pixelation) { 
     for (var x = 0; x < srcWidth; x += pixelation) { 

      var red = data[((srcWidth * y) + x) * 4], 
       green = data[((srcWidth * y) + x) * 4 + 1], 
       blue = data[((srcWidth * y) + x) * 4 + 2]; 

      for (var n = 0; n < pixelation; n++) { 
       for (var m = 0; m < pixelation; m++) { 
        if (x + m < srcWidth) { 
         data[((srcWidth * (y + n)) + (x + m)) * 4] = red; 
         data[((srcWidth * (y + n)) + (x + m)) * 4 + 1] = green; 
         data[((srcWidth * (y + n)) + (x + m)) * 4 + 2] = blue; 
        } 
       } 
      } 
     } 
    } 

    // overwrite original image 
    context.putImageData(imageData, xPos, yPos); 
    pixelation -= 1; 
} 
+3

데이터 URL을 통해 실제 이미지를 갖도록 업데이트했습니다. http://jsfiddle.net/xDt7U/1/ – Chad

답변

29

픽셀 화 효과를 만들기 위해 픽셀 버퍼를 반복 할 필요가 없습니다.

이미지 스무딩을 끄고 이미지의 작은 버전을 캔버스로 확대하기 만하면됩니다. 이는 또한 모든 이미지를 소스로 사용할 수 있음을 의미합니다 (CORS 와이즈).

예 :이 효과에 애니메이션을 적용 할 수

Fiddle demo

데모에서
// get a block size (see demo for this approach) 
var size = blocks.value/100, 
    w = canvas.width * size, 
    h = canvas.height * size; 

// draw the original image at a fraction of the final size 
ctx.drawImage(img, 0, 0, w, h); 

// turn off image aliasing 
ctx.msImageSmoothingEnabled = false; 
ctx.mozImageSmoothingEnabled = false; 
ctx.webkitImageSmoothingEnabled = false; 
ctx.imageSmoothingEnabled = false; 

// enlarge the minimized image to full size  
ctx.drawImage(canvas, 0, 0, w, h, 0, 0, canvas.width, canvas.height); 

의 성능이 브라우저로 픽셀을 반복하는 방법에 비해 매우 좋다고 볼 수는 처리한다 내부적으로 컴파일 된 코드의 "픽셀 화".

+0

와우는 멋지게 보이고 코드는 내가가는 것보다 훨씬 적습니다. 코드를 조금 설명해 주시겠습니까? pixelate 메서드가 무엇을하는지 이해하지만 toggleAnim이 작동하는 방식과 requestAnimationFrame에 대해 조금 궁금합니다. 어떻게 그 함수를 특정 지점 (픽셀 화)으로 움직이게하고 멈출 수 있습니까? 혹은 그 반대로도? – brandongray

+0

@brandongray toggleAnim은 성능 인상을 얻기 위해 픽셀 화를 애니메이션화하는 데모의 일부일뿐입니다. 나는 인라인 코멘트로 데모를 업데이트했다. requestAnimationFrame은 애니메이션을 동기화하여 업데이트를 모니터링하여 더 부드럽고 더 많은 실적을 낼 수있게 해주는 저수준 애니메이션 메서드입니다. 그것은 setTimout/setInterval보다 잘 작동합니다. – K3N

+0

@ ken-abdias-software 의견에 감사드립니다. 다른 분이 있고 도움을 기꺼이 원한다면 [이 바이올린] (http://jsfiddle.net/Ra9KQ/)을 살펴보십시오. 마우스 오버/아웃에서 작동하고 있지만 더럽다고 느낍니다. 예를 들어 마우스를 빠르게 마우스 오버 한 다음 밖으로 이동하면 화면이 부드럽게 보이지 않습니다. 마우스 오버 기능은 그 지점에서 계속 실행됩니다. 내가 원활하게 전환 할 수있는 방법에 대한 제안? 예를 들어 마우스를 빠르게 가리키고 마우스를 끈 경우 마우 스 효과가있는 지점에서 전환됩니다. 희망적으로 그것은 약간 이해된다. – brandongray

2

같은 효과를내는 자바 스크립트 라이브러리가 있습니다 (예 : pixelate 또는 close-pixelate).

관련 문제