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

IT技术 javascript html5-canvas
2021-01-16 16:52:47

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

它给了我错误:

未捕获的安全错误:无法在“HTMLCanvasElement”上执行“toDataURL”:可能无法导出受污染的画布。

我该怎么办?

6个回答

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

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

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

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

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

  • 在您的开发计算机上安装一个网络服务器(IIS 和 PHP 网络服务器都有免费版本,可以在本地计算机上很好地运行)。

@markE - 我从 localStorage 加载图像数据,而不是从文件或任何 url 加载,然后对其进行一些操作,例如添加文本。然后尝试使用 toDataURL() 将其恢复到 localStorage。但它显示“无法在‘HTMLCanvasElement’上执行‘toDataURL’:可能无法导出受污染的画布”。在这种情况下,我没有使用任何外部文件或 url 来解决跨域问题。那为什么会导致这个错误呢?
2021-03-15 16:52:47
(1)从xampp webserver查看,localhost/file而不是c:/localdisk/file;那么 chrome 不会抱怨安全错误。(2) 或者在启动chrome时使用这个标志:--allow-file-access-from-files
2021-03-15 16:52:47
只是添加另一个可能的问题:如果您尝试导出包含带有 ForeignObject 的 svg 的画布,某些浏览器会将其标记为已污染。
2021-03-15 16:52:47
@Saijth - 您可能想要验证用于图像的路径。我也遇到了这个问题,因为我正在测试通过其 IP (127.0.xx/) 直接访问我的本地虚拟服务器,但有些图像是通过域 (localhost/) 链接的。一旦我使用了本地主机,它就解决了。所以确保你没有遇到类似的事情。
2021-03-18 16:52:47
谢谢,设置 img.crossOrigin 属性对我有帮助!
2021-03-29 16:52:47

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

<img crossorigin="anonymous"></img>
这对我不起作用,因为所有的小写字母,但都crossOrigin有效。
2021-03-16 16:52:47
对于画布元素,问题的根源始终是您在其上绘制的某些图像(或多个图像)。因此,您只需要在加载图像之前跟踪图像并按照指示设置其 crossOrigin 属性。
2021-03-22 16:52:47
但是在 html5 canvas 的情况下该怎么做,而不是 img 元素
2021-03-31 16:52:47
凌晨 12 点我在办公室,我找到了这个简单的答案,这就是纯粹的幸福
2021-04-01 16:52:47
值得注意的是,image.crossOrigin = 'Anonymous'一旦加载图像,设置将无济于事。但是,如果重装是一种选择,你可以去类似:document.querySelectorAll('img').forEach(image => { image.crossOrigin = 'Anonymous'; image.src += ' '; })另请参阅MDN 上的这篇文章以供参考。
2021-04-01 16:52:47

如果有人对我的回答有意见,您可能处于这种情况:

1. 尝试使用 openlayers (version >= 3) 在 canvas 中获取地图截图
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"
     })
 });

在 OpenLayers6 中,ES6 有所改变。但是,代码是相似的。

import { XYZ } from 'ol/source'
import { Tile as TileLayer } from 'ol/layer'
const baseLayer = new TileLayer({
    name : 'basic',
    source: new XYZ({
      url: 'example.tile.com/x/y/z', // your tile url
      crossOrigin: 'Anonymous',
      // remove this function config if the tile's src is nothing to decorate. It's usually to debug the src
      tileLoadFunction: function(tile, src) {
        tile.getImage().src = src
      }
    })
  })

此外,如果在您自己的服务器中请求切片,请不要忘记在响应标头中设置access-control-allow-origin: *access-control-allow-origin: [your whitelist origins]
像这样: 在此处输入图片说明 更多细节,还有这个

太棒了!正是我自己在寻找的东西,我正在做的 OpenLayers 演示的简单修复。
2021-03-12 16:52:47
我正在使用矢量切片图层,并将此属性添加到源后,但它也不起作用!
2021-03-16 16:52:47
极好的。适用于所有来源,如 TileImage 等。
2021-03-17 16:52:47
正是我需要的:)
2021-03-22 16:52:47
我用的是ol6。但它不起作用,添加此行后没有变化
2021-03-31 16:52:47

如果您正在使用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

这个对我有用。谢谢。@SamSverko 确保在 img.src 之前设置属性。
2021-03-12 16:52:47
不起作用。说被 CORS 政策阻止
2021-03-20 16:52:47
这对我不起作用。仍然收到Tainted canvases may not be exported.错误消息。
2021-04-04 16:52:47

就我而言,我正在从带有类似canvas.drawImage(video, 0, 0). 为了解决受污染的画布错误,我必须做两件事:

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