网站首页 > 技术文章 正文
在前端开发的过程中, 我们经常遇到文件上传或者图片上传的需求, 有些场景中可能还会要求上传图片后对图片进行裁切, 压缩. 对于不想加班的程序员来说, 第一要义就是使用第三方库. 虽然像我们熟悉的antd, element等库提供了上传组件:
image.png
但是这些第三方UI库一方面体积比较庞大, 不够轻量, 另一方面不支持裁切, 压缩等功能, 所以还是需要自己实现或者整合第三方库实现, 当然 antd 提供了一个图片裁切的库 antd-img-crop, 但是使用上极度“难受”(受限), 无法自由裁切图片, 同时也无法提供压缩能力:
image.png
所以这个方案也直接pass. 最终为了实现想要的效果,我还是决定牺牲自己, 手动实现一个支持上传裁切并压缩的组件, 并取名为react-cropper-pro.
2022-07-16 16.02.04.gif
react-cropper-pro 使用介绍
react-cropper-pro是一款简单轻量的图片上传 + 裁切 + 压缩 组件, 不依赖antd / element等第三方UI, 快速实现图片处理相关操作, 底层依赖react-cropper.
安装
yarn add react-cropper-pro
使用
import CropperPro from 'react-cropper-pro';
export default () =>
<CropperPro
defaultImg=""
onChange={(file) => console.log(file)}
onDel={(image) => console.log('remove', image)}
/>;
image.png
API介绍
image.png
技术实现
技术上主要有以下几个核心点:
- 实现文件上传组件样式(主要是覆盖原生input[file]的“纯洁UI”)
- 实现突图片裁切
- 实现图片压缩
- 包装成react组件并发布到npm
接下来和大家简单介绍一下实现细节.
1. 实现文件上传组件样式
image.png
我们都知道元素的input文件上传组件采用的默认样式非常简陋, 所以我们需要通过某种方式替换原生样式, 这里和大家分享一下我实现的方式.
image.png
其实很简单, 就是用定位的方式将一个同样大小的div覆盖在input上面, 然后把让div事件穿透, 能响应input的事件即可. 核心代码如下:
<div className="xi-cropper-upload">
<input type="file" onChange={handleChange} accept="image/gif,image/jpeg,image/jpg,image/png" />
<div className="xi-cropper-file">
</div>
</div>
其次就是需要用户在上传完图片之后, 图片能展示在上传区域, 如下:
image.png
这块的完整代码如下:
<div className="xi-cropper-upload">
<input type="file" onChange={handleChange} accept="image/gif,image/jpeg,image/jpg,image/png" />
<div className="xi-cropper-file">
{
cropData ? <img src={cropData} /> : '+'
}
{
!!cropData && <span className="xi-cropper-del" onClick={handleDel}>?</span>
}
</div>
</div>
2. 实现突图片裁切
图片裁切这里我采用了 react-cropper 这个库, 虽然不能直接实现图片上传, 但是它的图片裁切能力还是很强大的. 我们需要实现的效果是图片上传后会出现上传弹窗, 显示裁切区域, 如下:
2022-07-16 16.02.04.gif
这里弹窗的实现我采用了React-Dom的createPortal API, 它可以实现弹窗dom挂载在指定的容器上, 很多组件库的组件比如抽屉, Modal, DropDown都采用了类似的实现原理, 我之前也写了一篇文章来介绍如何使用 createPortal 的, 感兴趣的朋友可以学习参考一下:
这块的核心源码可以参考github仓库对应的第134行.
文件路径如下: https://github.com/MrXujiang/react-cropper-pro/tree/main/src/crop
3. 实现图片压缩
图片压缩这块主要是基于产品业务场景来设计, 这里我分了4个档:
- 不压缩
- 高
- 中
- 低
如下:
image.png
这一块主要是利用了canvas和 cropper 的能力, 我们通过控制canvas对象的宽高比例, 和canvas提供的toBlob 来实现图片的压缩, 核心代码如下:
if (typeof cropper !== "undefined") {
setCropData(cropper.getCroppedCanvas().toDataURL());
const rate = 1 / (4 - imgLevel);
const { width, height } = cropper.getCropBoxData();
cropper.getCroppedCanvas({
width: width * rate,
height: height * rate,
imageSmoothingQuality: imgLevelValueMap[imgLevel],
fillColor: 'transparent',
}).toBlob((blob: Blob) => {
if(blob) {
const time = Date.now();
let croppedFile:any = new File([blob], fileRef.current.name, {
type: fileRef.current.type,
lastModified: Date.now(),
});
croppedFile.uid = time;
onChange && onChange(croppedFile)
}else {
new Error('图片裁切失败');
}
}, fileRef.current.type, rate)
}
当然有关 canvas 的toBlob API不熟悉的朋友可以移步MDN:
https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toBlob
4. 包装成react组件并发布到npm
有关如何实现组件库以及如何优雅发布到NPM公仓的技术我之前在《趣谈前端》 也分享过, 感兴趣的朋友可以参考一下:
应用场景
最后再来看看应用场景, 目前 react-cropper-pro 已经应用于H5-Dooring 可视化搭建平台中, 来实现图片更精准的控制:
image.png
感兴趣的朋友可以体验一下, 当然还有很多内容平台, 因为有富文本或者md等编辑器的写作能力, 所以也会涉及到对图片的控制, 所以这些都是 react-cropper-pro 的应用领域.
最后
开源不易, 欢迎搭建一起共建, 点个 star, 让生活更美好.
猜你喜欢
- 2024-11-11 一行JS代码实现一个简单的模板字符串替换「实践」
- 2024-11-11 14个 JavaScript 代码优化技巧 页面代码优化方法及技巧
- 2024-11-11 Web 端实时防挡脸弹幕(基于机器学习)
- 2024-11-11 聊聊苹果营销页中几个有趣的交互动画
- 2024-11-11 由浅入深,66条JavaScript面试知识点(一)
- 2024-11-11 前端JS实现字符串/图片/excel文件下载
- 2024-11-11 吃透 Vue 项目开发实践|16个方面深入前端工程化开发技巧【上】
- 2024-11-11 「前端进阶」高性能渲染十万条数据(时间分片)
- 2024-11-11 我是如何零基础入门前端开发的(2021 版)
- 2024-11-11 简单实现一个虚拟形象系统 虚拟形象制作软件下载
- 标签列表
-
- content-disposition (47)
- nth-child (56)
- math.pow (44)
- 原型和原型链 (63)
- canvas mdn (36)
- css @media (49)
- promise mdn (39)
- readasdataurl (52)
- if-modified-since (49)
- css ::after (50)
- border-image-slice (40)
- flex mdn (37)
- .join (41)
- function.apply (60)
- input type number (64)
- weakmap (62)
- js arguments (45)
- js delete方法 (61)
- blob type (44)
- math.max.apply (51)
- js (44)
- firefox 3 (47)
- cssbox-sizing (52)
- js删除 (49)
- js for continue (56)
- 最新留言
-