2013-10-02 6 views
14

Ich experimentiert ein wenig mit dem Canvas-Element und war neugierig, wie man einen Effekt abzieht.Wie man ein Bild mit Leinwand und Javascript pixelate

Ich habe etwas, was ich suche aus einer Sammlung von Tutorials und Demos, aber ich brauche etwas Hilfe, um den Rest des Weg dorthin zu bekommen. Was ich suche, ist ein Bild auf mouseover Pixelieren, dann refocus/un-pixelate es auf mouseout. Sie können ein gutes Beispiel für den Effekt bei http://www.cropp.com/ sehen, wenn Sie die Blöcke unterhalb des Hauptkarussells bewegen.

Hier ist ein link to a fiddle Ich begann. Die Geige funktioniert nicht, weil du keine domänenübergreifenden Bilder verwenden kannst (womp womp), aber du kannst meinen Code bis jetzt sehen. Wenn ich über mein Leinwandobjekt mische, kann ich das Bild verpixeln, aber es ist irgendwie umgekehrt zu dem, was ich zu bekommen versuche. Jede Hilfe oder Beratung wäre sehr willkommen.

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

Ihre Geige aktualisiert, um ein tatsächliches Bild zu haben, über eine Daten-URL: http://jsfiddle.net/xDt7U/1/ – Chad

Antwort

29

Sie müssen den Pixelpuffer nicht iterieren, um einen pixelierenden Effekt zu erzielen.

Schalten Sie einfach die Bildglättung aus und vergrößern Sie eine kleine Version des Bildes auf der Zeichenfläche. Dies bedeutet auch, dass Sie jedes Bild als Quelle (CORS-weise) verwenden können.

Beispiel:

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); 

In der Demo Du diesen Effekt animieren, um zu sehen, dass die Leistung ist sehr gut im Vergleich zu einem Pixel Iterieren Verfahren wie der Browser kümmert die "Pixelierung" intern im kompilierten Code.

+0

Wow, das sieht gut aus, und weit weniger Code als das, was ich hatte. Würde es Ihnen etwas ausmachen, den Code ein bisschen zu erklären? Ich verstehe, was die pixelate-Methode macht, aber ein wenig neugierig darauf, wie toggleAnim funktioniert und den requestAnimationFrame. Wie kann ich diese Funktion zu einem bestimmten Punkt animieren (pixelig) und dann anhalten? Oder umgekehrt? – brandongray

+0

@brandongray toggleAnim ist nur ein Teil der Demo, um die Pixelierung zu animieren, um einen Eindruck von der Leistung zu bekommen. Ich habe die Demo mit Inline-Kommentaren aktualisiert. requestAnimationFrame ist eine Low-Level-Animationsmethode, mit der Sie Animationen zur Überwachung von Aktualisierungen synchronisieren können, um sie flüssiger und leistungsfähiger zu machen. Es funktioniert besser als setTimout/setInterval. – K3N

+0

@ ken-abdias-software Ich schätze die Kommentare. Wenn Sie noch eine Minute haben und helfen wollen, können Sie sich [diese Geige] (http://jsfiddle.net/Ra9KQ/) ansehen. Ich habe es mit mouseover/out funktioniert, aber es fühlt sich schmutzig an. Zum Beispiel, wenn ich schnell über den Übergang rüber und dann den Übergang nicht glatt sehe. Die Mouse-Over-Funktion läuft an diesem Punkt weiter. Irgendwelche Vorschläge, wie ich es zum reibungslosen Übergang bringen könnte? Zum Beispiel, wenn ich schnell schweben und dann mit der Maus raus gehe, ist der Übergang von wo auch immer der Hover-Effekt kommt. Hoffentlich macht das einen Sinn. – brandongray

2

Denken Sie daran, es gibt ein paar Javascript-Bibliotheken, die denselben Effekt haben, zum Beispiel pixelate oder close-pixelate.

Verwandte Themen