Los lienzos contaminados no se pueden exportar


187

Quiero guardar mi lienzo en un img. Tengo esta función:

function save() {
    document.getElementById("canvasimg").style.border = "2px solid";
    var dataURL = canvas.toDataURL();
    document.getElementById("canvasimg").src = dataURL;
    document.getElementById("canvasimg").style.display = "inline";
}

Me da error:

SecurityError no capturado: no se pudo ejecutar 'toDataURL' en 'HTMLCanvasElement': los lienzos contaminados no se pueden exportar.

¿Qué tengo que hacer?


¿En que navegador? stackoverflow.com/a/21362569/476716 afirma que esto es un error.
OrangeDog

1
en Chrome y
Firefox

Respuestas:


180

Por razones de seguridad, su unidad local se declara como "otro dominio" y manchará el lienzo.

(¡Esto se debe a que su información más confidencial probablemente esté en su disco local!).

Durante las pruebas, pruebe estas soluciones alternativas:

  • Coloque todos los archivos relacionados con la página (.html, .jpg, .js, .css, etc.) en su escritorio (no en subcarpetas).

  • Publique sus imágenes en un sitio que admita el intercambio entre dominios (como dropbox.com). Asegúrese de poner sus imágenes en la carpeta pública de Dropbox y también establecer el indicador de origen cruzado al descargar la imagen (var img = new Image (); img.crossOrigin = "anónimo" ...)

  • Instale un servidor web en su computadora de desarrollo (los servidores web IIS y PHP tienen ediciones gratuitas que funcionan bien en una computadora local).


16
¡Gracias, configurar la propiedad img.crossOrigin me ayudó!
zumek

55
@markE: cargué datos de imágenes de localStorage en lugar de cargarlos desde un archivo o cualquier url, luego le hice alguna manipulación, como agregar un texto. Luego trató de devolverlo a localStorage usando toDataURL (). Pero muestra "Error al ejecutar 'toDataURL' en 'HTMLCanvasElement': los lienzos contaminados no se pueden exportar". En este caso, no estoy usando ningún archivo exteranl o url para obtener un problema de dominio cruzado. Entonces, ¿por qué está causando este error?
Sajith

2
@Saijth: es posible que desee verificar la ruta utilizada para las imágenes. También tuve este problema porque estaba probando el acceso directo a mi servidor virtual local a través de su IP (127.0.xx /) pero algunas de las imágenes estaban vinculadas a través del dominio (localhost /). Una vez que usé el localhost en su lugar funcionó. Así que asegúrese de no encontrarse con algo así.
Victor D.

1
(1) Visualícelo desde el servidor web xampp, localhost / file en lugar de c: / localdisk / file; entonces Chrome no se quejará de Error de seguridad. (2) O use esta bandera al iniciar Chrome: --allow-file-access-from-files
mosh

1
Simplemente agregue otro posible problema: si está intentando exportar un lienzo que contiene un svg con un ForeignObject, algunos navegadores lo marcarán como contaminado.
HairyFotr

128

En la etiqueta img establezca crossorigin en Anónimo.

<img crossorigin="anonymous"></img>

61
Pero qué hacer en el caso de lienzo html5, no elementos img
graphics123

11
En el caso de un elemento de lienzo, la fuente del problema siempre es con alguna imagen (o imágenes) que está dibujando en él. Por lo tanto, solo necesita rastrear la imagen y establecer su atributo crossOrigin como se indica, antes de cargarla.
Fernando Echeverria

3
Esto me salvó el día!
Chang

1
Feliz de ayudar :)
Annia Martinez

9
su im 12 a.m. en el cargo y que esta respuesta es simple, esto es pura felicidad
Dheeraj

26

Si alguien ve mi respuesta, tal vez en esta condición:

1. Intentando obtener una captura de pantalla de mapa en lienzo usando capas abiertas (versión> = 3)
2. Y vimos el ejemplo de exportación de mapa
3. Usando ol.source.XYZ para representar la capa del mapa

¡Bingo!

Usando ol.source.XYZ.crossOrigin = 'Anónimo' para resolver su confusión. O como el siguiente código:

     var baseLayer = new ol.layer.Tile({
         name: 'basic',
         source: new ol.source.XYZ({
             url: options.baseMap.basic,
             crossOrigin: "Anonymous"
         })
     });

1
fantástico. Útil para todas las fuentes, como TileImage y también.
Phil

Fatastic! Exactamente lo que estaba buscando, solución fácil para una demostración de OpenLayers que estoy haciendo.
Marc

Estoy usando capas de mosaicos vectoriales y después de agregar esta propiedad a la fuente, ¡pero tampoco funciona!
Mahdi n75

Exactamente lo que necesitaba :)
Ray

17

Si está utilizando la ctx.drawImage()función, puede hacer lo siguiente:

var img = loadImage('../yourimage.png', callback);

function loadImage(src, callback) {
    var img = new Image();

    img.onload = callback;
    img.setAttribute('crossorigin', 'anonymous'); // works for me

    img.src = src;

    return img;
}

Y en su devolución de llamada ahora puede usarlo ctx.drawImagey exportarlo usandotoDataURL


66
Esto no funcionó para mí. Aún recibo el Tainted canvases may not be exported.mensaje de error.
Sam Sverko

1
esto funciona para mi. Gracias. @SamSverko asegúrese de establecer el atributo antes de img.src.
aijogja

14

En mi caso, estaba dibujando en una etiqueta de lienzo de un video. Para abordar el error del lienzo contaminado, tuve que hacer dos cosas:

<video id="video_source" crossorigin="anonymous">
    <source src="http://crossdomain.example.com/myfile.mp4">
</video>
  • Asegúrese de que el encabezado Access-Control-Allow-Origin esté configurado en la respuesta de la fuente de video (configuración adecuada de crossdomain.example.com)
  • Configure la etiqueta de video para que tenga crossorigin = "anónimo"

5

Parece que está utilizando una imagen de una URL que no ha configurado el encabezado correcto de Access-Control-Allow-Origin y, por lo tanto, el problema. Puede obtener esa imagen de su servidor y obtenerla de su servidor para evitar problemas de CORS.


¿Podría ser más preciso sobre su respuesta, porque realmente no conozco todo ese concepto? ¿Cómo obtengo esa imagen de mi servidor?
user3465096

¿desde dónde estás buscando esa imagen, es desde tu servidor o algún otro?
Prasanna Aarthi

Va así: loadImage ("ejemplo.jpg", 0, 0, 500, 300); Puedo poner url o imagen de imagen aleatoria en la misma carpeta en mi computadora, sigue siendo la misma
user3465096

Sí, pero yo sólo imagen creada en la pintura y todavía es el mismo
user3465096

1
Di Access-Control-Allow-Origin: * para el archivo, pero aún muestra el error
Harikrishnan

5

Resolví el problema usando la useCORS: trueopción

 html2canvas(document.getElementsByClassName("droppable-area")[0], { useCORS:true}).then(function (canvas){
        var imgBase64 = canvas.toDataURL();
        // console.log("imgBase64:", imgBase64);
        var imgURL = "data:image/" + imgBase64;
        var triggerDownload = $("<a>").attr("href", imgURL).attr("download", "layout_"+new Date().getTime()+".jpeg").appendTo("body");
        triggerDownload[0].click();
        triggerDownload.remove();
    });

3

Echa un vistazo a [imagen habilitada CORS] [1] de MDN. Básicamente, debe tener un servidor que aloje imágenes con el encabezado apropiado Access-Control-Allow-Origin.

<IfModule mod_setenvif.c>
    <IfModule mod_headers.c>
        <FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">
            SetEnvIf Origin ":" IS_CORS
            Header set Access-Control-Allow-Origin "*" env=IS_CORS
        </FilesMatch>
    </IfModule>
</IfModule>

Podrá guardar esas imágenes en el almacenamiento DOM como si se hubieran servido desde su dominio; de lo contrario, se encontrará con un problema de seguridad.

var img = new Image,
    canvas = document.createElement("canvas"),
    ctx = canvas.getContext("2d"),
    src = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"; // insert image url here

img.crossOrigin = "Anonymous";

img.onload = function() {
    canvas.width = img.width;
    canvas.height = img.height;
    ctx.drawImage( img, 0, 0 );
    localStorage.setItem( "savedImageData", canvas.toDataURL("image/png") );
}
img.src = src;
// make sure the load event fires for cached images too
if ( img.complete || img.complete === undefined ) {
    img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
    img.src = src;
}


Si bien este enlace puede responder la pregunta, es mejor incluir las partes esenciales de la respuesta aquí y proporcionar el enlace como referencia. Las respuestas de solo enlace pueden volverse inválidas si la página vinculada cambia. - De la opinión
Gowtham Shiva

Gracias por la noticia. Acabo de agregar el contenido del enlace de MDN :)
BerlinaLi

1

Solo como una compilación de la respuesta de @ markE, si desea crear un servidor local. No tendrá este error en un servidor local.

Si tienes PHP instalado en tu computadora:

  1. Abre tu terminal / cmd
  2. Navegue a la carpeta donde están los archivos de su sitio web
  3. Mientras está en esta carpeta, ejecute el comando php -S localhost:3000← Observe la 'S' mayúscula
  4. Abra su navegador y en la barra de URL vaya a localhost: 3000 . Su sitio web debería estar funcionando allí.

o

Si tiene Node.js instalado en su computadora:

  1. Abre tu terminal / cmd
  2. Navegue a la carpeta donde están los archivos de su sitio web
  3. Mientras esté en esta carpeta, ejecute el comando npm init -y
  4. Ejecutar npm install live-server -go sudo npm install live-server -gen una Mac
  5. Ejecute live-servery debería abrir automáticamente una nueva pestaña en el navegador con su sitio web abierto.

Nota: recuerde tener un archivo index.html en la raíz de su carpeta o de lo contrario podría tener algunos problemas.


0

También resolví este error agregando useCORS : true,mi código como -

html2canvas($("#chart-section")[0], {
        useCORS : true,
        allowTaint : true,
        scale : 0.98,
        dpi : 500,
        width: 1400, height: 900
    }).then();
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.