2013-10-02 59 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