受污染的画布可能无法出口

use*_*096 158 javascript html5-canvas

我想将我的画布保存为img.我有这个功能:

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

它给了我错误:

Uncaught SecurityError:无法在'HTMLCanvasElement'上执行'toDataURL':可能无法导出受污染的画布.

我该怎么办?

mar*_*rkE 157

出于安全原因,您的本地驱动器被声明为"其他域"并将污染画布.

(那是因为您最敏感的信息可能在您的本地驱动器上!).

在测试时尝试以下解决方法:

  • 将所有与页面相关的文件(.html,.jpg,.js,.css等)放在桌面上(不在子文件夹中).

  • 将您的图像发布到支持跨域共享的网站(如dropbox.com).确保将图像放在Dropbox的公共文件夹中,并在下载图像时设置交叉原点标记(var img = new Image(); img.crossOrigin ="anonymous"...)

  • 在开发计算机上安装Web服务器(IIS和PHP Web服务器都具有可在本地计算机上正常运行的免费版本).

  • 谢谢,设置img.crossOrigin属性帮助了我! (11认同)
  • @markE - 我从localStorage加载图像数据而不是从文件或任何网址加载,然后像添加文本一样对它进行一些操作.然后尝试使用toDataURL()将其恢复为localStorage.但它显示"未能在'HTMLCanvasElement'上执行'toDataURL':可能无法导出受污染的画布".在这种情况下,我没有使用任何exteranl文件或url来获得跨域问题.那为什么会导致这个错误呢? (5认同)
  • @Saijth - 您可能想要验证用于图像的路径.我也遇到了这个问题,因为我正在测试通过其IP(127.0.xx /)直接访问我的本地虚拟服务器,但是一些图像通过域(localhost /)链接.一旦我使用localhost而不是它就解决了.因此,请确保您没有遇到类似的事情. (2认同)
  • (1)从xampp webserver查看,localhost/file而不是c:/localdisk/file;那么 chrome 不会抱怨安全错误。(2) 或者在启动chrome时使用这个标志:--allow-file-access-from-files (2认同)

小智 117

在img标签中设置交叉原点为Anonymous

<img crossorigin="anonymous"></img>
Run Code Online (Sandbox Code Playgroud)

  • 但是在html5 canvas的情况下该怎么办,而不是img元素 (56认同)
  • 对于canvas元素,问题的来源始终是您正在绘制的一些图像(或图像).因此,您只需要在加载图像之前跟踪图像并设置其指示的crossOrigin属性. (9认同)
  • 它上午12点我在办公室,我发现这个简单的答案,这是纯粹的幸福 (7认同)
  • 这节省了我的一天! (2认同)
  • 值得注意的是,一旦加载图像,设置“image.crossOrigin = 'Anonymous'”将不起作用。但如果可以选择重新加载,您可以选择类似:`document.querySelectorAll('img').forEach(image =&gt; { image.crossOrigin = 'Anonymous'; image.src += ' '; })`。另请参阅[MDN 上的这篇文章](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image) 以供参考。 (2认同)
  • 这对我来说不起作用,因为全是小写,但“crossOrigin”有效。 (2认同)

skn*_*ght 14

如果有人看到我的答案,你可能会遇到这种情况:

1.尝试使用openlayers 3或4在画布中获取地图屏幕截图
2.并查看导出地图的示例
3.使用ol.source.XYZ渲染地图图层

答对了!

使用ol.source.XYZ.crossOrigin ='Anonymous'来解决您的混淆.或者像下面的代码:

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

  • 极好的。对于所有来源都很有用,例如 TileImage 等。 (2认同)

jdr*_*mer 12

就我而言,我正在从视频中绘制一个画布标签.为了解决受污染的画布错误,我必须做两件事:

<video id="video_source" crossorigin="anonymous">
    <source src="http://crossdomain.example.com/myfile.mp4">
</video>
Run Code Online (Sandbox Code Playgroud)
  • 确保在视频源响应中设置了Access-Control-Allow-Origin标头(正确设置crossdomain.example.com)
  • 将视频代码设置为crossorigin ="anonymous"


Ahm*_*abi 8

我使用useCORS: true选项解决了问题

 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();
    });
Run Code Online (Sandbox Code Playgroud)


meh*_*mpt 7

如果使用ctx.drawImage()函数,则可以执行以下操作:

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;
}
Run Code Online (Sandbox Code Playgroud)

在您的回调中,您现在可以使用ctx.drawImage并使用toDataURL

  • 这对我不起作用。仍然收到“受污染的画布可能无法导出。”错误消息。 (11认同)
  • 这个对我有用。谢谢。@SamSverko 确保在 img.src 之前设置属性。 (4认同)

小智 6

从 MDN 中查看启用 CORS 的映像。基本上,您必须有一个托管具有适当 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>
Run Code Online (Sandbox Code Playgroud)

您将能够将这些图像保存到 DOM 存储,就像它们是从您的域提供的一样,否则您将遇到安全问题。

var img = new Image,
    canvas = document.createElement("canvas"),
    ctx = canvas.getContext("2d"),
    src = "http://example.com/image"; // 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;
}
Run Code Online (Sandbox Code Playgroud)


Jat*_*nka 6

这个可以在laravel中顺利运行。

首先,您需要将受污染的画布转换为斑点。之后,您可以上传一个 blob 来提供服务并将其保存为图像。在 ajax 调用中返回图像 URL。

这是上传画布 blob 的 ajax 调用。

$("#downloadCollage").click(function(){
  canvas.toBlob(function(blob){

    var formDataToUpload = new FormData();
    formDataToUpload.append("_token", "{{ csrf_token() }}");
    formDataToUpload.append("image",  blob);

    $.ajax({
        url:"{{ route('selfie_collage_upload') }}",
        data: formDataToUpload,
        type:"POST",
        contentType:false,
        processData:false,
        cache:false,
        dataType:"json",
        error:function(err){
            console.error(err);
        },
        success:function(data){
            window.location.href= data.url;
        },
        complete:function(){
        }
    });
  },'image/png');
  link.click();
});
Run Code Online (Sandbox Code Playgroud)


Pra*_*thi 5

似乎您正在使用未设置正确的Access-Control-Allow-Origin标头的URL中的图像,因此也出现了问题。

  • 我为该文件提供了 Access-Control-Allow-Origin:* ,但仍然显示错误 (2认同)

Lud*_*fyn 5

就像@markE 答案的基础上一样。您可以通过本地服务器为您的网站提供服务。在本地服务器上不会出现此错误。

如果您的计算机上安装了 PHP(某些较旧的 MacOS 版本已预安装):

  1. 打开你的终端/cmd
  2. 导航到您的网站文件所在的文件夹
  3. 在此文件夹中,运行命令php -S localhost:3000
  4. 打开浏览器并在 URL 栏中转到localhost:3000。您的网站应该在那里运行。

或者


如果您的计算机上安装了 Node.js:

  1. 打开你的终端/cmd
  2. 导航到您的网站文件所在的文件夹
  3. 在此文件夹中,运行命令npm init -y
  4. 运行npm install live-server -gsudo npm install live-server -g在 Mac 上
  5. 运行live-server它应该会自动在浏览器中打开一个新选项卡并打开您的网站。

注意:请记住在文件夹的根目录中有一个index.html 文件,否则可能会遇到一些问题。