以美图的图片处理为例子,学习JS中对图片的处理。处理图片时需要使用canvas
1 图片的跨域
使用canvas
处理图片,首先需要加载图片,如果是在线图片需要针对图片进行跨域的处理。具体的处理方法是:
在图片服务器上设置跨域头,并且在前端加载图片之前将<img>
标签的crossOrigin
设置为*
这样做的原因是:
尽管不通过
CORS
就可以在画布中使用图片,但是这会污染画布。一旦画布被污染,你就无法读取其数据。例如,你不能再使用画布的toBlob()
,toDataURL()
或getImageData()
方法,调用它们会抛出安全错误。(MDN Web docs)
还要注意的是:
crossOrgin
只有在线上图片时才设置,本地图片或者是base64图片不能设置,否在某些系统会报错,导致图片加载失败- 当项目为本地包环境时,例如内置于App中时,
crossOrigin
值无效,webview的安全机制会导致无论该值设置与否,都会报跨域的错误。解决办法是:需要将所有图片转换成base64才能正确绘制; crossOrigin
值一定要在图片加载之前设置,即为<img>
赋值src
之前进行设置,否则无效。
我的图片是存储在七牛云的,七牛对图片的跨域进行了默认的处理:
所以,一个Promise话的图片加载函数:
function loadImage(src) {
return new Promise((resolve, reject) = > {
let img = new Image();
// 在线图片设置crossOrigin跨域
if (src.indexOf(src) === 0) {
img.crossOrigin = '*';
}
img.src = src;
img.onload = () = > {
resolve(img)
};
img.onerror = () = > {
reject(new Error('图片解析失败'))
}
})
}
2 图片的缩放
图片缩放最常见的场景是图片的压缩,在保证清晰的前提下合理的缩小图片尺寸,能大大的降低图片的大小。
新建一个canvas画布,将宽高设置为需要压缩的尺寸,要注意的是需要保证图片的比例,所以canvas的尺寸是通过计算得出的。
2.1 drawImage
// 创建图片
const src = 'http://pblesaqy5.bkt.clouddn.com/18-7-27/52991435.jpg';
const img = await loadImage(src);
// 计算画布尺寸
const canvas = document.querySelector('#canvas');
const imgRatio = img.naturalWidth / img.naturalHeight;
const ctxWidth = 300;
const ctxHeight = ctxWidth / imgRatio;
canvas.width = ctxWidth;
canvas.height = ctxHeight;
// 绘制图片
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, ctxWidth, ctxHeight);
ctx.drawImage(image, dx, dy, dw, dh)
来讲图片画入canvas中,这个方法最多可以接收9个参数, 实现压缩,只需要使用其中的5个参数即可, 其余参数在其它部分使用到时再做详解:
image
: 需要绘制的图片源,需要接收已经加载完成的HTMLImageElement,HTMLCanvasElement或者HTMLVideoElement;