tainted not may imagenes htmlcanvaselement from failed exported canvases javascript canvas html5-canvas opera

javascript - not - htmlcanvaselement todataurl()



contexto drawImage/canvas toDataURL retraso significativamente en la ópera móvil (2)

No tengo una solución muy buena, pero sugeriría no manipular un lienzo invisible a través del dom haciendo que sea invisible.

En lugar de

var canvas = document.getElementById(''canvas'');

Tratar

var canvas = document.createElement(''canvas''); canvas.width = video.width; canvas.height = video.height; canvas.getContext(''2d'').drawImage(video, 0, 0)

De esta forma está separado del DOM.

También por qué no usar

canvas.toDataURL("image/jpg")?

EDITAR: Además, si lo está diseñando, ¿ha probado otros navegadores? ¿Qué le está restringiendo a Opera en los otros navegadores disponibles o usando phonegap?

EDIT2: Pensando en ello, Canvas también tiene otras dos opciones para colocar esa foto en el lugar que desea buscar en dos. Esos dos son:

var imgData = canvas.getContext(''2d'').getImageData(0,0,canvas.width,canvas.height);

-o-

canvas.getContext(''2d'').putImageData(imgData,0,0);

Estos dos ignoran cualquier escalado que hayas hecho al contexto, pero he descubierto que son mucho más directos y a menudo más rápidos. Son una alternativa sólida a toDaTURL y drawImage, pero los datos de imagen que pones y obtienes de estos se codifican como una matriz en el siguiente formato:

[r1, b1, g1, a1, r2, b2, g2, a2 ​​....]

puedes encontrar documentación para ellos aquí:

http://www.w3schools.com/tags/canvas_putimagedata.asp http://www.w3schools.com/tags/canvas_getimagedata.asp

Tengo un poco de Javascript que se ejecuta en una tableta de Android , ejecutando Opera Mobile 12 . La tableta está unida a la pared en una oficina, por lo que es utilizada por todos los que trabajan en esta oficina, como un sistema de cronometraje (es decir, lo usan para marcar el reloj / dejar el trabajo). Este javascript toma una foto del usuario cuando se produce un evento determinado y luego convierte esta foto en una URL de datos para que pueda enviarse a un servidor. Sin embargo, todo esto se ejecuta en segundo plano: los elementos de video y canvas están configurados para display:none; .

Aquí está el código que maneja la interacción de la cámara web:

var Webcam = function() { var video = document.getElementById(''video''); var stream_webcam = function(stream) { video.addEventListener(''loadedmetadata'', function(){ video.play(); }, false); video.src = window.URL.createObjectURL(stream); } // start recording if (navigator.getUserMedia) navigator.getUserMedia({video: true}, stream_webcam); else _error("No navigator.getUserMedia support detected!"); var w = {}; w.snap = function(callback) { var canvas = document.getElementById(''canvas''); canvas.getContext(''2d'').drawImage(video, 0, 0, canvas.width, canvas.height); // delay is incurred in writing to canvas on opera mobile setTimeout(function() { callback(canvas.toDataURL()); }, 1); }; return w; }

w.snap(callback) cuando el usuario presiona un botón determinado. El problema es que hay un desfase significativo entre la llamada a drawImage y una imagen que realmente se dibuja en el lienzo. Aquí está el problema que ocurre :

  • El usuario 1 usa la tableta, presiona el botón, su foto se "ajusta" y se envía al servidor. El servidor recibe una imagen en blanco, transparente. (No es el mismo problema que el lienzo html5 para DataURL devuelve una imagen en blanco ; los datos que se envían al servidor son sustancialmente menores para la primera imagen, porque están en blanco)
  • Unos minutos más tarde, el usuario 2 usa la tableta y presiona el botón, y tiene su foto "ajustada". El servidor recibe la foto del usuario 1.
  • Más tarde, el usuario 3 hace lo mismo y el servidor obtiene una foto del usuario 2.

Así que supongo que la llamada a toDataURL() devuelve datos antiguos porque drawImage() no lo hace. (Leí en alguna parte que es asíncrono, pero no puedo confirmarlo y no encuentro ninguna forma de adjuntar un evento cuando termina de dibujar).

He intentado:

  • cambiando el tiempo de espera en snap() a una variedad de valores. Lo más que intenté fue 2000, pero ocurrió el mismo problema. (Si alguien sugiere números más altos, me complace probarlos, pero no quiero ir mucho más alto porque si voy demasiado alto, existe la posibilidad de que el usuario 3 se tome una foto incluso antes de que haya procesado el usuario 2 foto, lo que significa que podría perderlo por completo!)
  • hacer que el lienzo dibuje algo cuando la página se carga por primera vez, pero eso no lo solucionó: cuando el usuario 1 fue fotografiado, el servidor recibió la foto que se tomó cuando se cargó la página, en lugar de la foto del usuario 1.
  • "obtener" el elemento canvas de nuevo, utilizando getElementById , antes de llamar toDataURL .

Algunas notas más:

  • Esto funciona bien en mi computadora (macbook air) en Chrome y Opera.
  • No puedo replicarlo de manera confiable usando un depurador (vinculándolo a la tableta usando Opera Dragonfly).
  • AFAIK Opera Mobile es el único navegador de Android que admite getUserMedia y, por lo tanto, puede tomar fotos.
  • Si elimino la display:none; desde el video y el canvas , funciona correctamente (en la tableta). El problema solo ocurre cuando el video y el lienzo tienen display:none; conjunto.

Como la página es una aplicación de una sola página sin necesidad de desplazarse ni acercarse, una posible solución es mover el video y el lienzo debajo de la página, luego deshabilitar el desplazamiento con javascript (es decir, desplazarse hacia arriba cada vez que el usuario se desplaza).

Pero preferiría una solución adecuada que una solución alternativa, si es posible.