zoukankan      html  css  js  c++  java
  • vue-cropperjs 插件的组件化使用 前端裁剪插件 vue

    vue-cropperjs 插件的组件化使用

    安装

    npm install --save vue-cropperjs   或者 cnpm install --save vue-cropperjs
    

    局部引入

    import VueCropper from 'vue-cropperjs'
    export default {
      components: { VueCropper },
    

    组件内容

      <div>
        <div class="crop-demo">
          <div class="crop-demo-btn" v-show="false">
            点击更换图片
            <input class="crop-input" type="file" name="image" accept="image/*" @change="setImage" id="change" />
          </div>
        </div>
        <el-dialog :append-to-body="true" title="图片剪裁" :visible.sync="dialogVisible" :close-on-click-modal="false" width="40%">
          <vue-cropper :aspect-ratio="cropperAspectWH" ref="cropper" :src="imgSrc" :ready="cropImage" :zoom="cropImage" :cropmove="cropImage" style=" 100%; height: 300px"></vue-cropper>
          <span slot="footer" class="dialog-footer">
            <el-button @click="cancelCrop">取 消</el-button>
            <el-button type="primary" @click="upladPic">确 定</el-button>
          </span>
        </el-dialog>
        <div v-show="false">{{ thisAspectWH }}</div>
      </div>
    </template>
    
    <script>
    import VueCropper from 'vue-cropperjs'
    export default {
      components: { VueCropper },
      props: ['label', 'AspectWH'],//label 是父组件传的标识符 (用于一个页面内多处使用裁剪组件,裁剪结果返回值错乱)   AspectWH 是用于限定裁剪框的比例的1为1:1  可传null则是不限制(注意传值是否为字符串)
      data() {
        return {
          //以下都是截图插件的
          imgSrc: '',
          dialogVisible: false,
          img_size: '',
          max_fuyuan_defaultSrc: [],
          cropperAspectWH: 1, //图片剪裁宽高比例
          reader: '',
          e_photo_file: '',
          e_photo_filefile: '',
          http_cropImg: '', //带http
          cropImg: '', //默认图片不带http
        }
      },
      methods: {
        //监听父组件是否点击上传的事件
        childAction() {
          $('#change').click()
        },
        //向父组件发送数据  cropImg 裁剪得到的图片名称  http_cropImg 带域名的图片名称  label就是传进来的标识符,也带着传出去
        sendMsg() {
          this.$emit('getPicNamefile', this.cropImg, this.http_cropImg, this.label)
        },
        /******************************图片剪切开始****************************************/
        setImage(e) {
          let that = this
          this.e_photo_file = e
          let file = e.target.files[0]
          this.e_photo_filefile = file
          if (!file.type.includes('image/')) {
            return
          }
          this.reader = ''
          let canvas = '',
            ctx = '',
            img = ''
    
          this.imgSrc = ''
          this.reader = new FileReader()
          this.reader.onload = (event) => {
            if (file.size >= 1024 * 1024 * this.GLOBAL.fileSize) {
              //调用自定义方法来处理图片
              var quality = 1 //压缩图片的质量
              canvas = document.createElement('canvas') //创建画布
              ctx = canvas.getContext('2d')
              img = new Image()
              img.src = event.target.result
              img.onload = function () {
                const width = img.width
                const height = img.height
                canvas.width = 1200 //这里可以自定义你的图片大小
                canvas.height = 1200 * (img.height / img.width)
                that.dialogVisible = true
                setTimeout(() => {
                  ctx.fillRect(0, 0, 0, 0)
                  ctx.drawImage(img, 0, 0, 1200, canvas.height)
                  that.imgSrc = canvas.toDataURL('image/jpeg', quality) //将图片转为Base64 之后预览要用
                  that.$refs.cropper.replace(that.imgSrc)
                }, 50)
              }
            } else {
              that.dialogVisible = true
              that.$nextTick(function () {
                that.imgSrc = event.target.result
                that.$refs.cropper.replace(event.target.result)
              })
            }
          }
          that.reader.readAsDataURL(file)
        },
        setImage_two(e) {
          let that = this
          let file = this.e_photo_filefile
          let canvas = '', ctx = '',img = '';
          this.e_photo_file = e
          this.e_photo_filefile = file
          this.reader = ''
          this.imgSrc = ''
          this.reader = new FileReader()
          this.reader.onload = (event) => {
            //调用自定义方法来处理图片
            var quality = 1 //压缩图片的质量
            canvas = document.createElement('canvas') //创建画布
    
            ctx = canvas.getContext('2d')
    
            img = new Image()
            img.src = event.target.result
            img.onload = function () {
              // 清除画布
              const width = img.width
              const height = img.height
              canvas.width = 1200 //这里可以自定义你的图片大小
              canvas.height = 1200 * (img.height / img.width)
              setTimeout(() => {
                ctx.fillRect(0, 0, 0, 0)
                ctx.drawImage(img, 0, 0, 1200, canvas.height)
    
                that.imgSrc = canvas.toDataURL('image/jpeg', quality) //将图片转为Base64 之后预览要用
                that.$refs.cropper && that.$refs.cropper.replace(that.imgSrc)
              }, 50)
            }
          }
          that.reader.readAsDataURL(file)
        },
        cropImage() {
          this.http_cropImg = this.$refs.cropper.getCroppedCanvas().toDataURL()
        },
        cancelCrop() {
          this.dialogVisible = false
          this.http_cropImg = this.max_fuyuan_defaultSrc[this.max_fuyuan_defaultSrc.length - 1]
          $('#change').val('') //取消change事件
        },
        upladPic() {
          this.sumitImageFile(this.http_cropImg)
        },
        sumitImageFile(base64Codes) {
          let that = this
          var formData = new FormData()
          var picName = new Date().getTime() + '.png' //给截图的文件命名
          formData.append('file', that.convertBase64UrlToBlob(base64Codes), picName) //append函数的第一个参数是后台获取数据的参数名,和html标签的input的name属性功能相同
    
          if (this.img_size >= 1024 * 1024 * this.GLOBAL.fileSize) {
            this.$message({
              message: '要上传图片太大,请再次截取,本次截取将进行压缩处理!',
              type: 'warning',
            })
            this.setImage_two(that.e_photo_file)
            return
          }
          if (this.img_size / 1024 / 1024 < this.GLOBAL.fileSize) {
            serviceApi.requestPostUploadFile(formData).then((body) => {
              that.cropImg = body.file_name
              //传递给父组件
    
              that.sendMsg()
            })
          } else {
            this.$message({
              message: '抱歉,要上传图片太大,请重新上传!',
              type: 'warning',
            })
            that.cropImg = ''
            that.http_cropImg = ''
            //传给表单
            //传递给父组件
            that.cropper_show = false
            that.sendMsg()
          }
          //关闭弹框
          $('#change').val('') //取消change事件
          this.dialogVisible = false
        },
        //将以base64的图片url数据转换为Blob
        convertBase64UrlToBlob(urlData) {
          var bytes = window.atob(urlData.split(',')[1]) //去掉url的头,并转换为byte
          //处理异常,将ascii码小于0的转换为大于0
          var ab = new ArrayBuffer(bytes.length)
          var ia = new Uint8Array(ab)
          for (let i = 0; i < bytes.length; i++) {
            ia[i] = bytes.charCodeAt(i)
          }
          let size = new Blob([ab], { type: 'image/png' })
          this.img_size = size.size
          return new Blob([ab], { type: 'image/png' })
        },
        /******************************图片剪切结束****************************************/
      },
      computed: {
        thisAspectWH() {
          if (this.AspectWH) {
            this.cropperAspectWH = this.AspectWH
          }
        },
      },
      mounted() {
        //监听父组件是否点击上传的事件
        this.$on('inputfile', (val) => {
          if (this.AspectWH) {
            this.cropperAspectWH = this.AspectWH
          }
          this.childAction(val)
        })
      },
      watch: {},
      created() {
        if (this.AspectWH) {
          this.cropperAspectWH = this.AspectWH
        }
      },
    }
    </script>
    
    
    <style scoped>
    /* 图片剪裁样式 */
    .crop-demo {
      display: flex;
      align-items: flex-end;
       150px;
      height: 150px;
    }
    .crop-demo-btn {
      position: absolute;
      left: auto;
      top: 50%;
      transform: translateY(-50%);
       100px;
      height: 40px;
      line-height: 40px;
      padding: 0;
      text-align: center;
      font-size: 12px;
      margin-left: 25px;
      color: #fff;
      background-color: rgba(0, 0, 0, 0.2);
      border-radius: 4px;
      box-sizing: border-box;
      cursor: pointer;
    }
    .crop-input {
      position: absolute;
       100px;
      height: 40px;
      left: 0;
      top: 0;
      opacity: 0;
      font-size: 0;
      padding: 0;
      cursor: pointer;
    }
    </style>
    
    

    注意点

    这个方法要自己写 serviceApi.requestPostUploadFile

    父组件中使用

     <div class="crop-demo">
                    <div
                      style="
                        position: relative;
                        display: flex;
                         340px;
                        height: 170px;
                      "
                    >
                      <span>
                        <img
                          :src="XXXXXXX"
                          style="
                             340px;
                            height: 170px;
                            background: #f8f8f8;
                            border: 1px solid #eee;
                            border-radius: 5px;
                            object-fit: cover;
                          "
                        />
                      </span>
                      <div
                        style="
                          position: absolute;
                          left: 50%;
                          top: 50%;
                          transform: translate(-50%, -50%);
                           100px;
                          line-height: 40px;
                          padding: 0;
                          text-align: center;
                          font-size: 12px;
                          background-color: #9da1a585;
                          color: #fff;
                          border-radius: 4px;
                          box-sizing: border-box;
                        "
                      >
                        点击更换图片
                        <div
                          @click="toSonClick('label')"
                          style="
                            position: absolute;
                             100px;
                            height: 40px;
                            left: 0;
                            top: 0;
                            opacity: 0;
                            cursor: pointer;
                          "
                        />
                      </div>
                    </div>
                  </div>
        <CropperCut
          v-if="CropperCutShow"
          :AspectWH="AspectWH"
          :label="CropperCutlabel"
          @getPicNamefile="getPicNamefile"
          ref="CropperCut"
        ></CropperCut>
    
        data中加入:
          //裁剪插件的label   是谁调用的
          AspectWH: "1", //裁剪插件的宽高比
          CropperCutlabel: "",
          CropperCutShow: false, //控制开关 裁剪插件
    
    
      //裁剪插件的事件
        toSonClick(label) {
          let that = this;
          if (label == "label") {
            this.AspectWH = 1;
          } else if (label == "XXX") {
            this.AspectWH = 2;
          }
          this.CropperCutShow = true;
          this.CropperCutlabel = label;
          setTimeout(() => {
            that.$refs.CropperCut.$emit("inputfile");
          }, 10);
        },
        //插件插件
        getPicNamefile(cropImg, http_cropImg, label) {
          this.CropperCutShow = false;
          this.AspectWH = 1;
          if (label == "label") {
            this.CropperCutlabel = "";
          } else if (label == "XXX") {
            this.CropperCutlabel = "";
          }
        },
    

    **插件官网:https://www.npmjs.com/package/vue-cropperjs

  • 相关阅读:
    【leetcode】Binary Search Tree Iterator
    【leetcode】Palindrome Partitioning II
    【leetcode】Best Time to Buy and Sell Stock III
    【leetcode】Best Time to Buy and Sell Stock II
    【leetcode】Longest Consecutive Sequence
    【leetcode】Factorial Trailing Zeroes
    【leetcode】Simplify Path
    【leetcode】Generate Parentheses
    【leetcode】Combination Sum II
    【leetcode】Combination Sum
  • 原文地址:https://www.cnblogs.com/panghu123/p/14973810.html
Copyright © 2011-2022 走看看