2011-04-28 13 views
15

Parece que la alteración de las dimensiones de un lienzo borra cualquier dibujo ya hecho en ese lienzo.evento de JavaScript para cambiar el tamaño de lienzo

¿Hay un evento que dispara sobre lienzo cambiar el tamaño, por lo que puede conectarlo y volver a dibujar cuando ocurre?

+0

¿En cuántos lugares diferentes de su código está redimensionando el lienzo?¿No podría simplemente llamar a su función de redibujado después de haber cambiado el tamaño? – robertc

+0

No quiero afirmar que soy el único que cambia el tamaño de un lienzo en particular. – rampion

+1

No sé si funcionaría para usted, pero estoy redibujando cada cuadro con 'requestAnimationFrame()' - Estoy recibiendo 60fps y no tengo que preocuparme por volver a dibujar cuando cambie de tamaño – Zac

Respuesta

10

lo general, no desea comprobar estrictamente para un evento de cambio de tamaño, ya que disparan mucho cuando haces un cambio de tamaño dinámico, así como $ .resize (ventana) en jQuery y por lo que soy consciente de que no hay cambio de tamaño nativo evento en elementos (there is on window). Me gustaría comprobar que en un intervalo lugar:

function onResize(element, callback){ 
    var elementHeight = element.height, 
     elementWidth = element.width; 
    setInterval(function(){ 
     if(element.height !== elementHeight || element.width !== elementWidth){ 
     elementHeight = element.height; 
     elementWidth = element.width; 
     callback(); 
     } 
    }, 300); 
} 

var element = document.getElementsByTagName("canvas")[0]; 
onResize(element, function(){ alert("Woo!"); }); 
+2

lo suficientemente bueno, suponer. Usar 'setInterval()' para algo que debería ser interactivo me hace estremecer cada vez. – rampion

+5

Es mejor conectarse al evento resize() y (re) iniciar un temporizador de redibujado cada vez que se dispara. Solo cuando se agota el temporizador de redibujado, se dibuja la imagen. – paniq

+0

¿Esto realmente funciona? MDN dice que solo 'ventana' desencadena un evento de cambio de tamaño – oberhamsi

1

guardar el estado lienzo como propiedad imageData y luego vuelve a dibujar después de cambiar el tamaño de

var imgDat=ctx.getImageData(0,0,ctx.canvas.width,ctx.canvas.height) 

después de cambiar el tamaño de

ctx.putImageData(imgDat,0,0) 
+0

el problema es detectar cuándo han ocurrido los cambios de tamaño. – rampion

5

Kit de respuesta de Sunde hará una gran cantidad de trabajo innecesario, mientras que la ventana del navegador no se cambia de tamaño. Es mejor para comprobar si el evento consiguió cambiar de tamaño en respuesta a un evento de navegador y el próximo ignorar cambiar el tamaño de eventos para una determinada cantidad de tiempo tras el cual se hace una comprobación de nuevo (esto hará que dos cheques después entre si en rápida sucesión y el código podría ser mejorado para evitar esto, pero probablemente entiendas la idea).

(function(){ 
     var doCheck = true; 
     var check = function(){ 
      //do the check here and call some external event function or something. 
     }; 
     window.addEventListener("resize",function(){ 
      if(doCheck){ 
       check(); 
       doCheck = false; 
       setTimeout(function(){ 
        doCheck = true; 
        check(); 
       },500) 
      } 
     }); 
})(); 

Tenga en cuenta que el código anterior se ha escrito a ciegas y no se controla.

6

la respuesta de David Mulder es una mejora, pero parece que va a desencadenar después de esperar el tiempo de espera milisegundos después del evento de cambio de tamaño primera. En otras palabras, si ocurren más cambios de tamaño antes del tiempo de espera, no reinicia el temporizador. Estaba buscando lo opuesto; Yo quería algo que esperar un poco de tiempo para que el cambio de tamaño de stop, y luego el fuego después de un cierto período de tiempo después de la última uno. El siguiente código hace eso.

El ID de cualquier temporizador actualmente en ejecución estará en timer_id. Entonces, cada vez que hay un cambio de tamaño, verifica si ya hay un tiempo corriendo. Si es así, cancela ese y comienza uno nuevo.

function setResizeHandler(callback, timeout) { 
    var timer_id = undefined; 
    window.addEventListener("resize", function() { 
     if(timer_id != undefined) { 
      clearTimeout(timer_id); 
      timer_id = undefined; 
     } 
     timer_id = setTimeout(function() { 
      timer_id = undefined; 
      callback(); 
     }, timeout); 
    }); 
} 

function callback() { 
    // Here's where you fire-after-resize code goes. 
    alert("Got called!"); 
} 
setResizeHandler(callback, 1500); 
1

No he encontrado ninguna acumulación de eventos para detectar nuevas dimensiones de la lona, ​​así que traté de encontrar una solución para dos escenarios.

function onresize() 
{ 
    // handle canvas resize event here 
} 

var _savedWidth = canvas.clientWidth; 
var _savedHeight = canvas.clientHeight; 
function isResized() 
{ 
    if(_savedWidth != canvas.clientWidth || _savedHeight != canvas.clientHeight) 
    { 
     _savedWidth = canvas.clientWidth; 
     _savedHeight = canvas.clientHeight; 
     onresize(); 
    } 
} 

window.addEventListener("resize", isResized); 

(new MutationObserver(function(mutations) 
{ 
    if(mutations.length > 0) { isResized(); } 
})).observe(canvas, { attributes : true, attributeFilter : ['style'] }); 
  1. Para detectar cualquier cambio canvas.style JavaScript, la API MutationObserver es bueno para. No detecta una propiedad de estilo específico, pero en este caso, es suficiente para comprobar si canvas.clientWidth y canvas.clientHeight ha cambiado.

  2. Si el tamaño del lienzo se declara en una etiqueta de estilo con una unidad de porcentaje, tenemos un problema para interpretar los selectores css correctamente (>, *, :: before, ...) utilizando JavaScript. Creo que en este caso la mejor manera es establecer un controlador window.resize y también verificar el tamaño del cliente canvas.

Cuestiones relacionadas