使用 img.crossOrigin = "Anonymous" 将图像绘制到画布不起作用

Posted

技术标签:

【中文标题】使用 img.crossOrigin = "Anonymous" 将图像绘制到画布不起作用【英文标题】:Drawing images to canvas with img.crossOrigin = "Anonymous" doesn't work 【发布时间】:2014-06-01 03:21:57 【问题描述】:

在客户端独立的 JS 应用程序中,我正在尝试制作它,以便可以在画布上调用 toDataURL(),在该画布上我绘制了一些由 URL 指定的图像。即,我可以在文本框中输入要在画布上绘制的任何图像(托管在 imgur 上)的 URL,单击“绘制”按钮,它将在画布上绘制。最终用户应该能够将他们的最终渲染保存为单个图像,为此我使用 toDataURL()。

无论如何,直到他们真正解决了那个烦人的“操作不安全”错误(天哪,你要告诉最终用户他们可以用自己的数据做什么和不能做什么?)我遵循了一个变通方法,说将图像添加到 DOM 并将其 crossOrigin 属性设置为“Anonmyous”,然后将其绘制到画布上。

这是我的代码的完整工作简化版本(但实际上会有更多功能):

<!DOCTYPE html5>
<html>
<head>
<style>
#canvas border:10px solid green;background-color:black;
#imgbox border:2px solid black;
</style>
</head>
<body>
<canvas id="canvas" width=336 height=336></canvas>
<br><br>
<input size=60 id="imgbox">
<input type="submit" value="Draw" onclick=draw()>
<script>
function draw() 
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");
    var img = new Image();
    img.src = document.getElementById("imgbox").value;
    img.crossOrigin = "Anonymous";
    context.drawImage(img, 40, 40);

</script>
</body>
</html>

没有img.crossOrigin = "Anonymous"; 行,我可以在文本框中输入http://i.imgur.com/c2wRzfD.jpg 并单击绘图,它会起作用。但是,一旦我添加了那条线,整个东西就坏了,甚至根本不会被绘制到画布上。

我需要改变什么来解决这个问题?我真的需要能够为最终用户实现保存最终图像的功能,而编写 html5 规范的人故意引入了这个 bug,这非常烦人。

【问题讨论】:

对我来说,我的问题是我把crossOrigin 不小心拼成了全小写的crossorigin 【参考方案1】:

您必须在 src 之前设置 CORS 请求 - 只需将这些行换成:

img.crossOrigin = "Anonymous";
img.src = document.getElementById("imgbox").value;

您还需要为图像添加一个 onload 处理程序,因为加载是异步的:

img.onload = function() 
    context.drawImage(this, 40, 40);
    // call next step in your code here, f.ex: nextStep();
;
img.crossOrigin = "Anonymous";
img.src = document.getElementById("imgbox").value;

【讨论】:

等等,现在它只适用于一些图像。来自 imgur 的图像可以工作,但来自谷歌图像搜索的一些随机图像仍然不会绘制到画布上。例如,icons.iconarchive.com/icons/yellowicon/game-stars/256/… 根本不会被绘制。知道为什么吗? @Joey 你只能请求 CORS 使用,服务器可能会拒绝请求,导致图片加载失败。您需要检查哪些服务器允许,哪些不允许。对于那些不允许 CORS 使用的人,只需删除请求(crossOrigin 行)。对于无法使用 CORS 请求加载的图像,您需要将它们复制到您自己的服务器(与页面相同)或将它们移动到允许使用 cors 的另一台服务器。 (希望这是有道理的) 我把原图放到base64中绘制到canvas上后怎么知道原图是不是cors? 我不太明白。如果我以编程方式(使用 javascript)生成一个 base64 字符串,如果转换为 png 图像将只是随机像素,我可以将其写入画布而不会出现 cors 错误吗? 我对这个img.crossOrigin = "Anonymous"; 感到困惑,当它认为有跨域的事情发生时,浏览器似乎需要这个img.crossOrigin = "Anonymous";。无论是否包含此行,Chrome 都可以从toDataURL("image/png"); 函数中显示和链接/下载文件数据,而 Safari 9.x 在所有情况下都会失败,无一例外。这都在同一个域上。【参考方案2】:

当服务器需要授权才能访问图像时,该值应为:

img.crossOrigin = "Use-Credentials";

否则浏览器收到HTTP 401后会放弃。

【讨论】:

以上是关于使用 img.crossOrigin = "Anonymous" 将图像绘制到画布不起作用的主要内容,如果未能解决你的问题,请参考以下文章

js绝对地址图片转换成base64的方法

解决Image在canvas以及audiovideo在AudioContext下跨域问题

js url图片转bese64

有没有啥办法再前台js/jQuery中将img地址转换为文件流

js 图片转换base64 base64转换为file对象

捕获“访问控制允许来源不允许来源”错误