现象:在使用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