一、drawImage 需要等图片加载完成
const LoadImage = (url) => {
var img = new Image();
img.src = url;
return new Promise((resolve, reject) => {
img.onload = () => {
resolve(img); //成功
};
img.onerror = () => {
reject(); //失败
};
});
}
完成这个步骤,图片就可以正确的绘制到画布上了。
二、toDataURL 报错
Failed to execute 'toDataURL' on 'HTMLCanvasElement'
image.png
在加载img时设置 crossorigin 为 anonymous 即可以解决
const LoadImage = (url) => {
var img = new Image();
img.setAttribute("crossorigin", "anonymous"); // 在加载img时设置 crossorigin
img.src = url;
return new Promise((resolve, reject) => {
img.onload = () => {
resolve(img); //成功
};
img.onerror = () => {
reject(); //失败
};
});
}
三、报跨越问题
当设置了 crossorigin 为 anonymous 后,可能会出现报跨越问题。
image.png
现象:
- 本地图片。(正常)
- 线上图片,未信任前端域名。(报跨域)
- 线上图片,信任了前端域名。(有可能,还是会报跨越)
原因+方案:
现象1:不多说。
现象2:原因不多说。方案就是让提供图片的服务信任前端域名即可解决。
现象3:这个按正常来说,图片的服务信任了前端域名,即不再回报错。
image.png
image.png
四、总结
- 仅仅在canvas上绘制图片,只需要图片加载完成后即可以绘制。
- 如果要把绘制的canvas图toDataURL导出:
同域图片:不需要做什么。
跨越图片:加载图片时需要 设置 crossorigin 为 anonymous。需要注意缓存问题。
完整调试代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
img {
width: 50%;
max-width: 50%;
}
</style>
</head>
<body>
<h2>img 显示 图片</h2>
<p>
<img src="https://cdn2.jianshu.io/assets/web/nav-logo-4c7bbafe27adc892f3046e6978459bac.png">
<!-- 自行改图片地址 -->
</p>
<h2>canvas 画图</h2>
<canvas id="canvas" width="750" height="1134" style="width: 100%; height:100%"></canvas>
<script>
const coverUrl = 'https://cdn2.jianshu.io/assets/web/nav-logo-4c7bbafe27adc892f3046e6978459bac.png?id=x'; //自行改图片地址
const DrawCanvas = {
async drawCover() {
this.canvas = document.getElementById('canvas');
this.context = this.canvas.getContext("2d");
const coverUrlData = await LoadImage(coverUrl).catch(error => {
return error;
});
coverUrlData && this.context.drawImage(
coverUrlData,
0,
0,
coverUrlData.width,
coverUrlData.height,
0,
0,
750,
1134
);
const base64ImageData = this.canvas.toDataURL("image/jpeg");
console.log(base64ImageData)
}
}
const LoadImage = (url) => {
var img = new Image();
img.setAttribute("crossorigin", "anonymous");
img.src = url;
return new Promise((resolve, reject) => {
img.onload = () => {
resolve(img); //成功
};
img.onerror = () => {
reject(); //失败
};
});
}
DrawCanvas.drawCover()
</script>
</body>
</html>