天气预报说北京还有暴雨,疫情又严重了,大家出门在外注意安全。
言归正传!
canvas 能做的事情太多了,也让我爱上了这门技术,这段时间对他投入了很大精力。
canvas 在绘制内容的时候,会创建一块画布,这块画布是干净的,此时,你可以往上面画文字、画图片、还可以画视频等。在绘制图片的时候,图片可能会来源于其它域名,比如:
在网页 https://wsy.com/index.html
中创建一个 canvas 元素,在 canvas 上绘制一张图片,图片地址为
https://image/suyan.png(不支持跨域),一旦把图片绘制到 canvas 上,当你使用 canvas.toDataURL() 时会报一个安全问题:

其实调用getImageData(),toBlob() 这些 api 也会报错。
关于这个问题,MDN 上也有描述:
The canvas's bitmap is not origin clean; at least some of its contents have or may have been loaded from a site other than the one from which the document itself was loaded.
解决这个问题核心思路是解决图片的跨域问题。
这里提个疑问,浏览器为啥要加入这个安全举措?可以把任何图片绘制到 canvas 上,但却不让把 canvas 导出?
在访问图片的时候,可以通过 crossorigin 来设置跨域访问图片,代码如下:
let image = new Image();
image.crossOrigin = 'anonymous';
image.addEventListener('load', () => {
// image load success
});
image.addEventListener('error', () => {
// image load error
});
image.src = src;
一旦设置 crossorigin 这个属性时,那么你的图片服务器必须支持跨域访问,否则将会报错:

解决这个问题让服务端支持跨域即可,如果服务端支持不了,可以通过 node 层写个代理:
const axios = require('axios');
const cors = require('cors');
const app = express();
// express 使用跨域插件
app.use(cors());
// 访问的图片域名,访问时添加参数 requrl,图片真正的地址
app.use('/img/content', (req, res) => {
let url = req.query.requrl;
axios.get(url, {
responseType: 'arraybuffer'
}).then(data => {
res.set('Content-Type', 'image/jpeg');
let content = Buffer.from(data.data, 'binary');
res.end(content);
});
});
其实不仅是图片,如果你在 canvas 中使用视频也会遇到这个问题。
总之,问题的核心是,你可以把任意网站的图片应用到你的网站,但是如果想使用图片中的数据,必须声明图片通过跨域访问,也就是说你用图片数据的时候,要和服务器打声招呼:'我要用你图片,帮忙加个白名单吧'。解决此类问题,归根结底是解决跨域问题。
看一看下面的文章,更进一步:
https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image

长按关注
素燕《前端小课》
帮助 10W 人入门并进阶前端
官网:https://lefex.gitee.io/
当在canvas上绘制跨域图片并尝试导出时,会遇到安全问题,浏览器限制了canvas的数据读取。解决方法包括设置图片的crossorigin属性和服务器支持跨域,确保在使用图片数据时进行合法的跨域请求。

1704

被折叠的 条评论
为什么被折叠?



