一、背景
- 背景:因业务需要改版个人中心,并兼容移动端,头像上传之前只是在pc端存在,移动端没有入口,现需增加
- 技术定位:react + react-cropper
前期调研移动端上传+裁剪现有方案都存在哪些,调研的方案有
- react-easy-crop: github.com/ValentinH/r…
- react-image-crop:github.com/DominicTobi…
- react-avatar-editor:www.npmjs.com/package/rea…
- react-cropper: github.com/react-cropp…
最终选择的是react-avatar-editor,后期和UI沟通裁剪都涉及了哪些功能,以及页面的展示,遂有转成了react-cropper
上传这里本来pc端用的是antd-upload,后来因为要直接关联到相册,便使用了antd-mobile中imageUploader (这里还需要研究一下,关联相册和文件的区别)
二、实现
上传
import { ImageUploader } from 'antd-mobile';
<ImageUploader
// value={fileList}
preview={false}
// beforeUpload={beforeUpload}
// onChange={handleUploadChange}
// maxCount={1}
accept={'image/*'}
upload={handleUpload}
// beforeUpload={() => closePopup()}
>
<div className={styles.upload_text}>
上传头像
</div>
</ImageUploader>
const handleUpload = async (file: File) => {
// console.log('file---', file);
// console.log('URL.createObjectURL(file)', URL.createObjectURL(file));
if (file && file.size && file.size > 10 * 1024 * 1024) {
return;
}
if (file) {
setFileImage(URL.createObjectURL(file) as any);
setModalVisible(true);
}
return {
url: URL.createObjectURL(file),
};
};
代码里面有一些注释的属性,因需求本身功能原因未使用到
handleUpload 方法 接受的是一个文件对象,包含上传的文件信息,可通过File 来进行逻辑判断和重写文件信息
URL.createObjectURL(file) 该方式可以将文件对象转换成二进制文件地址 url地址
将当前获取的地址 传递 剪裁组件中
裁剪
裁剪使用的组件是 react-cropper Api 文档就不过多赘述 前面有gitHub链接
- 主要的功能点
- 支持手动缩放
- 支持选择裁剪区域
- 裁剪区域必须为正方形
const cropperRef = useRef<HTMLImageElement>(null);
<div className={styles.content}>
{fileImage && (
<Cropper
src={fileImage}
aspectRatio={1}
viewMode={0}
style={{
height: '100%',
width: '100%',
backgroundColor: '#ffffff',
}}
// background={false}
center={false}
// initialAspectRatio={1}
guides={false}
crop={onCrop}
ref={cropperRef}
crossOrigin="use-credentials"
minCropBoxHeight={10}
minCropBoxWidth={10}
/>
)}
</div>
const onCrop = () => {
const imageElement: any = cropperRef?.current;
const cropper: any = imageElement?.cropper;
const dataUrl = cropper.getCroppedCanvas().toDataURL();
setImageUrl(dataUrl);
};
简单介绍一下 代码中的属性
-
Src 对应上传文件的二进制(blob)地址
-
aspectRatio 图片的宽高比
-
viewMode 视图模式 0 代表沿用canvas的视图
-
Center 代表是否居中显示
-
guides:裁剪框上方的虚线
-
crop 裁剪后的回调
-
crossOrigin 跨域配置
-
minCropBoxHeight 最小裁剪高度
-
minCropBoxWidth 最小裁剪宽度
onCrop 是cropper 裁剪后的回调函数 回调中可以通过获取当前cropper对象来获得裁剪后图片的地址
当点页面确定时,将裁剪后的图片进行上传 调取上传接口
const handleSaveCropImg = async () => {
setLoading(true);
const res = await uploadImageToPath('/avatar', imageUrl);
if (res?.success && res?.data && user?.studentProfile?.id) {
const saveRes = await updateAvatar(user?.studentProfile?.id, res.data);
if (saveRes?.success) {
await fetchUser();
}
}
setLoading(false);
};
上传接口返回值便是裁剪后图片的 云平台存储地址
有意思的方法
图片地址转化为base64
什么场景会用到这个方法呢
当服务端要求上传的图片路径是base64的时候,我们拿到文件的路径是一个相对路径或者二进制路径时 需要做一层转换
三、总结
-
调研方案一定要基于UI设计的功能 不然可能选择的插件不是最合适的
-
调研时 多去尝试插件库的demo 这样才能确定是否能正常满足需要
-
确定方案时 需要确认当前方案对应的热度和问题数以及迭代速度