如何将图像从 url 沿侧输入类型文件加载到 html5 画布?
Posted
技术标签:
【中文标题】如何将图像从 url 沿侧输入类型文件加载到 html5 画布?【英文标题】:How can I load image from url along side input type file to html5 canvas? 【发布时间】:2021-05-29 11:55:53 【问题描述】:我正在开发这个应用程序,我需要从 url 以及用户的硬盘驱动器将图像上传到 html5 画布。我已经为用户从硬盘驱动器输入实现了功能,但我不知道如何从 url 添加图像。
我用来从input type file
加载的代码都在输入的事件监听器中。它有很多功能,因为该应用程序还需要在图像上输入text
。所以image from url
也应该有同样的功能。
请注意imgObj
在事件监听器中。我尝试将 img.src
更改为 url 来测试它,但即使图像加载,我也无法再下载它。控制台抛出此错误:
Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
at HTMLButtonElement.<anonymous>
这里的代码减去了一些不需要在这里展示的函数:
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const btnDownload = document.getElementById('btnDownload');
const fileUpload = document.getElementById('file-upload');
fileUpload.addEventListener('change', function(e)
let imgObj = new Image();
imgObj.onload = draw;
imgObj.onerror = failed;
imgObj.src = URL.createObjectURL(this.files[0]);
// imgObj.src = 'https://static.vecteezy.com/system/resources/previews/000/094/478/original/free-abstract-pattern-vector.jpg';
// some functions to write on image
);
function draw()
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
const nw = this.naturalWidth;
const nh = this.naturalHeight;
ctx.drawImage(this, 0, 0, nw, nh);
;
function failed()
console.error("The provided file couldn't be loaded as an Image media");
;
btnDownload.addEventListener('click', () =>
const a = document.createElement('a');
document.body.appendChild(a);
a.href = canvas.toDataURL();
a.download = "canvas-image.png";
a.click();
document.body.removeChild(a);
);
<canvas id="canvas" ></canvas>
<input type="file" id="file-upload" />
<button id="btnDownload">Download</button>
简而言之,如何通过保留upload from input
功能来添加upload from url
功能?
请注意,对于upload from url
功能,输入侦听器内部的内容将是相同的。所以可能我必须对imgObj
和img.src
做点什么。
【问题讨论】:
【参考方案1】:您遇到了 CORS 问题。 CORS 是一种协议,旨在防止网站从其他网站访问您的数据(跨域数据)。由于图像在网络早期就已经存在,由于向后兼容性问题,无法阻止跨域图像加载,但可能会阻止访问此类数据。
因此,当您将跨域图像绘制到画布中时,画布会被“污染”,因此您无法再用它做很多事情,包括将其内容作为数据 URL 检索。从文件系统上传的图像是安全的,因为用户必须选择加入。
所以为了使用图片数据,你必须告诉浏览器图片必须以跨域方式加载。您可以通过设置 crossOrigin
属性或属性来做到这一点:
<img src="https://static.vecteezy.com/system/resources/previews/000/094/478/original/free-abstract-pattern-vector.jpg" crossorigin>
let imgObj = new Image();
imgObj.src =
"https://static.vecteezy.com/system/resources/previews/000/094/478/original/free-abstract-pattern-vector.jpg";
imgObj.crossOrigin = "";
使用此属性/属性,如果图像不支持 CORS,则加载将失败,甚至不会显示。但如果确实如此,就像本例一样,您将能够获取图像数据。
【讨论】:
嘿。感谢您的详细回答。在过去的半小时里,我一直在尝试这个crossOrigin
解决方案,但它似乎不起作用。我每次都会收到此错误:Access to image at 'https://static.vecteezy.com/system/resources/previews/000/094/478/original/free-abstract-pattern-vector.jpg' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
嘿,我现在可以下载它,因为我使用了来自 Imgur 的图像 url。我认为他们有 CORS 支持。现在你能帮我解决事件监听器的问题吗?
@Zak Huh,这很奇怪。 Access-Control-Allow-Origin
是标头服务器必须包含以支持 CORS。在这种情况下,服务器似乎根据请求来自哪个站点(和端口!)来选择接受或拒绝请求:http://localhost:8000
(在我的测试中)很好,但即使http://localhost:8080
也会被阻止。呵呵。
@Zak 不,没有。但支持 CORS 是一种最佳做法,因此如果您发现某些网站不支持图片等内容,请考虑与他们联系。
@Zak 顺便说一下,还有一些 CORS 代理可以让您访问一个站点,就像它支持 CORS 一样。这不会遇到“访问您的数据”问题,因为这些代理没有您的 cookie。以上是关于如何将图像从 url 沿侧输入类型文件加载到 html5 画布?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 URL 将图像加载到 imageView? [复制]
如何将图像从 url 加载到小部件的 android 远程视图中