JavaScript向canvas绘制图片失败 导出提示Tainted canvases报错如何解决
报错原因
这个错误是浏览器的Canvas跨域安全限制导致的画布污染:只要Canvas中绘制了未配置跨域许可的资源,浏览器就会将画布标记为只读状态,禁止调用toBlob()、toDataURL()、getImageData()这类导出类接口。
解决方案
按以下步骤修改即可:
- 加载水印图片前,先给Image对象设置
crossOrigin属性为anonymous,该配置必须写在给src赋值之前才会生效 - 确认你项目的静态资源服务(本地开发服务/线上服务器)已经给assets目录下的图片资源配置了
Access-Control-Allow-Origin跨域响应头,允许当前站点域名访问 - 如果是本地用
file://协议直接打开页面调试,跨域配置不会生效,需要用本地HTTP服务启动项目(比如VSCode的Live Server插件) - 如果你用到的输入图片file也是跨域来源,同样需要给输入图片的img对象加上
crossOrigin配置
修改后的核心代码
// 读取输入文件 const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => { // 创建画布、计算水印尺寸和位置 const canvas = document.createElement("canvas"); canvas.width = canvasSize.width; canvas.height = canvasSize.height; var calcW = canvasSize.width/2; var calcH = calcW/2.16; var calcX = (canvasSize.width - calcW)/2; var calcY = (canvasSize.height - calcH)/2; // 将输入图片加载到画布 const img = document.createElement("img"); // 如果输入图片也为跨域资源,可取消注释下行配置 // img.crossOrigin = 'anonymous' img.src = reader.result; img.onload = () => { const ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0); // 加载并绘制水印图片 const mark = new Image(); // 新增跨域配置,必须放在src赋值前 mark.crossOrigin = 'anonymous'; mark.src = 'assets/img/compliant.png'; mark.onload = () => { ctx.drawImage(mark, calcX,calcY,calcW,calcH); // 转blob并生成访问地址 canvas.toBlob((canvasBlob) => { const newImg = document.createElement("img"), url = URL.createObjectURL(canvasBlob); newImg.onload = function () { // 图片加载完成后销毁对象地址 URL.revokeObjectURL(url); }; // 展示加水印后的图片 newImg.src = url; window.open(url); }); }; }; };
内容的提问来源于stack exchange,提问作者Gmanski 156
相关产品推荐
相关产品推荐

