Vue3中怎么实现选取头像并裁剪
这篇文章主要介绍“Vue3中怎么实现选取头像并裁剪”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Vue3中怎么实现选取头像并裁剪”文章能帮助大家解决问题。
最终效果
安装VueCropper组件
yarn add vue-cropper@next
上面的安装值针对Vue3的,如果时Vue2或者想使用其他的方式引用,请访问它的npm官方地址:官方教程。
在组件中引用
使用时也很简单,只需要引入对应的组件和它的样式文件,我这里没有在全局引用,只在我的组件文件中引入
<script>import { userInfoByRequest } from '../js/api'import { VueCropper } from 'vue-cropper'import 'vue-cropper/dist/index.css'export default { components: { VueCropper },}
然后用<vue-cropper>
标签来进行使用,需要注意的是它需要有外层容器包裹,并且给外层容器设置指定的高度。
<el-dialog title="头像设置" v-model="showSetAvatarDialog"> <div class="cropperBox"> <vue-cropper ref="cropper" :canMoveBox="false" :img="avatarBase64" :fixedBox="true" :autoCrop="true" autoCropWidth="200" autoCropHeight="200" outputType="png"></vue-cropper> </div> <div class="optionBtn"> <el-button @click="rotateLeft"><i class="fa fa-rotate-left"></i>左旋转</el-button> <el-button @click="rotateRight"><i class="fa fa-rotate-right"></i>右旋转</el-button> <el-button @click="getPickAvatar" type="primary"><i class="fa fa-save"></i>保存</el-button> </div></el-dialog>
我这里是将它放到一个Dialog弹框中,当选择完图片后会弹出这弹框。
关于它的一些属性可以参考:官方教程中的详细描述,上面用到的属性含义:
canMoveBox:截图框能否移动,默认是可以的,我设置为false,因为我想让图片移动,截图框不动。
img:图片源,可以是图片网址也可以是base64数据。
fixedBox:不允许改变截图框的大小,默认是可以的,这里我设置为了true,因为我想要一个固定长宽的正方形。
autoCrop:是否默认生成截图框,这里设置为了true
autoCropWidth:自动生成截图框的默认宽度
autoCropHeight:自动生成截图框的默认高度
outputType:输出图片的格式,这里我设置为了png格式
获取图片内容
通过下面这种方式,使用它内置的方法获取截取图片的内容
//获取base64格式的截图内容this.$refs.cropper.getCropData(data => { // do something console.log(data) })//获取blob格式的截图内容this.$refs.cropper.getCropBlob(data => { // do something console.log(data) })
更多其他的内置方法请参考官方教程中的详细描述。
自定义上传图片
截图组件有了,下面需要我们选择一个图片,然后通过前端转换为base64后弹出截图的组件进行选择,这里用原生的input标签,type为file,但是原生的样式不是我们想要的,演示中我是点击一个相机的小图标后选择图片,这个实现过程如下:
首先将 中加入hidden属性,将它隐藏
然后当点击相机图标时通过js实现点击input的事件
在input标签中定义change事件,进行图片转base64的逻辑
然后将转换的数据设置到全局变量中
完整的代码实现
UserCenter.vue
<template> <div class="userCenter"> <input id="avatarFile" type="file" hidden @change="selectFile" /> <header> <div class="avatar"> <div class="back"> <el-tooltip content="返回"> <i @click="back" class="fa fa-arrow-left"></i> </el-tooltip> </div> <div class="topInfo"> <el-avatar :size="120" :class="lazy" data-src="avatarBlob==null?(userInfo.avatar==null?defaultAvatar:userInfo.avatar):avatarBlob"></el-avatar> <div class="setAvatar"> <el-tooltip content="修改头像"> <i @click="getFile" class="fa fa-camera"></i> </el-tooltip> </div> <div class="username">{{userInfo.nickName}}</div> </div> </div> </header> <el-row justify="center"> <el-col :lg="12" :xl="12" :md="18" :sm="20" :xs="20"> <div class="userInfoBox"> <div class="headerOption"> <el-tooltip content="修改用户基本信息,涉及账号的修改请点击底栏的操作按钮"> <el-link @click="editUserInfo"><i class="fa fa-edit"></i></el-link> </el-tooltip> </div> <ul> <li> <div class="userInfoTitle">用户名:</div> <div class="userInfoValue">{{userInfo.username}}</div> </li> <li> <div class="userInfoTitle">邮箱:</div> <div class="userInfoValue">{{userInfo.email}}</div> </li> <li> <div class="userInfoTitle">昵称:</div> <div class="userInfoValue">{{userInfo.nickName}}</div> </li> <li> <div class="userInfoTitle">性别:</div> <div class="userInfoValue">{{userInfo.gender==3?'保密':(userInfo.gender==0?'男':'女')}}</div> </li> <li> <div class="userInfoTitle">年龄:</div> <div class="userInfoValue">{{userInfo.age}}</div> </li> <li> <div class="userInfoTitle">生日:</div> <div class="userInfoValue">{{userInfo.birthday}}</div> </li> </ul> </div> </el-col> </el-row> <div class="option"> <el-button class="optionBtn" size="large" round><i class="fa fa-user"></i>用户名修改</el-button> <el-button class="optionBtn" size="large" round><i class="fa fa-lock"></i>修改密码</el-button> <el-button class="optionBtn" size="large" round><i class="fa fa-envelope"></i>修改邮箱</el-button> <el-button class="optionBtn" size="large" round><i class="fa fa-toggle-on"></i>激活邮箱</el-button> <el-button class="optionBtn" size="large" round><i class="fa fa-power-off"></i>注销账号</el-button> </div> <el-dialog title="基本信息" v-model="showUserInfoDialog"> <el-form :model="userInfoForm"> <el-form-item label="昵称"> <el-input placeholder="请输入昵称" v-model="userInfoForm.nickName"></el-input> </el-form-item> <el-form-item label="性别"> <el-select v-model="userInfoForm.gender"> <el-option v-for="item in genders" :key="item.id" :label="item.genderName" :value="item.genderCode"></el-option> </el-select> </el-form-item> <el-form-item label="生日"> <el-date-picker v-model="userInfoForm.birthday" :locale="locale" placeholder="选择出生日期" value-format="yyyy-MM-dd"></el-date-picker> </el-form-item> <div class="submitBtn" > <el-button @click="showUserInfoDialog=false" type="info">取消</el-button> <el-button type="primary">确定</el-button> </div> </el-form> </el-dialog> <el-dialog title="头像设置" v-model="showSetAvatarDialog"> <div class="cropperBox"> <vue-cropper ref="cropper" :canMoveBox="false" :img="avatarBase64" :fixedBox="true" :autoCrop="true" autoCropWidth="200" autoCropHeight="200" outputType="png"></vue-cropper> </div> <div class="optionBtn"> <el-button @click="rotateLeft"><i class="fa fa-rotate-left"></i>左旋转</el-button> <el-button @click="rotateRight"><i class="fa fa-rotate-right"></i>右旋转</el-button> <el-button @click="getPickAvatar" type="primary"><i class="fa fa-save"></i>保存</el-button> </div> </el-dialog> </div></template><script>import { userInfoByRequest } from '../js/api'import { VueCropper } from 'vue-cropper'import 'vue-cropper/dist/index.css'export default { components: { VueCropper }, data() { return { userInfo: {}, defaultAvatar: 'https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png', userInfoForm: {}, genders: [ { id: 1, genderName: '男性', genderCode: 0, }, { id: 2, genderName: '女性', genderCode: 1, }, { id: 3, genderName: '保密', genderCode: 3, } ], showUserInfoDialog: false, showSetAvatarDialog: false, avatarBase64:'', avatarBlob: null } }, methods: { back() { this.$router.go(-1) }, getUserInfo() { userInfoByRequest().then(res => { this.userInfo = res.data; }) }, editUserInfo() { this.userInfoForm.nickName = this.userInfo.nickName; this.userInfoForm.gender = this.userInfo.gender; this.userInfoForm.birthday = this.userInfo.birthday; this.showUserInfoDialog = true; }, getPickAvatar() { this.$refs.cropper.getCropData(data => { this.avatarBlob = data }) this.showSetAvatarDialog = false; }, rotateLeft() { this.$refs.cropper.rotateLeft(); }, rotateRight() { this.$refs.cropper.rotateRight(); }, getFile() { let fileEle = document.getElementById('avatarFile') fileEle.click() }, selectFile(e) { var file = e.target.files[0]; var filesize = file.size; var filename = file.name; var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = (e) => { var imgcode = e.target.result; this.avatarBase64 = imgcode this.showSetAvatarDialog = true; } } }, mounted() { this.getUserInfo(); }}</script><style scoped>.userCenter { display: flex; flex-direction: column; justify-content: center;}.username { color: #fff; font-weight: bold; font-size: 19px; padding: 0 10px;}header { text-align: center; padding: 10px; background-color: #333;}.topInfo { animation: userInfoCard 2s; -webkit-animation: userInfoCard 2s; }.back { text-align: left; color: #fff; position: relative; left: 10px;}.back>i { cursor: pointer;}.userInfoBox { box-shadow: 2px 3px 10px #D3d7d4; margin-top: 20px; padding: 20px; background-color: #fff; font-size: 16px; text-align: center; border-radius: 4px; animation: userInfoCard 3s; -webkit-animation: userInfoCard 3s; }.setAvatar { position: relative; top: -20px; font-size: 14px; color: #000; margin: -10px;}.setAvatar>i { cursor: pointer;}ul>li { display: flex; padding: 5px;}.userInfoTitle { font-weight: bold; width: 100px; text-align: right; padding-right: 10px;}.option { width: 100%; text-align: center; position: fixed; bottom: 20px; border: 1px solid gainsboro; padding: 10px;}.optionBtn { font-weight: bold; text-align: center; margin-top: 10px;}.headerOption { text-align: right;}@keyframes userInfoCard { from { opacity: 0; } to { opacity: 1; }}@-webkit-keyframes userInfoCard { from { opacity: 0; } to { opacity: 1; }}.cropperBox { width: 100%; height: 300px;}</style>
关于“Vue3中怎么实现选取头像并裁剪”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网行业资讯频道,小编每天都会为大家更新不同的知识点。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341