2013-10-02 78 views
14

我一直在嘗試使用canvas元素,並且很好奇如何取消效果。如何使用畫布和javascript使圖像像素化

我從教程和演示的集合中找到了一些我需要的東西,但是我需要一些幫助來獲得剩餘的方法。我正在尋找的是在mouseover上對圖像進行像素化,然後在mouseout上重新對焦/取消像素化。當鼠標懸停在主傳送帶下面的塊上時,您可以在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

更新你的小提琴以通過數據網址獲得實際圖像: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/)。我已經在mouseover/out上工作,但感覺很髒。例如,如果我快速將鼠標移過來,然後出現轉換看起來不順利。鼠標懸停功能繼續在該點運行。關於如何讓它順利過渡的任何建議?例如,如果我快速懸停,然後將鼠標懸停在懸停效果所達到的任何點上。希望這是有道理的。 – brandongray