Pregunta

¿Hay una manera fácil de cambiar el contenido de lienzo a la izquierda, dejar caer los píxeles más a la izquierda y mover a todos los demás hacia la izquierda?

¿Fue útil?

Solución

Usando getImageData y putImageData Puede implementar fácilmente un cambio de píxel por píxel. Por ejemplo:

// shift everything to the left:
var imageData = context.getImageData(1, 0, context.canvas.width-1, context.canvas.height);
context.putImageData(imageData, 0, 0);
// now clear the right-most pixels:
context.clearRect(context.canvas.width-1, 0, 1, context.canvas.height);

Otros consejos

Mira esto ejemplo de jsfiddle que usa ctx.translate y ctx.get/putImageData.

código fuente aquí

Cómo se hizo:

Si volver a dibujar lo que quieres cambiar no es demasiado lento, el Métodos de transformación de lienzo vale la pena usar.

get/putImageData También funcionará si solo desea cambiar el contenido actual del lienzo sin volver a dibujar. Esto no está exento de desventajas; Debe hacer una copia de la región de píxeles que se mueve y no se puede usar si extrae ninguna imagen de un dominio externo en su lienzo:

Cada vez que el método getImagedata () del contexto 2D de un elemento de lona cuyo indicador de origen se establece en falso se llama con argumentos correctos, el método debe lanzar una excepción de SecurityError.

En caso de que JSFIDDLE alguna vez falle, aquí está el código:

HTML:

<a href="javascript:doIt()">shift 25 pixels to the left using `translate`</a><br>
<a href="javascript:shiftImage()">shift 25 pixels to the left using `getImageData/putImageData`</a><br>
<canvas id="canvas" width="600" height="200"></canvas>

JS:

var canvas = document.getElementById( "canvas" ),
    ctx = canvas.getContext( "2d" );

var xOff = 0;
var redraw = function() {
        ctx.clearRect(0, 0, 600, 200);
        ctx.save();
        ctx.translate(xOff, 0);

        ctx.font = "100px Arial";
        ctx.fillText( "Google", 20, 130 );

        ctx.restore();
};

window.doIt = function() {
    xOff -= 25;
    redraw();
}

redraw();

var shiftContext = function(ctx, w, h, dx, dy) {
  var clamp = function(high, value) { return Math.max(0, Math.min(high, value)); };
  var imageData = ctx.getImageData(clamp(w, -dx), clamp(h, -dy), clamp(w, w-dx), clamp(h, h-dy));
  ctx.clearRect(0, 0, w, h);
  ctx.putImageData(imageData, 0, 0);
}

window.shiftImage = function() {
  shiftContext(ctx, 600, 200, -25, 0);   
}


var shiftContext = function(ctx, w, h, dx, dy) {
  var clamp = function(high, value) { return Math.max(0, Math.min(high, value)); };
  var imageData = ctx.getImageData(clamp(w, -dx), clamp(h, -dy), clamp(w, w-dx), clamp(h, h-dy));
  ctx.clearRect(0, 0, w, h);
  ctx.putImageData(imageData, 0, 0);
};

window.shiftImage = function() {
  shiftContext(ctx, 600, 200, -25, 0);   
};

Chicos perfectos y gracias. Aquí hay una versión simplificada del código de Ellisbben, funciona una delicia para algunos gráficos de desplazamiento que he construido:

function shift_canvas(ctx, w, h, dx, dy) {
  var imageData = ctx.getImageData(0, 0, w, h);
  ctx.clearRect(0, 0, w, h);
  ctx.putImageData(imageData, dx, dy);
}

Si desea mover todo el contenido, puede usar una operación compuesta Global Copy con una sola drawImage (), dibujando el lienzo sobre sí mismo. No parece funcionar en Safari, pero es una locura rápidamente en Chrome.

ctx.globalCompositeOperation = "copy";
ctx.drawImage(ctx.canvas,-widthOfMove, 0);
// reset back to normal for subsequent operations.
ctx.globalCompositeOperation = "source-over"

Me preguntaba si había una manera conveniente de hacer esto. Terminé presentando esta función de traducción, que no requiere ninguna de las funciones de datos de imagen (muy lentas):

function translate(x, y) {
    ctxBuffer.clearRect(0,0,canvasBuffer.width,canvasBuffer.height); //clear buffer
    ctxBuffer.drawImage(canvasDisplay,0,0); //store display data in buffer
    ctxDisplay.clearRect(0,0,canvasDisplay.width,canvasDisplay.height); //clear display
    ctxDisplay.drawImage(canvasBuffer,x,y); //copy buffer to display
}

He hecho una demostración rápida aquí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top