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="width: 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;
  width: 150px;
  height: 150px;
}
.crop-demo-btn {
  position: absolute;
  left: auto;
  top: 50%;
  transform: translateY(-50%);
  width: 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;
  width: 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;
                    width: 340px;
                    height: 170px;
                  "
                >
                  <span>
                    <img
                      :src="XXXXXXX"
                      style="
                        width: 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%);
                      width: 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;
                        width: 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

posted @ 2021-07-05 18:40  王二疯  阅读(967)  评论(0编辑  收藏  举报