MrShi
2025-03-12 69a1b3bf45738f048361ee4ccb6bdc64fce35720
admin/src/components/common/ImageCropper.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,232 @@
<template>
  <div class="iconShot">
    <div class="icon-dialog">
      <div class="clip">
        <div class="img" ref="img">
          <vue-cropper
              ref="cropper"
              :img="imgSrc"
              :width="options.width"
              :height="options.height"
              :canScale="options.canScale"
              :autoCrop="options.autoCrop"
              :canMove="options.canMove"
              :output-size="options.outputSize"
              :centerBox="options.centerBox"
              :autoCropWidth="options.autoCropWidth"
              :autoCropHeight="options.autoCropHeight"
              @realTime="realTime"
          ></vue-cropper>
        </div>
        <div class="previews">
          <img style="width: 150px;height: 150px;border-radius1: 50%;object-fit: cover" :src="cutImgSrc" alt="图片">
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import { VueCropper } from 'vue-cropper'
import {upload} from "@/api/system/common";
export default {
  name: 'ImageCropper',
  components: { VueCropper },
  props: {
    imgSrc: {
      type: String,
      default: ''
    },
    // å›žæ˜¾ä¸Šæ¬¡ä¿å­˜çš„æˆªå›¾çš„位置
    location: {
      type: Object,
      default () {
        return {}
      }
    }
    // iconItem:{
    //   type:Object,
    //   default(){
    //     return {};
    //   }
    // }
  },
  data () {
    return {
      // å­¦ä¹ æˆªå›¾é€‰é¡¹
      iconForm: {
        originImgBase64: '',
        imgBase64: ''
        // location: "",
        // matchingName: "",
        // matchingType: "",
        // note: "",
        // picGroupId: "0",
        // tsId: "",
      },
      // å‚¨å­˜æˆªå›¾åŒºåŸŸçš„图片,自己传
      // imgSrc:'',
      // å‚¨å­˜æˆªå›¾åŽçš„生成的base64图片
      cutImgSrc: '',
      // cropper插件的配置
      options: {
        canScale: false,
        autoCrop: true,
        canMove: false,
        centerBox: true,
        height: 500,
        width: 500,
        outputSize:{width: 500, height: 500 },
        autoCropWidth: 500,
        autoCropHeight: 500,
        fixed: true,
        fixedNumber: [1, 1]
      },
      // æˆªå›¾æ¡†ç›¸å¯¹å›¾ç‰‡çš„位置
      clipAxis: {},
      // æˆªå›¾å›žæ˜¾æ ‡å¿—,只触发一次实现回显,
      flag: true
    }
  },
  mounted () {
  },
  watch: {
  },
  methods: {
    getImagecropper(){
      return this.$refs.cropper
    },
    // å­¦ä¹ æˆªå›¾æ¡†å˜åŒ–事件
    realTime (data) {
      if (data.h) {
        // èŽ·å–å›¾ç‰‡ç›¸å¯¹å®¹å™¨çš„ä½ç½®
        const img = this.$refs.cropper.getImgAxis()
        // èŽ·å–æˆªå›¾æ¡†ç›¸å¯¹å®¹å™¨çš„ä½ç½®
        const clip = this.$refs.cropper.getCropAxis()
        this.clipAxis.x = clip.x1 - img.x1
        this.clipAxis.y = clip.y1 - img.y1
        // èŽ·å–æˆªå›¾å›¾ç‰‡
        this.$refs.cropper.getCropData(img => {
          this.clipAxis.width = data.w
          this.clipAxis.height = data.h
          this.cutImgSrc = img
        })
        // èŽ·å–åŽŸå›¾base64的图片
        // this.imageUrlToBase64(data.url);
        // å›¾æ ‡åˆ—表编辑回显(初始化只触发一次)
        if (this.location.height != undefined && this.flag) {
          this.$nextTick(() => {
            // auto crop
            this.$refs.cropper.goAutoCrop()
            this.$nextTick(() => {
              // if cropped and has position message, update crop box
              this.$refs.cropper.cropOffsertX = this.location.x + img.x1
              this.$refs.cropper.cropOffsertY = this.location.y + img.y1
              this.$refs.cropper.cropW = this.location.width
              this.$refs.cropper.cropH = this.location.height
              // this.iconForm.location=this.iconItem.location;
              // this.iconForm.matchingName=this.iconItem.matchingName;
              // this.iconForm.matchingType=this.iconItem.matchingType;
              // this.iconForm.note=this.iconItem.note;
              // this.picGroupId=this.iconItem.picGroupId.split(',');
              // this.iconForm.id=this.iconItem.id;
              // this.iconForm.tsId=this.iconItem.tsId;
              this.flag = false
            })
          })
        }
      }
    },
    // åŽŸå›¾é€šè¿‡canvas转为base64的格式
    imageUrlToBase64 (src) {
      // ä¸€å®šè¦è®¾ç½®ä¸ºlet,不然图片不显示
      const image = new Image()
      // è§£å†³è·¨åŸŸé—®é¢˜
      image.setAttribute('crossOrigin', 'anonymous')
      const imageUrl = src
      image.src = imageUrl
      // image.onload为异步加载
      image.onload = () => {
        var canvas = document.createElement('canvas')
        canvas.width = image.width
        canvas.height = image.height
        var context = canvas.getContext('2d')
        context.drawImage(image, 0, 0, image.width, image.height)
        // var quality = 0.8;
        // è¿™é‡Œçš„dataurl就是base64类型
        const dataURL = canvas.toDataURL('image/jpeg')// ä½¿ç”¨toDataUrl将图片转换成jpeg的格式
        this.iconForm.originImgBase64 = dataURL
      }
    }
  }
}
</script>
<style lang="scss" scoped>
.iconShot {
  .icon-dialog {
    .clip {
      display: flex;
      .img {
        flex: 7.5;
        height: 500px;
        //float: left;
        // display: inline-block;
        .vue-cropper {
          background-image: none;
        }
        .cropper-move {
          cursor: default;
        }
        .cropper-face.cropper-move {
          cursor: move;
        }
      }
      .previews {
        //width: 100px;
        flex: 2.5;
        //float: right;
        height: 200px;
        //position: relative;
        >img {
          //position: absolute;
          //left: 50%;
          transform: translate(35%, 50px);
          max-height: 100%;
        }
      }
    }
  }
  .icon-options {
    font-size: 12px;
    font-weight: 200;
    >.el-row {
      >.el-col {
        >.el-row {
          height: 36px;
          line-height: 36px;
          >.el-col:nth-child(1) {
            font-weight: 600;
            text-align: right;
          }
          .el-col:nth-child(2) {
            .el-input,.el-select {
              width: 185px !important;
            }
          }
          >.el-col {
            padding: 0 10px;
          }
        }
      }
    }
  }
}
</style>