一、前言
为什么选择使用react-avatar-editor这个插件?
由于最近在使用React写移动端项目,其中有一个需求是做一个头像裁剪功能(可以本地选择图片裁剪,也可以拉取远程图片进行裁剪)。
于是风风火火的去GitHub找相关插件。按star量来找,找到如下几个插件。
那我为什么要使用react-avatar-editor?
1.先看官方介绍:
Facebook like, avatar / profile picture component. Resize, crop and rotate your uploaded image using a clear user interface.
2.为什么使用?
- 体积够小(只有几百k啊!啊喂!)
- 方便扩展
- Issues少(😂只有一个1个issue啊!)
- 支持移动端
- 方便压缩
二、使用
安装
npm install --save react-avatar-editor
官方示列
import React from 'react'
import AvatarEditor from 'react-avatar-editor'
class MyEditor extends React.Component {
render() {
return (
<AvatarEditor
image="http://example.com/initialimage.jpg"
width={250}
height={250}
border={50}
color={[255, 255, 255, 0.6]} // RGBA
scale={1.2}
rotate={0}
/>
)
}
}
export default MyEditor
Props
值得注意prop:
-
image
-
crossOrigin
这两个prop是我实现拉取远程图片进行裁剪的关键,其他prop只要照着官方说明传就基本没啥问题
坑
我一开始是做完了本地选取图片裁剪,然后接图片上传接口就直接成功。但到我使用远程图片裁剪完调用canvas.toDataURL()时控制台给我了一个意向不到的错误。
Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
???什么玩意???
大意就是
无法在“ HTMLCanvasElement”上执行“ toDataURL”:可能无法导出污染的画布。
此时我还不知道出了什么问题,于是我默默的去google, 一顿操作以后,得知了
由于在 <canvas> 位图中的像素可能来自多种来源,包括从其他主机检索的图像或视频,因此不可避免的会出现安全问题。
尽管不通过 CORS 就可以在 <canvas> 中使用其他来源的图片,但是这会污染画布,并且不再认为是安全的画布,这将可能在 <canvas> 检索数据过程中引发异常。
使用 "硬编码" 图片网址可以很方便的允许图片来自任何地址。当开始下载图片时,我们使用 Image() 构造器创建新的 HTMLImageElement 对象,将图片的 crossOrigin 属性设置为"匿名"(即,允许对未经过验证的图像进行跨域下载)。添加图片的 load (en-US)事件的监听来判断图片数据是否已接收。最后,将图片的 src (en-US)属性设置为图片的URL以触发图片下载。
原来如此! 前面不是有个crossOrigin属性吗?整上!
插件源码里面这样写的:
export default function loadImageURL(imageURL, crossOrigin) {
return new Promise((resolve, reject) => {
const image = new Image()
image.onload = () => resolve(image)
image.onerror = reject
if (isDataURL(imageURL) === false && crossOrigin) {
image.crossOrigin = crossOrigin
}
image.src = imageURL
})
}
搞定!刷新!
为什么图片访问不了??????
于是我又去仔细看了一遍MDN的文档:启用了CORS的图片
原来还需要服务端配置。
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
<FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">
SetEnvIf Origin ":" IS_CORS
Header set Access-Control-Allow-Origin "*" env=IS_CORS
</FilesMatch>
</IfModule>
</IfModule>
三、思考与延展
图片裁剪的原理
这个时候其实我有点模糊了,于是我去查自己的资料库,想起张鑫旭大神在18年写过一篇文章《图片纯前端JS压缩的实现》 具体内容我就不在这里赘述了。 原理的大意是:
就是使用canvas的drawImage()方法。Canvas本质上就是一张位图,而drawImage()方法可以把一张大大的图片绘制在小小的Canvas画布上,等同于图片尺寸压缩了
如果想要上传/下载图片的话可以使用:
- canvas.toDataURL() 转成base64
- canvas.toBlob() 转成二进制文件
最后
第一次写,单纯记录,欢迎提出意见,欢迎讨论👏,勿喷。