被污染的画布可能无法导出


186

我想将画布保存为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";
}

它给我错误:

未捕获到的SecurityError:无法在“ HTMLCanvasElement”上执行“ toDataURL”:可能无法导出污染的画布。

我该怎么办?


在什么浏览器中?stackoverflow.com/a/21362569/476716声称这是一个错误。
OrangeDog 2014年

1
在Chrome和Firefox上
2014年

Answers:


178

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

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

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

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

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

  • 在开发计算机上安装Web服务器(IIS和PHP Web服务器都有免费版本,它们可以在本地计算机上正常运行)。


15
谢谢,设置img.crossOrigin属性对我有帮助!
zumek 2014年

5
@markE-我从localStorage加载图像数据,而不是从文件或任何URL加载,然后对其进行了一些操作,例如添加文本。然后尝试使用toDataURL()将其重新存储到localStorage。但是它显示“无法在'HTMLCanvasElement'上执行'toDataURL':可能无法导出污染的画布”。在这种情况下,我没有使用任何exteranl文件或url来获得跨域问题。那为什么会导致这个错误呢?
萨吉斯(Sajith)

2
@Saijth-您可能要验证用于图像的路径。我也有这个问题,因为我正在通过其IP(127.0.xx /)直接测试本地虚拟服务器的访问权限,但是有些映像是通过域(localhost /)链接的。一旦我使用本地主机,它就会解决。因此,请确保您不会遇到类似问题。
维克多D.15年

1
(1)从xampp Web服务器(本地主机/文件)而不是c:/ localdisk / file查看它;chrome不会抱怨安全错误。(2)或在启动chrome时使用此标志:--allow-file-access-from-files
mosh

1
只是增加了另一个可能的问题:如果您尝试导出包含带有ForeignObject的svg的画布,则某些浏览器会将其标记为已污染。
HairyFotr

128

在img标签中,将crossorigin设置为Anonymous。

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

60
但是在html5 canvas而不是img元素的情况下该怎么办
graphics123

11
对于canvas元素,问题的根源总是在于您要在其上绘制的某些图像。因此,您只需要在加载图像之前跟踪图像并按照指示设置其crossOrigin属性。
费尔南多·埃切维里亚

3
这挽救了我的一天!

1
乐于

9
它在办公室凌晨12点,我找到了一个简单的答案,这就是纯粹的幸福
Dheeraj

26

如果有人查看我的答案,那么您可能处于这种情况:

1.尝试使用openlayers(版本> = 3)在画布中获取地图屏幕快照。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"
         })
     });

1
太棒了。对所有来源都有用,例如TileImage等。
Phil

太棒了!正是我在寻找自己的东西,我可以轻松解决OpenLayers演示。
马克

我正在使用矢量平铺图层,并将此属性添加到源中后,但它也无法正常工作!
mahdi n75

正是我所需要的:)
Ray

16

如果使用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;
}

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


6
这对我不起作用。仍然收到Tainted canvases may not be exported.错误消息。
山姆·斯维尔科

1
这个对我有用。谢谢。@SamSverko确保在img.src之前设置属性。
aijogja

14

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

<video id="video_source" crossorigin="anonymous">
    <source src="http://crossdomain.example.com/myfile.mp4">
</video>
  • 确保在视频源响应中设置了Access-Control-Allow-Origin标头(正确设置crossdomain.example.com)
  • 将视频标签设置为具有crossorigin =“ anonymous”

5

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


您能否更精确地回答您的问题,因为我不太了解所有的概念。如何从服务器中获取该图像?
user3465096 2014年

您是从哪里获取该图像的,是从服务器还是其他服务器获取的?
Prasanna Aarthi 2014年

就像这样:loadImage(“ example.jpg”,0,0,500,300); 我可以将随机图像url或图像放在计算机的同一文件夹中,该文件夹仍保持不变
user3465096 2014年

是的,但是我只是在油漆上创建了图像,而且还是一样
user3465096 2014年

1
我为文件提供了Access-Control-Allow-Origin:*,但仍显示错误
Harikrishnan

4

我使用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();
    });

3

从MDN中检出[启用了CORS的图像] [1]。基本上,您必须具有托管带有适当的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>

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

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;
}


尽管此链接可以回答问题,但最好在此处包括答案的基本部分,并提供链接以供参考。如果链接的页面发生更改,仅链接的答案可能会失效。- 评分
的Gowtham湿婆

感谢您的通知。我只是从MDN链接中添加内容:)
BerlinaLi

1

就像建立在@markE的答案上一样(如果要创建本地服务器)。您在本地服务器上不会出现此错误。

如果您的计算机上安装了PHP:

  1. 打开您的终端/ cmd
  2. 导航到您的网站文件所在的文件夹
  3. 在此文件夹中,运行命令php -S localhost:3000←注意大写字母“ S”
  4. 打开浏览器,然后在URL栏中转到localhost:3000。您的网站应该在那里运行。

要么

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

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

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


0

我还通过添加useCORS : true,代码来解决此错误,例如-

html2canvas($("#chart-section")[0], {
        useCORS : true,
        allowTaint : true,
        scale : 0.98,
        dpi : 500,
        width: 1400, height: 900
    }).then();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.