美文网首页
vuecropper插件的使用

vuecropper插件的使用

作者: zsyyyyy | 来源:发表于2019-09-28 10:56 被阅读0次
    94def755706e634e7d77b5c46bf2822.png

    就是完成以上这种效果

    vuecropper插件的使用说明:https://blog.csdn.net/kangkang_style/article/details/82776082

    vuecropper就是一个组件来的,一般我们在父组件引进它

    <div style="position: relative;">
        <corpperlabel ref="cropper" :preImageList="preImageList" :haveDetele="true"></corpperlabel>
    </div>
    <script>
    //preImageList传给子组件corpperlabel 的图片数据
            preImageList: any = [];
            getPrePic() {
                indexApi.getPrePic({
                    preId: this.presId
                }).then(res => {
                    if (res["retCode"]) {
                        this.preImageList = res.data;
                        if (res.data.length > 0) {
                            let a: any = this.$refs.cropper;
                            a.changePreImageUrl(0);
                        }
                    } else {
                        if (!res["islogin"]) {
                            this.$alert(res["message"]);
                        }
                        console.error("数据查询错误");
                    }
                });
            }
    </script>
    

    子组件corpperlabel 部分

    <template>
      <div>
        <div class="wrapper"  style="position: relative;">
    //黑白格显示的图片
    //默认显示第一张,包括preImageList传进来的,当点击哪一项时,才显示哪一张
          <vuecropper style="height: 60vh;min-width:100%;"
                      ref="cropper"
                      :img="option.img"
                      :outputSize="option.size"
                      :outputType="option.outputType"
                      :info="true"
                      :full="option.full"
                      :canMove="option.canMove"
                      :canMoveBox="option.canMoveBox"
                      :fixedBox="option.fixedBox"
                      :original="option.original"
                      :canScale="option.canScale">
          </vuecropper>
         <div style="position: absolute   bottom: 70px;right: 20px;">
    //有图片数据时显示
            <span v-if="preImageList.length > 0">
              <span style="font-size: 28px;">{{preIndex+1}}</span>/<span style="">{{preImageList.length}}</span>
            </span>
    //无图片数据时显示暂无图片
            <span v-else
                  style="font-weight: 600;color: #666;">暂无图片</span>
          </div>、
          <div style="width:100%;background-color:#f7f7f7;display:flex;    justify-content: space-around;align-items: center;">
    //图片的操作按钮
    //放大
            <div class="iconcropper"
                 @click="changeScale(1)">
              <i class="iconfont icon-fangda"
                 style="font-size:24px;"></i>
            </div>
    //缩小
            <div class="iconcropper"
                 @click="changeScale(-1)">
              <i class="iconfont icon-suoxiao-"
                 style="font-size:28px;"></i>
            </div>
    //左旋转
            <div class="iconcropper"
                 @click="rotateLeft">
              <i class="iconfont icon-llfilterrotate"
                 style="font-size:31px;"></i>
            </div>
    //右旋转
            <div class="iconcropper"
                 @click="rotateRight">
              <i class="iconfont icon-youxuanzhuan"
                 style="font-size:28px;"></i>
            </div>
            <!-- v-promiss.edit -->
    //删除
            <div class="iconcropper"
                 @click="rotateDetele()"
                 :style="haveDetele && !notHaveAdd?'display:initial':'display:none'">
              <i class="iconfont icon-iconfontshanchu3"
                 style="font-size:24px;"
                 :style="(temporary &&  !preImageList[preIndex].temporary) || preImageList.length==0 ?'opacity: 0.2;':''"></i>
            </div>
    
            <div class="iconcropper"
                 @click="rotateSave()"
                 v-if="haveSave && !notHaveAdd"
                 v-promiss.edit>
              <!-- <el-tooltip class="item" effect="dark" content="保存所有暂存图片" placement="top-start" > -->
              <i class="iconfont icon-49"
                 style="font-size:28px;"
                 :style="allTemporary ?'':'opacity: 0.2;'"></i>
              <!-- </el-tooltip> -->
            </div>
          </div>
        </div>
    //照片列表哦
        <div style="width:100%;display: flex;margin:10px 0;align-items: center;overflow: auto; ">
          <div v-for="(item,index) in preImageList"
               :key="index"
               style="display: flex;margin-right:20px;    position: relative;    border-radius: 3px;"
               @click="changePreImageUrl(index)"
               class=""
               :class="preIndex == index ?'selectImage':'noselect'">
            <img :src="item.presImageUrl"
                 style="width:100px;height:100px;" />
          </div>
    //添加照片的按钮,注意这个事件的调用情况,下面有解释
          <div @click="doClick()"
               class="el-upload el-upload--picture-card"
               style="height: 100px;width: 100px;"
               v-if="!notHaveAdd">
            <div style="margin-right: 20px;height: 100px;width: 100px;display: flex;justify-content: center;align-items: center;">
              <i class="el-icon-plus"
                 style="font-size:21px;"></i>
            </div>
          </div>
    //原生JavaScript的添加照片上传,但是把它none掉
          <input type="file"
                 ref="logo"
                 id="logo"
                 style="display:none;"
                 @change="isSizeClear();" />
        </div>
    //删除提示弹框
        <el-dialog :close-on-click-modal="false"
                   :append-to-body="true"
                   title="警告"
                   :visible.sync="centerDialogVisible"
                   width="30%"
                   center>
          <div style="    text-align: center;
        height: 300px;
        overflow: hidden;
        width: 300px;
        margin: auto;"
               class="flex flex-align-center flex-pack-center">
            <img :src="option.img"
                 style="width:100%" />
          </div>
          <div style="text-align: center;
        margin-bottom: -20px;
        margin-top: 15px;
        color: #666;
        font-size: 15px;">是否删除当前选中的图片?</div>
          <span slot="footer"
                class="dialog-footer">
            <el-button size="small"
                       @click="centerDialogVisible = false">取 消</el-button>
            <el-button type="warning"
                       size="small"
                       @click="doDetele()">确 定</el-button>
          </span>
        </el-dialog>
      </div>
    </template>
    
    <script lang="ts">
    import Vue from "vue";
    import Component from "vue-class-component";
    import axios from "axios";
    import { Prop } from "vue-property-decorator";
    import * as indexApi from "../../api/indexApi";
    import * as Api from "../../api/api";
    
    import filterdrug from "../drug/filterdrug";
    import * as Config from "../../api/conf";
    import vuecropper from "vue-cropper";
    @Component({
      props: {},
      components: {
        filterdrug,
        vuecropper
        // prescriptioninfo
      }
    })
    export default class Corpperlabel extends Vue {
      @Prop({ required: false })
      preImageList: any;
      @Prop({ required: false })
      presId: any;
      @Prop({ required: false })
      haveDetele: boolean;
      @Prop({ required: false })
      haveSave: boolean;
      //true 不可以删除已有图片
      //false 全部图片可以删除
      @Prop({ required: false })
      temporary: boolean;
      @Prop({ required: false })
      notHaveAdd: boolean;
      get allTemporary() {
        let a = this.preImageList.filter(item => {
          return item.temporary;
        });
        return a.length > 0;
      }
      //传入网络图片地址和回调 将网络图片转换成base64格式
      getBase64(img, callback) {
        function getBase64Image(img, width, height) {
          //width、height调用时传入具体像素值,控制大小 ,不传则默认图像大小
          var canvas = document.createElement("canvas");
          canvas.width = width ? width : img.width;
          canvas.height = height ? height : img.height;
          var ctx = canvas.getContext("2d");
          ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
          var dataURL = canvas.toDataURL();
          callback(dataURL);
          return dataURL;
        }
        var image = new Image();
        image.setAttribute("crossOrigin", "anonymous");
        image.src = img + "?time=" + new Date().valueOf();
        if (img) {
          image.onload = function() {
            return getBase64Image(image, null, null);
          };
        }
      }
    //删除弹框
      centerDialogVisible = false;
    //点击图片列表的每一项,可以获取的点击当前的下标,为实参
      changePreImageUrl(index) {
        //使用定时器因为this.preImageList 不能立即拿到
        setTimeout(() => {
          console.log('我好想被调用了')
          let img = null;
          console.log(this.preImageList)
          if(this.preImageList[this.preIndex].presMinImageUrl){
              //使用回调拿取base64编码是因为 转换的时候使用了img的upload方法导致getBase64是异步的
            this.getBase64(this.preImageList[this.preIndex].presMinImageUrl, res => {
              img = res;
    转为base64后赋值给option.img
              this.option.img = img;
            });
          }else{
              //使用回调拿取base64编码是因为 转换的时候使用了img的upload方法导致getBase64是异步的
            this.getBase64(this.preImageList[this.preIndex].presImageUrl, res => {
              img = res;
              this.option.img = img;
            });
          }
        }, 100);
        //这个放在定时器外面是因为放在里面会出问题需要点击两次才能设置上index 原因不明,只能放在定时器外面
    preIndex 默认为零,把下标赋值给preIndex 
        this.preIndex = index;
      }
      crap = false;
      previews = {};
    
      option = {
        img: "",
        size: 1,
        full: false,
        outputType: "jpg",
        canMove: true,
        fixedBox: false,
        original: true,
        canMoveBox: false,
        canScale: true
      };
      downImg = "#";
    //放大
      changeScale(value) {
        let a: any = this.$refs.cropper;
        a.changeScale(value);
      }
    //右旋转
      rotateRight() {
        let a: any = this.$refs.cropper;
        a.rotateRight();
      }
    //旋转
      左rotateLeft() {
        let a: any = this.$refs.cropper;
        a.rotateLeft();
      }
    //点击删除弹框出来,需要判断有照片才能弹框删除
      rotateDetele() {
        if (
          (this.temporary && !this.preImageList[this.preIndex].temporary) ||
          this.preImageList.length == 0
        ) {
          return;
        }
        this.centerDialogVisible = true;
      }
    //删除
      doDetele() {
    his.preIndex在点击每一项的时候获取的,就是下标,如果不点击,就是默认第一张,下标是0
        this.preImageList.splice(this.preIndex, 1);
    //判断如果删除之后照片列表还有数据,而且删除的不是第一张,则vuecropper 显示删除的前一张,所以this.preIndex需要减一,如果删除的就是一张,则第二张图片就会变成就一张,所以this.preIndex还是为零
        if (this.preImageList.length > 0) {
          if (this.preIndex !== 0) {
            this.preIndex -= 1;
          }
        } else {
          this.option.img = null;
        }
        this.changePreImageUrl(this.preIndex);//然后调用changePreImageUrl
        this.centerDialogVisible = false;
      }
    //这里也是关键,点击+添加图片是,其实调用的的是原生的上传文件的控件
    //原生JavaScript的添加照片上传,但是把它none掉
          <input type="file"
                 ref="logo"
                 id="logo"
                 style="display:none;"
                 @change="isSizeClear();" />
        </div>
      doClick() {
        if ((<any>this.$refs.logo).files.length == 0) {
        } else {
          (<any>this.$refs.logo).value = "";
        }
        (<any>this.$refs.logo).click();
      }
    //选取
      isSizeClear() {
        let form = new FormData();//上传文件需要创建这样的实例
        let logo = (<any>this.$refs.logo).files[0];
        console.log( (<any>this.$refs.logo).files)
            console.log( (<any>this.$refs.logo).files[0])
        console.log(logo)//上传到服务器需要的参数
        if (!logo) {
          return;
        }
    //上传文件
     form.append("file", logo);//append到form 实例
    
    //封装好上传图片的勾子
    //export const uploadFile = (form) => {
        //return axios.post(upload, form, {
           // method: 'post',
            //headers: { 'Content-Type': 'multipart/form-data' }
       // })
         //   .then(response => response)
          //  .catch(error => error);
    //};
    //注意所有需要上传图片的接口,都需要先请求上传图片接口**
    //图片接口上传完会返回一个图片地址给我们
    //uploadFile是图片上传接口地址
        Api.uploadFile(form)//当做参数传进去,就可以了,返回一个前端的图片路径
          .then(({ data }) => {
            console.log("data", data);
            if (data.status === 200) {
              let imgUrl = data.data.filename;
          console.log(imgUrl);
    //就会返回一个地址:"https://........cn/yidekuai/news/file5d7e09f3c4919d7e504d73b9.png"”
              this.preImageList.push({ presImageUrl: imgUrl, temporary: true });
    //如果上页面preImageList传过来的为空,而且添加的第一张,则需要调用changePreImageUrl()
              if (this.preImageList.length === 1) {
                this.changePreImageUrl(0);
              }
            }
          })
          .catch(error => {
            console.log(error);
          });
      }
    
      preIndex = 0;
    
      rotateSave() {
        if (!this.allTemporary) {
          return;
        }
        this.$confirm("保存所有暂存图片将立刻更改处方图片,是否继续?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
          closeOnClickModal: false
        })
          .then(() => {
            let imguploadlist = this.preImageList.map(item => {
              return item.presImageUrl;
            });
            let updateForm = { presId: this.presId, pictureIds: imguploadlist };
            indexApi.updatePre(updateForm).then(res => {
              if (res["retCode"]) {
                this.$emit("getInfo");
                this.$message({
                  type: "success",
                  message: "保存成功!"
                });
              } else {
                if (!res["islogin"]) {
                  this.$alert(res["message"]);
                }
                console.error("数据查询错误");
              }
            });
          })
          .catch(() => {
            this.$message({
              type: "info",
              message: "已取消上传"
            });
          });
      }
      mounted() {
        this.$parent
        let that = this;
        //阻止浏览器默认滚动行为
        document
          .querySelector(".vue-cropper")
          .addEventListener("wheel", function(e) {
            if (that.option.img) {
              e.preventDefault();
            }
          });
      }
    }
    </script>
    
    console.log( (<any>this.$refs.logo).files)
    console.log( (<any>this.$refs.logo).files[0])//返回以下
    
    125700f541a9d76c1c889c669e85fc4.png

    上传图片例子;

    注意所有需要上传图片的接口,都需要先请求上传图片接口
    图片接口上传完会返回一个图片地址给我们,再把图片地址放到添加数据的接口对应参数上即可

    <template>
        <div class="IndexSwiper">
            <h1>轮播图</h1>
            <el-row class="addBtn clear_fix">
                <!--添加按钮-->
                <el-button class="addImg" type="primary" @click="dialogFormVisible = true">新增轮播图</el-button>
                <!--下拉框-->
                <el-select class="selectType" @change="inpBtn" v-model="value">
                    <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
                    </el-option>
                </el-select>
            </el-row>
            <!--首页头部-->
            <el-table :data="tableData">
                <el-table-column label="图片">
                    <!--通过 Scoped slot 可以获取到 row, column, $index 和 store(table 内部的状态管理)的数据-->
                    <template slot-scope="scope">
                        <span style="margin-left: 10px">
                    <div class="indImg"><img :src="scope.row.img_url"/></div>
                </span>
                    </template>
                </el-table-column>
                <el-table-column label="排序">
                    <template slot-scope="scope">
                        <p>{{scope.row.orders}}</p>
                    </template>
                </el-table-column>
                <el-table-column label="链接">
                    <template slot-scope="scope">
                        <p>{{scope.row.href}}</p>
                    </template>
                </el-table-column>
                <el-table-column label="操作">
                    <template class="el-table__row" slot-scope="scope">
                        <el-button size="medium" @click="handleUp(scope.$index, scope.row)">上升</el-button>
                        <el-button size="medium" @click="handleDown(scope.$index, scope.row)">下降</el-button>
                        <el-button size="medium" type="danger" @click="handleDelete(scope.$index, scope.row)">删除</el-button>
                    </template>
                </el-table-column>
            </el-table>
    
            <!--弹窗-->
            <el-dialog title="添加轮播图" :visible.sync="dialogFormVisible">
                <!--图片上传-->
                <div class="uploadBox">
                    <div class="upload">上传文件</div>
                    <el-upload class="upload-demo" ref="upload" action="" :file-list="fileList" :auto-upload="false" :on-change='changeUpload'>
                        <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
                        <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
                        <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,每次只能上传一张,最大不超过5mb</div>
                        <div slot="tip" v-if="remin" class="remin">请选择背景图</div>
                    </el-upload>
                </div>
                <!--单选框-->
                <div class="radioBox">
                    <div class="upload">轮播图位置</div>
                    <template>
                        <el-radio v-model="radio" label="1">首页头部</el-radio>
                        <el-radio v-model="radio" label="2">首页底部</el-radio>
                    </template>
                </div>
                <!--链接地址-->
                <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="urlBox">
                    <el-form-item label="链接地址" prop="name">
                        <el-input v-model="ruleForm.name"></el-input>
                    </el-form-item>
                    <el-form-item>
                        <el-row>
                            <el-button type="primary" @click="subBtn('ruleForm')">立即提交</el-button>
                        </el-row>
                    </el-form-item>
                </el-form>
            </el-dialog>
        </div>
    </template>
    <script>
        export default {
            data() {
                return {
                    //表格数据
                    tableData: [],
                    //下拉框数据
                    options: [{
                        value: '1',
                        label: '首页头部'
                    }, {
                        value: '2',
                        label: '首页底部'
                    }],
                    //链接地址及规则
                    ruleForm: {
                        name: '',
                    },
                    rules: {
                        name: [{
                            required: true,
                            message: '请链接地址',
                            trigger: 'blur'
                        }]
                    },
                    value: '1',
                    changeNum: 0,
                    dialogTableVisible: false,
                    dialogFormVisible: false,
                    radio: '1',//单选框        
                    updateImg: this.$config.uploadImg,//传图片接口
                    formData: new FormData(),//实例化上传方法
                    fileList: [],
                    imgUrl: "",//上传图片路径
                    remin: false////没上传图片提示
                }
            },
            methods: {
                //成功提醒
                message() {
                    this.$notify({
                        title: '成功',
                        message: '这是一条成功的提示消息',
                        type: 'success',
                        duration: 2000
                    });
                },
                //失败提醒
                error() {
                    this.$notify.error({
                        title: '失败',
                        message: '这是一条失败的提示消息',
                        duration: 2000
                    });
                },
                //提交成功
                succmsg() {
                    this.$message({
                        message: '提交成功',
                        type: 'success'
                    });
                },
                //下拉框选中
                changeBlock(num) {
                    this.changeNum = num
                },
                //上传按钮  注意需要先请求上传图片接口,再请求上传轮播图接口
                          //先请求上传图片接口 传完会返回一个图片地址给我们
                submitUpload() {
                    this.$require.post(this.$config.uploadImg, this.formData);//uploadImg上传图片接口
                        .then((res) => {
                            this.$refs.upload.clearFiles(); 
                            this.message(); //成功提醒
                            console.log(res)
                            if(res.data.data.img_url != undefined) {
                            //请求上传图片接口
                            //成功后图片接口上传完会返回一个图片地址给我们,再把图片地址放到添加数据的接口对应参数上即可
                                this.imgUrl = res.data.data.img_url //赋值
                            } else {
                                this.imgUrl = res.data.data.img_url_array[res.data.data.img_url_array.length - 1]
                            }
                            console.log(this.imgUrl)
                        })
                        .catch((err) => {
                            this.error(); //失败提醒
                        })
                },
    //on-change文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用
                changeUpload(file, fileList) {
                    console.log(fileList)
                    console.log(file.raw);
                    this.formData.append("files", file.raw);//上传文件都需这步
                },
                //提交按钮,后在再把图片地址放到添加数据的接口对应参数上即可,就是请求后台数据,请求上传轮播图接口 
                subBtn(formName) {
                    this.$refs[formName].validate((valid) => {
                        if(valid && this.imgUrl != "") {
                            console.log(this.imgUrl)
                            this.remin = false;
                            this.succmsg(); //提交成功提示
                            this.$require.post(this.$config.addCarousel, {//addCarousel添加轮播图接口
                                    href: this.ruleForm.name,
                                    img_url: this.imgUrl,
                                    order: 0,
                                    position_id: this.radio
                                })
                                .then((res) => {
                                    this.imgUrl = "";
                                    this.$refs[formName].resetFields();
                                    this.dialogFormVisible = false;
                                    //请求后台数据,再次请求前端数据
                                    this.getList()
                                })
                        } else {
                            this.remin = true
                            this.error();
                            return false;
                        }
                    });
                },
                //请求数据
                getList() {
                    console.log(this.$config1)
                    console.log(this)
                    console.log(this.value)
                    this.$require.get(this.$config1.carousel, {
                            params: {
                                position_id: this.value
                            }
                        })
                        .then((res) => {
                            console.log(res)
                            this.tableData = res.data.data.rows
                            console.log(this.tableData)
                        })
                        .catch((err) => {
                            console.log("请求失败")
                        })
                },
                //操作接口开始
                //删除按钮
                handleDelete(idx, row) {
                    this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
                            confirmButtonText: '确定',
                            cancelButtonText: '取消',
                            type: 'warning',
    
                        }).then((res) => {
                            // this.delid = id
                            this.$message({
                                type: 'success',
                                message: '删除成功!',
                            });
                            this.$require.post(this.$config.delCarousel, {
                                    id: row.id
                                })
                                .then((res) => {
                                    this.getList()
                                    console.log(res)
                                })
                        })
                        .catch(() => {
                            this.$message({
                                type: 'info',
                                message: '已取消删除'
                            })
                            this.getList()
                        });
                },
                //下拉框更换数据
                inpBtn(){
                    this.getList()
                },
                //上升
                handleUp(index, row) {
                    this.$require.post(this.$config.sortCarousel, {
                            move: 1,
                            orders: row.orders
                        })
                        .then((res) => {
                            this.getList()
                        })
                },
                //下降
                handleDown(index, row) {
                    this.$require.post(this.$config.sortCarousel, {
                            move: -1,
                            orders: row.orders
                        })
                        .then((res) => {
                            this.getList()
                        })
                }
            },
            created(){
                this.getList();//请求轮播图
            },
        }
    </script>
    

    上传图片显示进度条demo

    <!DOCTYPE html>
    <html>
    
        <head>
            <meta charset="UTF-8">
            <title></title>
            <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
            <style>
                .avatar-uploader .el-upload {
                    border: 1px dashed #d9d9d9;
                    border-radius: 6px;
                    cursor: pointer;
                    position: relative;
                    overflow: hidden;
                }
                
                .avatar-uploader .el-upload:hover {
                    border-color: #409EFF;
                }
                
                .avatar-uploader-icon {
                    font-size: 28px;
                    color: #8c939d;
                    width: 178px;
                    height: 178px;
                    line-height: 178px;
                    text-align: center;
                }
                
                .avatar {
                    width: 178px;
                    height: 178px;
                    display: block;
                }
            </style>
        </head>
    
        <body>
            <script src="https://cdn.jsdelivr.net/npm/vue"></script>
            <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    
            <div id="app">
                <div>
                    <el-upload class="avatar-uploader" action="https://jsonplaceholder.typicode.com/posts/" :show-file-list="false" :on-success="handleAvatarSuccess" :on-progress='uploaded' :before-upload="beforeAvatarUpload">
                        <!--//当有进度条就不显示+-->
                        <div v-if="percentage" avatar-uploader-icon>
                            <div class="box" v-if="percentage<100">
                                <!--进度条-->
                                <el-progress type="circle" :percentage="Math.round(percentage)"></el-progress>
                            </div>
                            <!--进度条100时显示照片-->
                            <img v-if="percentage == 100" :src="imageUrl" alt="" class="avatar">
                        </div>
                        <i v-else class="el-icon-plus avatar-uploader-icon"></i>
                    </el-upload>
                </div>
    
            </div>
            <script>
                var vm = new Vue({
                    el: "#app",
                    data() {
                        return {
                            imageUrl: '', //
                            percentage: ""
                        }
                    },
                    methods: {
                        //                  :on-progress
                        //                  文件上传时的钩子
                        uploaded(file) {
                            console.log(file.percent);//进度条的变化 1-100
                            this.percentage = file.percent;
                        },
                        //                  :on-success
                        //文件上传成功时的钩子
                        handleAvatarSuccess(res, file) {
                            this.imageUrl = URL.createObjectURL(file.raw);
                        },
                        //                  :before-upload
                        //                  上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。
                        beforeAvatarUpload(file) {
                            const isJPG = file.type === 'image/jpeg';
                            const isLt2M = file.size / 1024 / 1024 < 2;
    
                            if(!isJPG) {
                                this.$message.error('上传头像图片只能是 JPG 格式!');
                            }
                            if(!isLt2M) {
                                this.$message.error('上传头像图片大小不能超过 2MB!');
                            }
                            return isJPG && isLt2M;
                        }
                    }
                });
            </script>
        </body>
    
    </html>
    

    demo2vuecropper插件的使用+进度条

    <template>
      <div>
        <div class="wrapper"
             style="position: relative;">
          <VueCropper style="height: 60vh;min-width:100%;"
                      ref="cropper"
                      :img="option.img"
                      :outputSize="option.size"
                      :outputType="option.outputType"
                      :info="true"
                      :full="option.full"
                      :canMove="option.canMove"
                      :canMoveBox="option.canMoveBox"
                      :fixedBox="option.fixedBox"
                      :original="option.original"
                      :canScale="option.canScale">
          </VueCropper>
          <div style="position: absolute; bottom: 70px; right: 20px;">
            <span v-if="preImageList.length > 0">
              <span style="font-size: 28px;">{{preIndex+1}}</span>/<span style="">{{preImageList.length}}</span>
            </span>
            <span v-else
                  style="font-weight: 600;color: #666;">暂无图片</span>
          </div>
          <div style="width:100%;background-color:#f7f7f7;display:flex;justify-content: space-around;align-items: center;">
            <div class="iconcropper"
                 @click="changeScale(1)">
              <i class="iconfont icon-fangda"
                 style="font-size:24px;"></i>
            </div>
            <div class="iconcropper"
                 @click="changeScale(-1)">
              <i class="iconfont icon-suoxiao-"
                 style="font-size:28px;"></i>
            </div>
    
            <div class="iconcropper"
                 @click="rotateLeft">
              <i class="iconfont icon-llfilterrotate"
                 style="font-size:31px;"></i>
            </div>
            <div class="iconcropper"
                 @click="rotateRight">
              <i class="iconfont icon-youxuanzhuan"
                 style="font-size:28px;"></i>
            </div>
            <!-- v-promiss.edit -->
            <div class="iconcropper"
                 @click="rotateDetele()"
                 :style="haveDetele && !notHaveAdd?'display:initial':'display:none'">
              <i class="iconfont icon-iconfontshanchu3"
                 style="font-size:24px;"
                 :style="(temporary &&  !preImageList[preIndex].temporary) || preImageList.length==0 ?'opacity: 0.2;':''"></i>
            </div>
    
            <div class="iconcropper"
                 @click="rotateSave()"
                 v-if="haveSave && !notHaveAdd"
                 v-promiss.edit>
              <!-- <el-tooltip class="item" effect="dark" content="保存所有暂存图片" placement="top-start" > -->
              <i class="iconfont icon-49"
                 style="font-size:28px;"
                 :style="allTemporary ?'':'opacity: 0.2;'"></i>111
              <!-- </el-tooltip> -->
            </div>
            <div class="iconcropper"
                 @click="lookImg">
                 <i class="el-icon-picture-outline" style="font-size:24px;"></i>
            </div>
          </div>
        </div>
    
        <div style="width:100%;display: flex;margin:10px 0;align-items: center;overflow: auto; ">
          <div v-for="(item,index) in preImageList"
               :key="index"
               style="display: flex;margin-right:20px;    position: relative;    border-radius: 3px;"
               @click="changePreImageUrl(index)"
               :class="preIndex == index ?'selectImage':'noselect'">
                <div>
                  <!-- 进度条 -->
               <el-progress type="circle" :percentage="fileredstatus" v-if="fileredstatus < 100  && fileredstatus != 0 && index == preImageList.length -1"></el-progress>
                  <img :src="item.presMinImageUrl ? item.presMinImageUrl : item.presImageUrl"
                    style="width:126px;height:126px;" v-else/>
                </div>
            <!-- <el-tooltip class="item"
                        effect="dark"
                        content="暂未保存"
                        placement="top-start"
                        v-if="item.temporary">
              <i class="iconfont icon--"
                 style="font-size: 24px;color: #f4c542; position: absolute;right: 0;line-height: initial; top: -1px;border-radius: 3px;"></i>
            </el-tooltip> -->
          </div>
    
          <div @click="doClick()"
               class="el-upload el-upload--picture-card"
               style="height: 126px;width: 126px;"
               v-if="!notHaveAdd">
            <div style="margin-right: 20px;height: 126px;width: 126px;display: flex;justify-content: center;align-items: center;">
              <i class="el-icon-plus"
                 style="font-size:21px;"></i>
            </div>
          </div>
          <input type="file"
                 ref="logo"
                 id="logo"
                 style="display:none;"
                 @change="isSizeClear();" />
    
        </div>
    
        <!-- <div v-if="presId">
          <div style="width:100%;display: flex;margin:10px 0;      overflow: auto; ">
            <el-upload accept=".jpg,.jpeg,.png,.gif,.bmp,.pdf,.JPG,.JPEG,.PBG,.GIF,.BMP,.PDF"
                       :action="fileUploadUrl"
                       list-type="picture-card"
                       ref="upload"
                       :before-upload="beforeUpload"
                       :on-remove="handleRemove"
                       :on-success="handleSuccess"
                       :file-list="fileList">
              <i class="el-icon-plus"></i>
            </el-upload>
          </div>
          <div>
            <el-button type="primary"
                       @click="pictureUploadPre()">上传图片</el-button>
          </div>
        </div> -->
    
        <el-dialog :close-on-click-modal="false"
                   :append-to-body="true"
                   title="警告"
                   :visible.sync="centerDialogVisible"
                   width="30%"
                   center>
          <div style="text-align: center;height: 300px;overflow: hidden;width: 300px;margin: auto;"
               class="flex flex-align-center flex-pack-center">
            <img :src="option.img"
                 style="width:100%" />
          </div>
          <div style="text-align: center;margin-bottom: -20px; margin-top: 15px;color: #666;font-size: 15px;">是否删除当前选中的图片?</div>
          <span slot="footer"
                class="dialog-footer">
            <el-button size="small"
                       @click="centerDialogVisible = false">取 消</el-button>
            <el-button type="warning"
                       size="small"
                       @click="doDetele()">确 定</el-button>
          </span>
        </el-dialog>
    
      </div>
    </template>
    
    <script lang="ts">
    import Vue from "vue";
    import Component from "vue-class-component";
    import axios from "axios";
    import { Prop } from "vue-property-decorator";
    import * as indexApi from "../../api/indexApi";
    import * as Api from "../../api/api";
    
    import filterdrug from "../drug/filterdrug.vue";
    import * as Config from "../../api/conf";
    import { VueCropper }  from "vue-cropper";
    
    // import prescriptioninfo from "../transmit/prescriptioninfo";
    @Component({
      props: {},
      components: {
        filterdrug,
        VueCropper
        // prescriptioninfo
      }
    })
    export default class Corpperlabel extends Vue {
      @Prop({ required: false, type: Array })
      preImageList: any;
    
      @Prop({ required: false })
      presId: any;
    
      @Prop({ required: false })
      haveDetele: boolean;
    
      @Prop({ required: false })
      haveSave: boolean;
    
      //true 不可以删除已有图片
      //false 全部图片可以删除
      @Prop({ required: false })
      temporary: boolean;
      @Prop({ required: false })
      notHaveAdd: boolean;
    
      get allTemporary() {
        let a = this.preImageList.filter(item => {
          return item.temporary;
        });
        return a.length > 0;
      }
      //传入网络图片地址和回调 将网络图片转换成base64格式 getBase64现已废弃,因图片无跨域问题无需这样处理
      getBase64(img, callback) {
        function getBase64Image(img, width, height) {
          //width、height调用时传入具体像素值,控制大小 ,不传则默认图像大小
          var canvas = document.createElement("canvas");
          canvas.width = width ? width : img.width;
          canvas.height = height ? height : img.height;
          var ctx = canvas.getContext("2d");
          ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
          var dataURL = canvas.toDataURL();
          callback(dataURL);
          return dataURL;
        }
        var image = new Image();
        image.setAttribute("crossOrigin", "anonymous");
        image.src = img + "?time=" + new Date().valueOf();
        if (img) {
          image.onload = function() {
            return getBase64Image(image, null, null);
          };
        }
      }
    
      centerDialogVisible = false;
      changePreImageUrl(index) {
        //使用定时器因为this.preImageList 不能立即拿到
        setTimeout(() => {
          // 如果存在小图则使用小图,如果不存在则使用原图
          let str = this.preImageList[index].presMinImageUrl
            ? "presMinImageUrl"
            : "presImageUrl";
          this.option.img = this.preImageList[index][str];
        }, 50);
        //这个放在定时器外面是因为放在里面会出问题需要点击两次才能设置上index 原因不明,只能放在定时器外面
        this.preIndex = index;
      }
      crap = false;
      previews = {};
      option = {
        img: "",
        size: 1,
        full: false,
        outputType: "jpg",
        canMove: true,
        fixedBox: false,
        original: true,
        canMoveBox: false,
        canScale: true
      };
      //进度条初始值
      fileredstatus = 0;
      downImg = "#";
      changeScale(value) {
        let a: any = this.$refs.cropper;
        a.changeScale(value);
      }
    
      rotateRight() {
        let a: any = this.$refs.cropper;
        a.rotateRight();
      }
      rotateLeft() {
        let a: any = this.$refs.cropper;
        a.rotateLeft();
      }
      rotateDetele() {
        if (
          (this.temporary && !this.preImageList[this.preIndex].temporary) ||
          this.preImageList.length == 0
        ) {
          return;
        }
        this.centerDialogVisible = true;
      }
      //查看原图
      lookImg(index){
          delete this.preImageList[this.preIndex].presMinImageUrl
          this.option.img = this.preImageList[this.preIndex].presImageUrl
      }
      doDetele() {
        this.preImageList.splice(this.preIndex, 1);
        if (this.preImageList.length > 0) {
          if (this.preIndex !== 0) {
            this.preIndex -= 1;
          }
        } else {
          this.option.img = null;
        }
        this.changePreImageUrl(this.preIndex);
        this.centerDialogVisible = false;
      }
      doClick() {
        if ((<any>this.$refs.logo).files.length == 0) {
        } else {
          (<any>this.$refs.logo).value = "";
        }
        (<any>this.$refs.logo).click();
      }
    
    
      //封装好上传图片的勾子,有进度条
      // export const uploadFile = (form,callback) => {
      //     //https://mapp.aisimob.com/tfj/multiupload
      //     return axios.post(upload, form, {
      //         method: 'post',
      //         headers: { 'Content-Type': 'multipart/form-data' },
      //         onUploadProgress : function(progressEvent){
      //             if(progressEvent.lengthComputable){
      //                 callback(progressEvent)
      //             }
      //         }
      //     })
      //         .then(response => response)
      //         .catch(error => error);
      // };
      //上传图片的方法
      isSizeClear() {
        let form = new FormData();//新建FormData对象
        let logo = (<any>this.$refs.logo).files[0];
        if (!logo) {
          return;
        }
        //preImageList图片数组
        this.preImageList.push({ presImageUrl: null, temporary: true })
        form.append("file", logo);
        let that = this
        //上传图片到服务器
        Api.uploadFile(form,(res) =>{//这个回调是用来显示进度条用的
          console.log(res)
          let complete = Math.ceil(res.loaded / res.total * 100)
          that.fileredstatus = complete
        })
          .then(({ data }) => {
            if (data.status === 200) {
              console.log(data)
              let imgUrl = data.data.filename;//图片的地址
              // this.$set()用来修改或添加数组 使用this.$set(obj, key, value)obj为对象数组本身,key为下标或这
              // 属性名 value为添加后数组元素的值或者键值,this.$set()修改视图层才会响应该数据的变化
    
              this.$set(this.preImageList,this.preImageList.length-1,{ presImageUrl: imgUrl, temporary: true })
              if (this.preImageList.length === 1) {
                //如果上页面preImageList传过来的为空,而且添加的第一张,则需要调用,因为上传
                // 第一张需要不点击就显示大图那里
                this.changePreImageUrl(0);
              }
            }
          })
          .catch(error => {
            console.log(error);
          });
      }
    
      preIndex = 0;
    
      rotateSave() {
        if (!this.allTemporary) {
          return;
        }
        this.$confirm("保存所有暂存图片将立刻更改处方图片,是否继续?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
          closeOnClickModal: false
        })
          .then(() => {
            let imguploadlist = this.preImageList.map(item => {
              return item.presImageUrl;
            });
            let updateForm = { presId: this.presId, pictureIds: imguploadlist };
            indexApi.updatePre(updateForm).then(res => {
              if (res["retCode"]) {
                this.$emit("getInfo");
                this.$message({
                  type: "success",
                  message: "保存成功!"
                });
              } else {
                if (!res["islogin"]) {
                  this.$alert(res["message"]);
                }
                console.error("数据查询错误");
              }
            });
          })
          .catch(() => {
            this.$message({
              type: "info",
              message: "已取消上传"
            });
          });
      }
      mounted() {
        let that = this;
        //阻止浏览器默认滚动行为 此处会触发谷歌报错,被动事件侦听器无法阻止默认事件,实际不影响效果
        let cropperDom = document.querySelector(".vue-cropper");
        cropperDom.addEventListener("wheel", function(e) {
          if (that.option.img) {
            e.preventDefault();
          }
        });
      }
    }
    </script>
    
    <style  scoped>
    .noselect {
      border: 1px #e5e5e5 solid;
    }
    
    .selectImage {
      cursor: pointer;
      border: 1px #409eff solid;
    }
    .noselect:hover {
      cursor: pointer;
      border: 1px #409eff solid;
    }
    .iconcropper {
      padding: 10px;
      cursor: pointer;
    }
    .iconcropper:active {
      opacity: 0.5;
    }
    </style>
    
    <style lang="scss" scoped>
    @import "../../common/sass/mixinmap.scss";
    
    $wrapper: (
      null: 100%,
      300px: 100%,
      768px: 100%,
      1024px: 100%,
      1280px: 100%,
      1680px: 500px
    );
    .wrapper {
      @include handleMinWidth($wrapper);
    }
    // .el-progress{
    //   height:100px;
    //   width: 100px;
    // }
    // .el-progress .el-progress-circle{
    //   height:100px;
    //   width: 100px;
    // }
    </style>
    

    相关文章

      网友评论

          本文标题:vuecropper插件的使用

          本文链接:https://www.haomeiwen.com/subject/suvzyctx.html