vue element upload上传组件 裁剪后上传

上传文件时候接到一个需求 商品必须为固定尺寸 在网上找的 基本在 before-upload 加限制条件没有根本的解决问题 于是想到裁剪后上传

之前上传文件的标签

                  <el-upload
                    class="avatar-uploader"
                    :headers="uploadHeaders"
                    :action="uploadUrl + '?updateSupport=' + 0"
                    :show-file-list="false"
                    :on-success="handleAvatarSuccess"
                    :before-upload="beforeAvatarUpload"
                  >
                    <img v-if="imageUrl" :src="imageUrl" class="avatar">
                    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
                    <template #tip>
                      <div class="el-upload__tip">可上传一张图片,140*140</div>
                    </template>
                  </el-upload>

 参考其他人想要实现自定义上传 需要修改  auto-upload:false http-request 自定义上传方法等

后来发现没有那么麻烦 仅保留before-upload即可 

                           <el-upload
                                    class="avatar-uploader"
                                    :action="''"
                                    :show-file-list="false"
                                    :before-upload="beforeAvatarUpload"
                            >
                                <img v-if="imageUrl" :src="imageUrl" class="avatar">
                                <i v-else class="el-icon-plus avatar-uploader-icon"></i>
                                <template #tip>
                                    <div class="el-upload__tip">可上传一张图片,140*140</div>
                                </template>
                            </el-upload>

裁剪工具为 VueCropper 

  •  安装 npm install vue-cropper // npm 安装
  • 局部引入并编写组件 (参考其他小伙伴进行修改)
  • <template>
        <div>
            <el-dialog
                    title="图片剪裁"
                    v-model="dialogVisiblex"
                    :close-on-press-escape="false"
                    :close-on-click-modal="false"
                    append-to-body
                    width="1000px"
            >
                <div class="cropper-content">
                    <div class="cropper" style="text-align:center">
                        <vueCropper
                                ref="cropper"
                                :img="option.img"
                                :outputSize="option.outputSize"
                                :outputType="option.outputType"
                                :info="option.info"
                                :canScale="option.canScale"
                                :autoCrop="option.autoCrop"
                                :autoCropWidth="option.autoCropWidth"
                                :autoCropHeight="option.autoCropHeight"
                                :fixedBox="option.fixedBox"
                                :fixed="option.fixed"
                                :fixedNumber="option.fixedNumber"
                                :canMove="option.canMove"
                                :canMoveBox="option.canMoveBox"
                                :original="option.original"
                                :centerBox="option.centerBox"
                                :infoTrue="option.infoTrue"
                                :full="option.full"
                                :enlarge="option.enlarge"
                                :mode="option.mode"
                        >
                        </vueCropper>
                    </div>
                </div>
                <template #footer class="dialog-footer">
                    <el-button @click="dialogVisiblex = false">取消</el-button>
                    <el-button type="primary" @click="finish" :loading="loading"
                    >确认</el-button
                    >
                </template>
            </el-dialog>
        </div>
    </template>
    
    <script>
        import VueCropper from "vue-cropper/src/vue-cropper.vue"
    
        export default {
            components: {VueCropper},
            props: {},
            data() {
                return {
                    dialogVisiblex: false,
                    loading: false,
                    option: {
                        img: '', // 裁剪图片的地址 url 地址, base64, blob
                        outputSize: 1, // 裁剪生成图片的质量
                        outputType: 'jpeg', // 裁剪生成图片的格式 jpeg, png, webp
                        info: true, // 裁剪框的大小信息
                        canScale: true, // 图片是否允许滚轮缩放
                        autoCrop: true, // 是否默认生成截图框
                        autoCropWidth: 345, // 默认生成截图框宽度
                        autoCropHeight: 245, // 默认生成截图框高度
                        fixedBox: true, // 固定截图框大小 不允许改变
                        fixed: true, // 是否开启截图框宽高固定比例
                        fixedNumber: [1, 1], // 截图框的宽高比例 [ 宽度 , 高度 ]
                        canMove: true, // 上传图片是否可以移动
                        canMoveBox: true, // 截图框能否拖动
                        original: false, // 上传图片按照原始比例渲染
                        centerBox: true, // 截图框是否被限制在图片里面
                        infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
                        full: true, // 是否输出原图比例的截图
                        enlarge: '1', // 图片根据截图框输出比例倍数
                        mode: 'contain' // 图片默认渲染方式 contain , cover, 100px, 100% auto
                    },
                    unimgurl: '',
                    success: () => {} // 回调方法
                }
            },
            computed: {},
            watch: {},
            created() {
    
            },
            mounted() {},
            activated() {},
            methods: {
                showModal(obj) {
                    if (obj.img) {
                        this.option.img = obj.img
                    }
                    //裁剪生成图片的质量
                    if (obj.outputSize) {
                        this.option.outputSize = obj.outputSize
                    } else {
                        this.option.outputSize = 1
                    }
                    //裁剪生成图片的格式
                    if (obj.outputType) {
                        this.option.outputType = obj.outputType
                    } else {
                        this.option.outputType = 'jpeg'
                    }
                    //裁剪框的大小信息
                    if (obj.info) {
                        this.option.info = obj.info
                    } else {
                        this.option.info = true
                    }
                    //图片是否允许滚轮缩放
                    if (obj.canScale) {
                        this.option.canScale = obj.canScale
                    } else {
                        this.option.canScale = true
                    }
                    //是否默认生成截图框
                    if (obj.autoCrop) {
                        this.option.autoCrop = obj.autoCrop
                    } else {
                        this.option.autoCrop = true
                    }
                    //默认生成截图框宽度
                    if (obj.autoCropWidth) {
                        this.option.autoCropWidth = obj.autoCropWidth
                    } else {
                        this.option.autoCropWidth = 375
                    }
                    //默认生成截图框高度
                    if (obj.autoCropHeight) {
                        this.option.autoCropHeight = obj.autoCropHeight
                    } else {
                        this.option.autoCropHeight = 245
                    }
                    //固定截图框大小 不允许改变
                    if (obj.fixedBox) {
                        this.option.fixedBox = obj.fixedBox
                    } else {
                        this.option.fixedBox = false
                    }
                    //是否开启截图框宽高固定比例
                    if (obj.fixed) {
                        this.option.fixed = obj.fixed
                    } else {
                        this.option.fixed = true
                    }
                    //截图框的宽高比例
                    if (obj.fixedNumber) {
                        this.option.fixedNumber = obj.fixedNumber
                    } else {
                        this.option.fixedNumber = [this.option.autoCropWidth, this.option.autoCropHeight]
                    }
                    //上传图片是否可以移动
                    if (obj.canMove) {
                        this.option.canMove = obj.canMove
                    } else {
                        this.option.canMove = true
                    }
                    //截图框能否拖动
                    if (obj.canMoveBox) {
                        this.option.canMoveBox = obj.canMoveBox
                    } else {
                        this.option.canMoveBox = true
                    }
                    //上传图片按照原始比例渲染
                    if (obj.original) {
                        this.option.original = obj.original
                    } else {
                        this.option.original = false
                    }
                    //截图框是否被限制在图片里面
                    if (obj.centerBox) {
                        this.option.centerBox = obj.centerBox
                    } else {
                        this.option.centerBox = true
                    }
                    //true 为展示真实输出图片宽高 false 展示看到的截图框宽高
                    if (obj.infoTrue) {
                        this.option.infoTrue = obj.infoTrue
                    } else {
                        this.option.infoTrue = true
                    }
                    //是否输出原图比例的截图
                    if (obj.full) {
                        this.option.full = obj.full
                    } else {
                        this.option.full = true
                    }
                    //图片根据截图框输出比例倍数
                    if (obj.enlarge) {
                        this.option.enlarge = obj.enlarge
                    } else {
                        this.option.enlarge = '1'
                    }
                    //图片默认渲染方式
                    if (obj.mode) {
                        this.option.mode = obj.mode
                    } else {
                        this.option.mode = 'contain'
                    }
                    if (obj.success) {
                        this.success = obj.success
                    } else {
                        this.success = () => {}
                    }
                    this.dialogVisiblex = true
                },
                finish() {
                    // 获取截图的数据
                    let that = this
                    this.$refs.cropper.getCropBlob(data => {
                        that.unimgurl = data
                        that.confirm()
                    })
                },
                confirm() {
                    this.success({
                        img: this.unimgurl
                    })
                    this.dialogVisiblex = false
                },
                cancel() {
                    this.dialogVisiblex = false
                }
            }
        }
    </script>
    <style lang="scss" scoped></style>
    <style lang="scss">
        .real_info_class {
            .el-checkbox__input .el-checkbox__inner {
                border-radius: 0;
            }
        }
        .file-image {
            width: 320px;
            height: 320px;
            font-size: 14px;
            border: 1px solid #cccccc;
            margin: 15px 0;
        }
    
        /* 截图 */
        /* .cropper-content {} */
        .cropper {
            width: 960px;
            height: 606px;
        }
    </style>
    

    注意引入方式为 

    import VueCropper from "vue-cropper/src/vue-cropper.vue"

在upload标签下加上如下代码

 下面贴出 完成的before-upload代码

  beforeAvatarUpload(file) {
                let _this = this
                return new Promise((resolve, reject) => {
                    let types = ['image/jpeg', 'image/jpg', 'image/png'];
                    // let width = 140;
                    // let height = 140;
                    const isJPG = types.includes(file.type)
                    const isLt2M = file.size / 1024 / 1024 < 2
                    if (!isJPG) {
                        _this.$message.error('上传图片只能是 JPG 或 png格式!')
                        reject()
                    }
                    if (!isLt2M) {
                        _this.$message.error('上传图片大小不能超过 2MB!')
                        reject()
                    }


                    let _URL = window.URL || window.webkitURL;


                    //上传前对图片进行裁剪
                    _this.$refs.iscropper.showModal({
                        img: _URL.createObjectURL(file) , // 裁剪图片的地址
                        autoCropWidth: 140, // 默认生成截图框宽度
                        autoCropHeight: 140, // 默认生成截图框高度
                        fixedBox:true,
                        success: res => {
                            //拿到裁剪后图片没有name 属性
                            //file的name属性为只读 不能手动设置
                            //创建一个新的图片对象 设置原始文件名
                            const cloneFile = new File([res.img], file.name);

                            const formData = new FormData()
                            //   console.log(param.file)
                            //通过 append 函数往formdata对象里传参,这里传的是后端需求的接口信息
                            formData.append('file', cloneFile)

                            //执行上传操作
                            request({
                                method: "post",
                                url: "/sys/file/upload/productImage",
                                data: formData,
                                headers: { "Content-Type": "multipart/form-data" },

                            }).then(response => {
                                //请求成功
                                _this.handleAvatarSuccess(response,cloneFile)
                            })

                            resolve()
                        }
                    })
                })
}

讲一下大概的思路 

  1. 第一步照常对上传文件做一个限制
  2. 打开裁剪框 设置固定的裁剪大小 并设置滚动放大缩小图片
  3. 由于裁剪后的图片没有文件名 并且文件名是只读  所以创建一个新的图片对象 并将图片原始文件名设置
  4. 文件传输是通过formdata上传的 创建formdata对象 将图片放在formdata对象中
  5. 上传成功后图片进行回显 并将图片id回传到业务数据中
            handleAvatarSuccess(res,file) {
                console.log(res)

                if(res.code == 2000){
                    this.$successmsg(res.msg)
                    this.imageUrl = URL.createObjectURL(file);
                    this.ruleForm.productImg = res.data.id
                }else{
                    this.$warnmsg(res.msg);
                    this.imageUrl = '';
                    this.ruleForm.productImg	 = ''
                }
            }

上传成功 后的操作 可根据自己 项目自定义 

最后的效果 

保存在本地的图片

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,针对您的问题,以下是实现 Vue+Element-UI上传图片并压缩的基本步骤: 1. 安装依赖 在项目中安装 Element-UI 和插件 vue-image-crop-upload 以及图片压缩库,可使用以下命令: ``` npm install element-ui vue-image-crop-upload compressjs --save ``` 2. 引入 Element-UI 在 main.js 中引入 Element-UI: ```javascript import Vue from 'vue' import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(ElementUI) ``` 3. 使用 vue-image-crop-upload 在需要上传图片的组件中使用 vue-image-crop-upload,可使用以下代码: ```vue <template> <div> <vue-image-crop-upload ref="upload" :url="uploadUrl" :headers="uploadHeaders" :size="size" :accept="accept" :beforeUpload="beforeUpload" :cropConfig="cropConfig" :compressConfig="compressConfig" @input="handleInput" @crop-success="handleCropSuccess" > <el-button size="small" type="primary">上传图片</el-button> </vue-image-crop-upload> </div> </template> <script> import VueImageCropUpload from 'vue-image-crop-upload' export default { components: { VueImageCropUpload }, data() { return { uploadUrl: 'xxx', // 上传地址 uploadHeaders: { // 上传请求头 Authorization: 'Bearer ' + getToken() }, size: 1024 * 1024 * 2, // 上传图片大小限制 accept: '.jpg,.jpeg,.png', // 上传图片格式限制 cropConfig: { // 图片裁剪配置 aspectRatio: 1 / 1, autoCropArea: 1, viewMode: 1, zoomable: false, guides: false, dragMode: 'move', cropBoxResizable: false, crop: () => {} }, compressConfig: { // 图片压缩配置 targetSize: 1024 * 1024, // 目标大小 quality: 0.7, // 压缩质量 mimeType: 'image/jpeg' // 输出格式 } } }, methods: { beforeUpload(file) { // 文件上传前的回调函数 this.$refs.upload.startUpload() }, handleInput(file) { // 文件选择后的回调函数 this.$refs.upload.showCrop() }, handleCropSuccess(blob, file) { // 图片裁剪成功后的回调函数 this.compressImage(blob, file) // 压缩图片 }, compressImage(blob, file) { // 图片压缩 const reader = new FileReader() reader.readAsDataURL(blob) reader.onload = (e) => { const base64 = e.target.result const compressedBlob = Compress.compress(base64, this.compressConfig) const compressedFile = new File([compressedBlob], file.name, { type: compressedBlob.type }) this.$emit('upload', compressedFile) // 触发上传事件 } } } } </script> ``` 4. 完成上传 在父组件中监听上传事件,使用 axios 或其他方法上传文件至服务器: ```vue <template> <div> <upload :action="uploadUrl" @upload="handleUpload"></upload> </div> </template> <script> import axios from 'axios' import Upload from './Upload.vue' export default { components: { Upload }, data() { return { uploadUrl: 'xxx' // 上传地址 } }, methods: { handleUpload(file) { const formData = new FormData() formData.append('file', file) axios.post(this.uploadUrl, formData).then(response => { console.log(response.data) }) } } } </script> ``` 以上就是实现 Vue+Element-UI上传图片并压缩的基本步骤,您可以根据您的具体需求进行修改和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值