1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 1小时搞定cropper.js制作头像/图片上传 裁剪 并发送至后端

1小时搞定cropper.js制作头像/图片上传 裁剪 并发送至后端

时间:2024-08-24 06:21:40

相关推荐

1小时搞定cropper.js制作头像/图片上传 裁剪 并发送至后端

1小时搞定cropper.js制作头像/图片上传、裁剪、并发送至后端

先给大家看一下最终效果。

大多数功能都是由Cropper.js封装好的,调整并制作了:

上传图片对图片的裁剪以及调整(旋转、缩放)、实时预览将裁剪后的数据保存为blob发送至后端。

Q1:为什么选择Cropper.js和如何安装Cropper.js?

一开始制作这个需求思路有两个,使用canvas原生或者寻找现成的库,对比了一番觉得canvas实现时间耗费较长,且秉承着不重复造轮子的原则(其实是菜),决定使用Cropper.js。官方封装了很多参数、方法、事件,上手容易,文档阅读体验较好、而且便于扩展。

Cropper.js官方仓库+文档:/fengyuanche…

Installation

npm install cropperjs复制代码

Q2:如何上传图片?

我们实现上述功能需要的核心HTMl部分只有:

<!-- 1.一个用于获取上传文件的input,type="file",并且监听onchange事件 --><input type="file"accept="image/*" id="imgReader" onchange="loadingImg"> <!-- 2.一个用于给Cropper.js覆盖使用的img --><img id="cropImg"><!-- 3.两个用于预览的div --><div class="previewText">裁剪预览</div><div class="previewBox"></div><div class="previewBoxRound"></div>复制代码

首先先将用于上传的input隐藏起来,我们并不需要它的样式

.inpuFile{display: none;}复制代码

然后给你项目中的某个按钮添加一个点击事件,并且调用

function uploadImg(){document.querySelector('#imgReader').click()},复制代码

即可打开上传文件的窗口,然后选择你需要的图片

Q3:如何将图片读取显示和使用Cropper.js添加裁剪控件?

上传文件成功后,会触发onchange事件,调用loadingImg()

//引入Cropper.jsimport 'cropperjs/dist/cropper.css';import Cropper from 'cropperjs';let CROPPER//创建一个cropper的全局对象 function loadingImg(eve){//读取上传文件let reader = new FileReader();if(event.target.files[0]){//readAsDataURL方法可以将File对象转化为data:URL格式的字符串(base64编码)reader.readAsDataURL(eve.target.files[0]);reader.onload = (e)=>{let dataURL = reader.result;//将img的src改为刚上传的文件的转换格式document.querySelector('#cropImg').src = dataURL; const image = document.getElementById('cropImg'); //创建cropper实例-----------------------------------------CROPPER = new Cropper(image, {aspectRatio: 16 / 16,viewMode:0,minContainerWidth:500,minContainerHeight:500,dragMode:'move',preview:[ document.querySelector('.previewBox'),document.querySelector('.previewBoxRound')]})}}}复制代码

new Cropper方法:

new Cropper(element[, options])

第一个参数:element

类型:HTMLImageElement 或 HTMLCanvasElement;作用:用于显示裁剪功能;

第二个参数(可选):

类型: Object;作用:用于添加具体参数设置

我们需要用到的参数有:

{aspectRatio: 16 / 16, //固定裁剪框的比例(横/竖),此处16/16则固定为正方形minContainerWidth:500, //容器最小的宽度minContainerHeight:500, //容器最小的高度dragMode:'move', //设置裁剪框为可以移动preview:[ document.querySelector('.previewBox'), //设置我们需要添加实时预览的地方document.querySelector('.previewBoxRound')]//更多参数请参照官方仓库...我们这里用不着}复制代码

先忽略实时预览,完成到这里我们就可看到我们上传的图片以及裁剪功能:

Q4:如何进行实时预览?

上面创建cropper的时候,我们在选项中添加了

preview:[ document.querySelector('.previewBox'), document.querySelector('.previewBoxRound')]复制代码

preview就是用来设置我们需要实时预览的地方,但是设置完成之后要给上述的两个div添加一下样式,才可以正常显示

.previewBox,.previewBoxRound{box-shadow: 0 0 5px #adadad;width: 100px;height: 100px;margin-top: 30px;overflow: hidden; /*这个超出设置为隐藏很重要,否则就会整个显示出来了*/}.previewBoxRound{border-radius: 50%;/*设置为圆形*/}复制代码

Q5:如何获取裁剪数据并发送至后端?

function GetData(){//getCroppedCanvas方法可以将裁剪区域的数据转换成canvas数据CROPPER.getCroppedCanvas({maxWidth: 4096,maxHeight: 4096,fillColor: '#fff',imageSmoothingEnabled: true,imageSmoothingQuality: 'high',}).toBlob((blob) => {//然后调用浏览器原生的toBlob方法将canvas数据转换成blob数据//之后就可以愉快的将blob数据发送至后端啦,可根据自己情况进行发送,我这里用的是axiosconst formData = new FormData();// 第三个参数为文件名,可选填.formData.append('croppedImage', blob/*, 'example.png' */);let config = {headers:{'Content-Type':'multipart/form-data'}} this.$axios.post(flow_mission_UploadFile(),param,config).then((response)=>{ console.log(response) }).catch((err)=>{console.log(err)})})}复制代码

其他需要注意的地方:

1.裁剪框尺寸问题

裁剪部分默认会根据上传图片的大小进行改变

解决图片过小的问题:

//在new Cropper的参数中设置minContainerWidth:500, //容器最小的宽度minContainerHeight:500, //容器最小的高度复制代码

解决图片过大的问题: 给添加固定宽度样式

#cropImg{height: 450px;width: 450px;box-shadow: 0 0 5px #adadad;}复制代码

2.重复上传的问题

再次上传不同图片的时候,还是出现原来的图片,只需要在上传文件的时候,对之前存在的CROPPER进行摧毁就可以了

function uploadImg(){document.querySelector('#imgReader').click()if(CROPPER){CROPPER.destroy()}},复制代码

3.其他功能的实现

这里列举几个我这里用到的

CROPPER.rotate(90) :旋转图片,单位为数字,90为顺时针旋转90度CROPPER.zoom(0.1) :缩放图片,单位为数字,0.1为在原缩放基础上增加0.1倍CROPPER.reset() :重置对图片的所有操作

还有很多其他方法和事件可以自行参照仓库,一个普通的上传头像功能就这样应该够用了!这里就不一一列举啦

如果觉得写得有不好的地方请多多指教,喜欢的话可以点个赞哈!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。