好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

详解canvas.toDataURL()报错的解决方案全都在这了

报错详尽信息

Uncaught DOMException: F ai led to execute 'toDataURL' on 'HT ML CanvasElement': Tainted canvases may not be export ed.

关键词

canvas.toDataURL() crossOri gin Access-Control-Allow-Origin

前言

最近在做一个创意类的图片合成工具,大概齐就是通过拼接自定义的文字和图片信息生成一张商品图片类似的功能,项目中用到了fa br ic.js这个画板库,最后一步在保存图片的时候报上面的一长串错误,墙内墙外搜了一遍,给出的解决 方案 都不全面,为避免 同学 们再次踩坑,于是有了此文

正文

我们在convertDOM2Image时,如果DOM内存在图片资 源 ,该资源所在的web -s erver是不支持跨域的,保存图片是不会成功的。

因此在排查问题时,首先要确定

web-server 是否 允许跨域,我们以nginx 为例 ,response-header内要存在Access-Control-Allow- org in:xxxx(可以是*,安全性要求比较高的可以根据主域名自定义) 如果是 img 标签, 是否添加了crossorigin="anonymous", 如果是Image对象,同样是否添加了改属性obj.crossOrigin='anonymous' 如果还不行,这里先不把答案放出来,我们先看看栗子

在接下来的栗子中我们 会用 到将Image转换为canvas对象的方法

function convertImageToCanvas(image) {
// 创建canvas DOM元素,并设置其 宽 高和图片一样 
let canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.h ei ght = image.height;
canvas.getContext("2d").drawImage(image, 0, 0);
// 我们在实际的开发中,需要将抓换后的base64图片编码传输到后台图片 服务器 ,由server直接存储 或者 生成一张图片;
// 所以会用到 toDataURL
console. LOG (canvas.toDataURL('image/j PE g'))
return canvas;
}

栗子1

本地未设置跨域允许选项crossorigin=anonymous,web-server未设置跨域允许选项

<div id="d1">
<img style="width: 300px;height: 240px;" src="http://jb51.net/images/cover_thumbnail_3rd. jpg " alt="">
<p>本地未设置跨域允许选项crossorigin=anonymous,web-server未设置跨域允许选项</p>
</div>
<button onclick="setCanvas('d1')">canvas保存</button>

function setCanvas(DOMID) {
let img = document.getElementById(DOMID).querySelector('img')
document.body.appendChild(convertImageToCanvas(img))
}

很显然,报错

栗子2

本地标签内设置跨域允许选项, web-server未设置跨域允许选项

这次连图片都出不来,直接报错

这个好理解,浏览器 同源策略 限制嘛

Access to image at 'xxxx' ( red irected From 'xxxx') f rom origin 'null' has been blocked by CORS policy : No 'Access-Control-Allow-Origin' header is PR esent on the requested resource.

栗子3

本地未设置跨域允许选项 crossorigin=anonymous , web-server 设置跨域允许选项

报错,妥妥的。

栗子4

本地标签内设置跨域允许选项 crossorigin=anonymous , web-server 设置跨域允许选项

<div id="d4">
<img style="width: 300px;height: 240px;" src="https://img.alicdn .COM /tfs/TB1_uT8a5ERMeJjSspiXXbZLFXa-143-59.png" alt="" crossorigin="anonymous">
<p>本地设置跨域允许选项`crossorigin=anonymous`,`web-server`设置跨域允许选项</p>
</div>
<button onclick="setCanvas('d4')">canvas保存</button>

居然可以了,但是~如果在代码内设置跨域呢?

栗子5

function setCanvas(DOMID) {
let img = document.getElementById(DOMID).querySelector('img')

img.crossOrigin= 'anonymous'

document.body.appendChild(convertImageToCanvas(img))
}

报错

我看 官方文档 的 意思 是必须同步设置crossOrigin=anonymous,该图片凭证才会被信任

This means t hat CORS is enabled and credentials are sent if the image is fetched from the s am e origin from which the document was loaded.

否则缓存的图像数据仍然会被 画布 视为有污染的跨源内容.

怎么办?重新取一遍图片呗,加个随机数,图片还是那个图片, 不过 加了个马甲,浏览器就不认识了

栗子6

function setCanvas(DOMID) {
let img = document.getElementById(DOMID).querySelector('img')

img.src =img.src+'?v='+Math.random()
img.crossOrigin= 'anonymous'

img.onload=()=>{
document.body.appendChild(convertImageToCanvas(img))
}
}

binggo, 完美解决

所以我们在开发 过程中 ,新建图片,更换图片,还原图片等功能代码内,最好每一次都加个随机数,以保证源都是最新的,不走缓存

多说 一点 吧,关于fabric.js的相关跨域配置见下方

let _fabric config  = {
//  .. ..
crossOrigin:'anonymous'
};
/* fabric对象 */
let _fabricObj = new fabric.Canvas(id, _fabricConfig);


// 新建图片对象时
let imgInstance = new fabric.Image.fromURL(url + '?v='+ Math.random(), img => {}, {crossOrigin: 'anonymous'})

// 动态更新图片时
let  current Active = _fabricInstance.getActiveObj();
currentActive.setSrc(randomURL, img =>{}, {crossOrigin: 'anonymous'})

g IT h ub : http://github测试数据/phillyx

到此这篇关于详解canvas.toDataURL()报错的解决方案全都在这了的 文章 就介绍到这了,更多相关canvas.toDataURL()报错内容请搜索以前的文章或继续浏览下面的相关文章,希望大家以后多多支持!

总结

以上是 为你收集整理的 详解canvas.toDataURL()报错的解决方案全都在这了 全部内容,希望文章能够帮你解决 详解canvas.toDataURL()报错的解决方案全都在这了 所遇到的问题。

如果觉得 网站内容还不错, 推荐好友。

查看更多关于详解canvas.toDataURL()报错的解决方案全都在这了的详细内容...

  阅读:45次