canvas生成图片toDataURL报错(Uncaught DOMException: Failed to execute ‘toDataURL‘ on ‘HTMLCanvasEl)

现象:在使用canvas的toDataURL()方法时,控制台有时会报错:Uncaught DOMException: Failed to execute ‘toDataURL’ on ‘HTMLCanvasElement’: Tainted canvases may not be exported.
原因:这是由于之前由drawImage()向canvas导入的图片跨域而导致的。
解决方法:

1、在引用图片之前打开跨域资源允许权限(一定要注意顺序):
var img=new Image;
img.setAttribute('crossOrigin', 'anonymous') //关键
img.src = url + '?time=' + new Date().valueOf();
img.src="图片地址";
2、存放图片地址的服务器也要开启跨域允许权限,不然会报错:No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

如Apache设置:
①.打开LoadModule headers_module modules/mod_headers.so

②.在虚拟主机内加上 Header set Access-Control-Allow-Origin *

总结
跨域图片能正常裁剪(图片未转化成base64),应该满足三个条件:

1,img元素中设置crossorigin属性
2,图片允许跨域,设置响应头Access-Control-Allow-Origin
3,使用js方式请求图片资源, 需要避免使用缓存,设置url后加上时间戳,或者http头设置Cache-Control为no-cache

最后 贴上我canvas绘制图片,画线最后生成图片的代码

在这里插入图片描述

<div class="jiepingCanvas" id="jtCs"  v-show="dialogJPG">
    <canvas id="mycanvas" ref="mycanvas" width="848" height="508"></canvas>
    <div class="yesNo">
        <div class="jtYes" @click="jtSure()">
            <img src="../common/comImg/yes.png" alt="">
        </div>
        <div class="jtYes" @click="jtCancel()">
            <img src="../common/comImg/no.png" alt="">
        </div>
    </div>
    <div class="tipsjt">
         提示:图片可以进行画线操作
    </div>
</div>
data() {
 return {
	 onoffjt:false,
	 oldxjt:0,
	 oldyjt:0,
	 ctxjt:'',
	 linecolorjt:'',
	 linwjt:8,
	 onArrjt:[],
	 endArrjt:[],
	 ctxjt:"",
	 huajt:false,
	 canvasJT:""
 }
}

//初始化画布
canvasInit(){
	var that=this
	var imgUrl='https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2583035764,1571388243&fm=26&gp=0.jpg'
	that.dialogJPG=true
	//  获取canvas
	that.canvasJT = document.getElementById("mycanvas")
	var a = setInterval(() =>{
	    that.canvasJT = document.getElementById("mycanvas")
	    if(!that.canvasJT){
	        return false
	    } else {
	        clearInterval(a)
	        that.ctxjt = that.canvasJT.getContext('2d')
	        var img = new Image()
	        
	        img.src = imgUrl+"?timeStamp="+new Date();
	        img.setAttribute("crossOrigin",'anonymous')
	        img.onload = function(){
	            if(img.complete){
	                //  根据图像重新设定了canvas的长宽
	                that.canvasJT.setAttribute("width",844)
	                that.canvasJT.setAttribute("height",504)
	                //  绘制图片
	                that.ctxjt.drawImage(img,0,0,844,504)
	                that.initjt()
	            }
	        }
	        that.dialogJPG=true
	    }
	},1)
}

//开始画线
initjt(){
    //画一个黑色矩形
    this.ctxjt.fillStyle="transparent";
    this.ctxjt.fillRect(0,0,848,508);
    //按下标记
    this.onoffjt=false;
    this.oldxjt=0;
    this.oldyjt=0;
    this.linecolorjt=this.linecolor;
    //宽度默认为8
    this.linwjt=8;
    //鼠标移动事件,事件绑定
    this.canvasJT.addEventListener("mousemove",this.drawjt,true);
    this.canvasJT.addEventListener("mousedown",this.downjt,false);
    this.canvasJT.addEventListener("mouseup",this.upjt,false);
},
//鼠标按下事件
downjt(event){
    if(this.huajt==true){
        this.onoffjt=false
    }else{
        this.onoffjt=true;
        this.oldxjt=event.pageX-this.canvasJT.getBoundingClientRect().left;
        this.oldyjt=event.pageY-this.canvasJT.getBoundingClientRect().top;
        console.log(this.oldxjt,this.oldyjt,'event')
    }
},
//鼠标绘制线条
drawjt(event){
    if(this.onoffjt==true){
                var newxjt=event.pageX-this.canvasJT.getBoundingClientRect().left;
                //getBoundingClientRect方法是边框距离浏览器的距离
                var newyjt=event.pageY-this.canvasJT.getBoundingClientRect().top;
                // console.log(newx,newy,'000')
                this.ctxjt.beginPath();
                this.ctxjt.moveTo(this.oldxjt,this.oldyjt);
                this.ctxjt.lineTo(newxjt,newyjt);
                // console.log(newx);
                this.ctxjt.strokeStyle=this.linecolorjt;
                this.ctxjt.lineWidth=this.linwjt;
                this.ctxjt.lineCap="round";
                this.ctxjt.stroke();
                
                this.oldxjt=newxjt;
                this.oldyjt=newyjt;
                let xy={
                    x:this.oldxjt,
                    y:this.oldyjt
                }
                this.onArrjt.push(xy)
            }
       
},
//鼠标抬起事件
upjt(){
    this.onoffjt=false;
    if(this.onArrjt.length>0){
        this.endArrjt.push(this.onArrjt)
        this.onArrjt=[]
    }
},
//点击确认生成图片
jtSure(){
    let dataURL = document.getElementById('mycanvas')
    let dataURLs=dataURL.toDataURL("images/png")
        let params = {
            data: dataURLs,
            compid: 30,
            hzm:'png'
        };
        postUpFile(params).then(res => {
            let { ReturnCode, Data } = res;
            if (ReturnCode == 200) {

                let DataUrl = Data.Url;
                console.log(DataUrl,'DataUrl路径')
                
                let msg=this.nickName+'#&$'+DataUrl
                let senBtnws={
                    order:enumPack.enum_msg.drawImage,
                    uid:Number(this.option.uid),
                    msg:msg,
                    device:4
                }
                this.handdleMsg(JSON.stringify(senBtnws))
                this.stepArray.push(DataUrl)

            } 

        });

        this.dialogJPG=false
        let c=document.getElementById("mycanvas");  
        let cxtjt=c.getContext("2d");  
        cxtjt.clearRect(0,0,c.width,c.height); 
},
//点击取消清除画布
jtCancel(){
    this.dialogJPG=false
    let c=document.getElementById("mycanvas");  
    let cxtjt=c.getContext("2d");  
    cxtjt.clearRect(0,0,c.width,c.height); 
}
}

以上参考了很多大神的文章
如:https://www.cnblogs.com/sunala/p/7085525.html https://segmentfault.com/q/1010000008648867

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值