基于elemenui+vue的上传头像加裁剪功能

npm install vue-cropper //安装
import { VueCropper } from ‘vue-cropper’ //导入
components: { //注册
VueCropper,
},

<el-form :model="form" label-width="80px" class="input-dialog-form" size="small" style="margin-top:20px;">
                <el-form-item label="头像">
                    <div class="avatar-uploader">
                        <label class="el-upload el-upload--text" for="uploads">
                            <img v-if="form.avatar" :src="form.avatar_path" class="avatar">
                            <div v-else class="avatar-uploader-icon">
                                <div class="upload-icon avatar-upload_icon"></div>
                            </div>
                        </label>
                        <input type="file" id="uploads" style="position:absolute; clip:rect(0 0 0 0);" accept="image/png, image/jpeg, image/gif, image/jpg" @change="uploadImg($event)">
                    </div>
                </el-form-item>
           <div class="save-form-button">
                <el-button size="small" type="primary" :loading="saveLoading" @click="saveUserInfo">保 存</el-button>
            </div>
//裁剪图片
        <el-dialog title="图片裁剪" :visible.sync="dialogCropper" class="avatar-cropper">
            <div>
                <vueCropper
                    style="height:320px;"
                    ref="cropper"
                    :img="option.img"
                    :outputSize="option.size"
                    :outputType="option.outputSize"
                    :autoCrop="option.autoCrop"
                    :autoCropWidth="option.autoCropWidth"
                    :autoCropHeight="option.autoCropHeight"
                    :fixedBox="option.fixedBox"
                    :info="option.info"
                    @realTime="realTime"
                ></vueCropper>
                <div style="margin:10px 0px;">头像预览:</div>
                <div class="show-preview" :style="{'width': previews.w + 'px', 'height': previews.h + 'px', 'overflow': 'hidden'}">
                    <div :style="previews.div">
                        <img :src="previews.url" :style="previews.img">
                    </div>
                </div>
                <div class="show-preview preview-style_1" :style="{'width': previews.w + 'px', 'height': previews.h + 'px', 'overflow': 'hidden'}">
                    <div :style="previews.div">
                        <img :src="previews.url" :style="previews.img">
                    </div>
                </div>
                <div class="show-preview preview-style_2" :style="{'width': previews.w + 'px', 'height': previews.h + 'px', 'overflow': 'hidden'}">
                    <div :style="previews.div">
                        <img :src="previews.url" :style="previews.img">
                    </div>
                </div>
            </div>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogCropper = false">取 消</el-button>
                <el-button type="primary" :loading="uploadLoading" @click="finishImg">确 定</el-button>
            </span>
        </el-dialog>

js部分

script>
    import { VueCropper } from 'vue-cropper';

    export default {
        name: "sys_user_center",
        components: {
            VueCropper
        },
        data() {
            return {
                //用户信息编辑
                saveLoading: false,
                form: {
                    id: 0,
                    type: "",
                    name: "",
                    sex: "",
                    code: "",
                    mobile: "",
                    nick_name: "",
                    avatar: "",
                    avatar_path: "",
                },

                //上传图片
                headers: {
                    "Authorization": "Bearer " + localStorage.getItem("lsp_token")
                },
                accept: "image/*",
                upload_data: {
                    upload_type: "formData",
                },

                //上传图片裁剪
                dialogCropper: false,
                uploadLoading: false,
                previews: {},
                option: {
                    img: "",//裁剪图片的地址
                    size: 1,
                    outputSize: "png",//裁剪生成图片的质量
                    autoCrop: true,//是否默认生成截图框
                    autoCropWidth: "180",//默认生成截图框的宽度
                    autoCropHeight: "180",
                    fixedBox: true,//固定截图框的大小不允许改变
                    info: false,//裁剪框的大小信息
                },
                canMove: true,
                original: false,
                canMoveBox: true,
                autoCrop: true,
                autoCropWidth: 200,
                autoCropHeight: 200,
                fixedBox: true
            }
        },
        watch: {
            dialogCropper(val){//监听dialog的显示或者隐藏
                let vue = this;
                if(!val){//取消上传
                    vue.cancelUpload();
                }
            }
        },
        methods: {
            //获取用户信息
            async getUserInfo(){
                let vue = this;
                let res = await vue.$api.home.user();
                let data = res.data;
                vue.userInit(data.base)
            },
            //保存用户信息
            async saveUserInfo(){
                let vue = this;
                if(vue.form.mobile.trim() == ""){
                    vue.$message({type: 'warning', message: '请输入手机号'});
                    return false;
                }
                let params = {
                    mobile: vue.form.mobile,
                    nick_name: vue.form.nick_name,
                    avatar: vue.form.avatar,
                }
                vue.saveLoading = true;
                let res = await vue.$api.home.user(params, "put", "personal");
                vue.$message({
                    type: res.code == 0 ? 'success' : 'error',
                    message: res.message
                });
                vue.saveLoading = false;
            },
            userInit(val = null){
                let vue = this;
                vue.form = {
                    id: val ? val.user_id : 0,
                    type: val ? val.type_name : "",
                    name: val ? val.real_name : "",
                    sex: val ? val.sex_name : "",
                    code: val ? val.user_code : "",
                    mobile: val ? val.mobile : "",
                    nick_name: val ? val.nick_name : "",
                    avatar: val ? val.avatar : "",
                    avatar_path: val ? val.avatar_path : "",
                }
            },
           //选择本地图片
            uploadImg(e) {
                var vue = this;
                var file = e.target.files[0];
                if (!/\.(jpg|jpeg|png|bmp|JPG|PNG)$/.test(e.target.value)) {
                    vue.$message({message:'图片类型必须是jpeg,jpg,png,bmp中的一种', type:'warning'});
                    return false;
                } 
                var reader = new FileReader(); 
                reader.onload =(e) => {//监听图片上传成功事件
                    let data; 
                    if (typeof e.target.result === 'object') { 
                        // 把Array Buffer转化为blob 如果是base64不需要 
                        data = window.URL.createObjectURL(new Blob([e.target.result])) 
                    }else { 
                        data = e.target.result 
                    }
                    vue.option.img = data;			***//重要***
                    vue.dialogCropper = true;
                } 
                // 转化为base64 
                reader.readAsDataURL(file) 
                // 转化为blob
                //reader.readAsArrayBuffer(file);
            },
            compress(img) {//canvas画图 压缩 返回
                let canvas = document.createElement("canvas"),
                ctx = canvas.getContext("2d"),
                initSize = img.src.length,
                width = img.width,
                height = img.height;
                canvas.width = width
                canvas.height = height
                // 铺底色 
                ctx.fillStyle = "#fff"
                ctx.fillRect(0, 0, canvas.width, canvas.height)
                ctx.drawImage(img, 0, 0, width, height)
                //进行压缩 
                let ndata = canvas.toDataURL("image/jpeg", 0.8)
                return ndata
            },
            // //上传头像
            finishImg(type) {
                let vue = this;
                let formData = new FormData();
                //获取截图的base64 数据
                vue.$refs.cropper.getCropData((data) => {
                    let img = new Image();
                    img.src = data;
                    img.onload = function(){
                        let data = vue.compress(img);
                        vue.uploadLoading = true;
                        let params = {
                            file: data,
                            type: "avatar"
                        }
                        vue.$api.home.avatarImage(params, "post").then((res) => {
                            if(res.code == 0){
                                vue.form.avatar_path = res.data.full_path;
                                vue.form.avatar = res.data.image_name;
                                vue.uploadLoading = false;
                                vue.dialogCropper = false;
                            }else{
                                vue.$message({type: 'error', message: res.message});
                            }
                        });
                    }
                }) 
            },
            // 取消上传
            cancelUpload() {
                let f = document.getElementById('uploads');
                if(f.value){
                    try{
                        f.value = ''; //for IE11, latest Chrome/Firefox/Opera...
                    }catch(err){
                    }
                    if(f.value){ //for IE5 ~ IE10
                        var form = document.createElement('form'), ref = f.nextSibling, p = f.parentNode;
                        form.appendChild(f);
                        form.reset();
                        p.insertBefore(f,ref);
                    }
                }
            },
            realTime(data){//预览图片
                let vue = this;
                vue.previews = data;//传给要展示的
            },
        },
        mounted() {
            let vue = this;
            vue.user = JSON.parse(localStorage.getItem("lsp_user"))
            if(vue.user){
                vue.getUserInfo()
            }else{
                vue.$message({type: 'warning', message: '未查询到登录信息,请重新登录'});
            }
        }
    }
</script>

css样式

<style lang="scss" scoped>
    .input-dialog-form{
        width: 600px;
        margin-left: 5%;
    }

    .save-form-button{
        width:520px;
        display: inline-block;
        margin-left: 134px;
        margin-top: 20px;
        padding:15px;
        text-align: center;
    }

    /*头像上传*/
    .avatar-uploader{
        height: 120px;
    }

    .avatar-uploader-icon {
        border: 1px dashed #c0ccda;
        background-color: #fbfdff;
        border-radius: 6px;
        cursor: pointer;
        width: 120px;
        height: 120px;
        text-align: center;
        position: relative;
        overflow: hidden;
    }

    .upload-icon{
        width:50px;
        height:50px;
        display: inline-block;
        margin-top: 30px;
    }

    .avatar-uploader-icon:hover {
        border-color: #409eff;
    }

    .avatar {
        width: 120px;
        height: 120px;
        display: block;
        border-radius: 6px;
        border: 1px solid #C9D9F5;
    }

    .show-preview{
        display: inline-block;
        border: 1px solid #C9D9F5;
    }

    .preview-style_1{
        transform: scale(0.6667);
        position: relative;
        top:30px;
        border: 2px solid #C9D9F5;
    }

    .preview-style_2{
        transform: scale(0.3334);
        position: relative;
        top:60px;
        left:-60px;
        border: 3px solid #C9D9F5;
    }
</style>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用vant-uploader和vue-cropper来实现裁剪图片并上,你可以按照以下步骤进行操作: 1. 首先,安装vant和vue-cropper插件。你可以使用npm或yarn来安装它们。 2. 在你的Vue组件中,引入vant-uploader和vue-cropper组件。 3. 在模板中,使用vant-uploader组件来实现图片上功能。设置上的action属性为你的上接口地址,并设置on-success事件来处理上成功后的逻辑。 4. 在on-success事件中,获取到上成功后的图片地址,并将其递给vue-cropper组件。 5. 在vue-cropper组件中,设置裁剪框的样式和裁剪比例等属性。使用v-model指令来绑定裁剪后的图片数据。 6. 在提交按钮的点击事件中,将裁剪后的图片数据上到服务器。 下面是一个简单的示例代码: ```vue <template> <div> <van-uploader action="/upload" :on-success="handleUploadSuccess" ></van-uploader> <vue-cropper v-if="showCropper" :src="cropperSrc" :output-size="{ width: 200, height: 200 }" :output-type="'jpeg'" :fixed-box="true" :fixed-number="\[1, 1\]" v-model="croppedImage" ></vue-cropper> <button @click="handleSubmit">提交</button> </div> </template> <script> import { VanUploader } from 'vant'; import VueCropper from 'vue-cropper'; export default { components: { VanUploader, VueCropper, }, data() { return { showCropper: false, cropperSrc: '', croppedImage: '', }; }, methods: { handleUploadSuccess(response) { // 获取上成功后的图片地址 const imageUrl = response.data.imageUrl; // 显示裁剪组件 this.showCropper = true; // 设置裁剪组件的图片地址 this.cropperSrc = imageUrl; }, handleSubmit() { // 提交裁剪后的图片数据到服务器 // this.croppedImage 包含裁剪后的图片数据 }, }, }; </script> ``` 请注意,以上代码只是一个简单的示例,你需要根据你的实际需求进行适当的修改和调整。同时,你还需要在后端实现相应的上裁剪功能

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值