最近修改bug,测试提了一个优化:上传图片,然后对图片进行平移,放大缩小来调整做头像,因此记录一下整个开发过程的思路。
整体思路:
上传图片,获取地址
->
给到调整框(对图片进行放大缩小平移操作来确定头像)
->
实时预览(获取调整后的图片)
->
确定将调整后的地址回传
使用组件:vue-cropper
父组件(弹框)代码:
<script lang="tsx">
import { Component, Prop, Vue, Emit, Watch } from 'vue-property-decorator'
//引入子组件(图片裁剪功能)
import cropper from './cropper.vue'
import { EMessage,EavatarType,EavatarCutParam } from '@/views/userCenter/model'
import { stripscript } from '@/utils/util'
@Component({
components:{
cropper
}
})
export default class AvatarCut extends Vue {
/**
* 个人信息表单
* @param Object
*/
avatarFile:any = null
// 上传图片返回地址
imgUrl = ''
// 图片裁剪值,实时预览
previews:any = {}
beforeAvatarUpload(file:any){
let _this = this;
const isImage = file.type == EavatarType.PNG || file.type == EavatarType.JPG || file.type == EavatarType.JPEG;
const isLt500KB = file.size < EavatarCutParam.FILESIZE;
if (!isImage) {
this.$message.error(this.$t('userCenter.isavatarType'));
return
}
if (!isLt500KB) {
this.$message.error(this.$t('userCenter.isavatarSize'));
return
}
var reader = new FileReader();
//转base64
reader.onload = function(e:any) {
// 上传完成,将图片地址给到裁剪组件
_this.imgUrl = e.target.result
}
reader.readAsDataURL(file);
let fileName = stripscript(file.name)
if(fileName != file.name){
var renameFile = new File([file],fileName,{type:file.type})
console.log(file)
file = renameFile
console.log(file)
}
this.avatarFile = file;
return false;
}
@Emit()
cutCanvas(base:any){
return {avatarPerview:base,avatarFile:this.avatarFile}
}
// 实时监听裁剪结果,结果就是最后确定值
realTime(data:any) {
console.log('kkkkkkkkk',data)
this.previews = data.data;
this.cutCanvas(data.base)
}
render() {
return (
<div class="my-message-popup-content">
<el-upload
class="upload-demo"
action="#"
before-upload={this.beforeAvatarUpload}
accept="image/jpeg,image/png,image/jpg"
on-preview="handlePreview"
list-type="picture"
show-file-list={false}>
<el-button type="primary">{this.$t('userCenter.uploadAvatars')}</el-button>
<div slot="tip" class="el-upload__tip">{this.$t('userCenter.uploadLimit')}</div>
</el-upload>
<div class="content-file">
<div class="file-canvas">
<cropper props={{url:this.imgUrl}} onrealTime={this.realTime} ref='cropper'></cropper>
</div>
<div class="file-preview">
<div class="preview-title">{this.$t('userCenter.perviewAvatars')}</div>
<div class="preview-avatar">
<div style={this.previews.div} class="preview">
<img src={this.previews.url?this.previews.url: require('@/assets/images/head_default.svg')} style={this.previews.img}/>
</div>
</div>
</div>
</div>
</div>
)
}
}
</script>
<style lang="less" scoped>
.my-message-popup-content{
padding:20px 0 20px 0px;
.upload-demo{
height: 36px;
display: flex;
.el-upload__tip{
line-height: 36px;
margin-top: 0;
margin-left: 14px;
color: #999999;
}
/deep/ .el-button{
width: 104px;
height: 38px;
background: #2255B9;
border-radius: 0;
}
}
.content-file{
width: 100%;
height: 208px;
margin-top: 20px;
margin-bottom: 40px;
display: flex;
.file-canvas{
width: 322px;
height: 100%;
position: relative;
border: 1px solid #F1F1F1;
.file-shade{
position: absolute;
width: 100%;
height: 100%;
top: 0;left: 0;
z-index: 10;
.file-shade-top,.file-shade-bottom{
width:100%;;background: #000; opacity: 0.6;
}
.file-shade-middle{
display: flex;
.file-shade-left,.file-shade-right{
height: 160px;background: #000; opacity: 0.6;
}
.file-cut{
width: 160px;
height: 160px;
border: 1px dashed #1890FF;
cursor: move;
}
}
}
}
.file-preview{
width: 168px;
height: 100%;
margin-left: 20px;
border: 1px solid #F1F1F1;
.preview-title{
margin-top: 36px;
color: #333333;
line-height: 16px;
width: 100%;
text-align: center;
//font-weight: 600;
font-size: 16px;
}
.preview-avatar{
width: 100%;
height: 132px;
margin-top:24px;
text-align: center;
}
}
}
/deep/ .preview{
width: 90px;
height: 90px;
margin: 0 auto;
overflow: hidden;
border-radius: 50%;
img{
width: 90px;
height: 90px;
z-index: -1;
}
}
/deep/ .vue-cropper{
background: #FFFFFF;
}
}
</style>
复制代码
子组件(裁剪功能)代码
<template>
<div>
<vueCropper
style="width:320px;height:206px"
ref="cropper"
:img='url'
:autoCrop="options.autoCrop"
:fixedBox="options.fixedBox"
:canMoveBox="options.canMoveBox"
:autoCropWidth="options.autoCropWidth"
:autoCropHeight="options.autoCropHeight"
:centerBox="options.centerBox"
@realTime="realTime"
></vueCropper>
</div>
</template>
<script>
import { VueCropper } from 'vue-cropper'
export default {
name: 'cropper',
components: {
VueCropper
},
props:{
url:{
default:'',
type:String
}
},
data(){
return{
options: {
autoCrop: true, //默认生成截图框
fixedBox: true, //固定截图框大小
canMoveBox: false, //截图框不能拖动
centerBox: false, //截图框被限制在图片里面
autoCropWidth:100, //截图框宽度
autoCropHeight:100, //截图框高度
},
previews:{}
}
},
methods:{
// 实时预览函数
realTime(data){
// 获取裁剪图片blob数据,可以直接用getCropData获取base64
this.$refs.cropper.getCropBlob((blob)=>{
this.blobToDataURL(blob,(base)=>{
this.$emit('realTime',{data,base})
})
})
},
// 将blob转换成base64
blobToDataURL(blob, callback) {
let a = new FileReader();
a.onload = function (e) { callback(e.target.result); }
a.readAsDataURL(blob);
}
}
}
</script>
<style scoped>
</style>
复制代码
效果
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END