本文主要介绍vue中使用cropperjs插件实现裁剪头像功能的大体思路和主要实现业务代码:先看效果----
一、图像上传预览
1、准备file类型输入框,并通过点击头像触发上传
<input type="file" hidden ref="choseHeadImg" @change="onChange" />
<van-nav-bar title="个人信息" left-arrow @click-left="$router.back()" />
<van-cell
title="头像"
is-link
@click="$refs.choseHeadImg.click()"
@change="onChange"
>
<van-image class="avatar" fit="cover" round :src="userData.photo" />
</van-cell>
2、给input定义change事件
3、获取上传文件信息
methods: {
// 监听文件对象改变的方法
onChange() {
// 获取文件对象
const file = this.$refs.choseHeadImg.files[0]
// 获取blob数据
const data = window.URL.createObjectURL(file)
// 数据传递至弹出层中
this.img = data
// 显示出弹出层
this.Headshow = true
// file-input 如果选择了同一个文件不会触发change事件
// 解决办法就是每次使用完毕,把它的value清空
this.$refs.choseHeadImg.value = ''
}
},
二、图片上传预览功能处理
父组件中定义弹出层结构:
<van-popup v-model="Headshow" position="bottom" :style="{ height: '100%' }">
<updateHead @close="Headshow = false" v-if="Headshow" :img="img" />
</van-popup>
弹出层结构:
<div class="update-avatar">
<img :src="img" ref='img'/>
<div class="toolbar">
<span>取消</span>
<span>完成</span>
</div>
</div>
img为父组件中获取到的blob数据
弹出层CSS:
.update-avatar {
background: #000;
width: 100%;
height: 100%;
.toolbar {
position: fixed;
bottom: 10px;
width: 100%;
display: flex;
justify-content: space-between;
font-size: 28px;
color: #fff;
padding: 0 15px;
box-sizing: border-box;
}
}
img {
max-width: 100%;
}
子组件中父组件传递来的img 数据(图片数据)
props: {
img: {
type:[Object,String],
required:true
}
},
data() {
return { }
},
三、图片裁切
使用第三方库cropper.js
1.安装cropper.js
npm install cropperjs 或者
yarn add cropperjs
2、引入css、js
import 'cropperjs/dist/cropper.css'
import Cropper from 'cropperjs'
3.在mounted中初始化
const image = this.$refs.img
const cropper = new Cropper(image, {
aspectRatio: 16 / 9,
crop (event) {
console.log(event.detail.x)
console.log(event.detail.y)
console.log(event.detail.width)
console.log(event.detail.height)
console.log(event.detail.rotate)
console.log(event.detail.scaleX)
console.log(event.detail.scaleY)
}
})
4.配置cropperjs
const cropper = new Cropper(image, {
viewMode: 1, // 只能在裁剪的图片范围内移动
dragMode: 'move', // 画布和图片都可以移动
aspectRatio: 1, // 裁剪区默认正方形
autoCropArea: 1, // 自动调整裁剪图片
cropBoxMovable: false, // 禁止裁剪区移动
cropBoxResizable: false, // 禁止裁剪区缩放
background: false // 关闭默认背景
})
四、获取裁剪图片
将cropper实例存储到data中
data() {
return {
cropper: null
}
},
mounted() {
const image = this.$refs.img
this.cropper = new Cropper(image, {
viewMode: 1, // 只能在裁剪的图片范围内移动
dragMode: 'move', // 画布和图片都可以移动
aspectRatio: 1, // 裁剪区默认正方形
autoCropArea: 0, // 自动调整裁剪图片
cropBoxMovable: true, // 禁止裁剪区移动
cropBoxResizable: false, // 禁止裁剪区缩放
background: false // 关闭默认背景
})
五、保存更新
此部分省略
不过要注意的是:
- 如果自己后端提供了服务端的裁切,就使用getData方法 得到裁剪区域的参数。
console.log(this.cropper.getData())
- 如果是纯客户端的图片裁切,就使用:getCroppedCanvas方法。此方法得到裁切之后的图片对象,类似于URL.createObjectURL方法得到的文件对象。
- 此外如果是移动端项目 ,推荐使用getData()方法。
最后还是将更新图片的方法讲讲:
1.封装修改用户头像的方法
// 修改用户头像的方法
export const updatePhoto = (fd) => {
return axios({
method: 'PATCH',
url: '',
data: fd
})
}
2.导入
import { updatePhoto } from '@/api/user.js'
3.发送请求
onChange() {
// 获取 裁剪后的 图片数据
this.cropper.getCroppedCanvas().toBlob(async (imgBlob) => {
try {
const fd = new FormData()
fd.append('photo', imgBlob)
const res = await updatePhoto(fd)
this.$emit('close') //关闭弹层
this.$emit('onChangePhoto', res.data.data.photo) //更新视图
console.log(res)
this.$toast.success('上传成功')
} catch (err) {
this.$toast.fail('上传失败')
}
})
}