VUE图片裁剪,打码,旋转功能

话不多说,直接上代码

1,先下载插件。

cnpm install image-mosaic -D   

cnpm install --save vue-cropper  

2,在components目录下创建一个imageEdit文件夹,文件夹下创建index.vue,index.vue中内容如下:

<template>
  <div>
    <el-dialog
      title=""
      :visible.sync="dialogImg"
      :close-on-click-modal="false"
      width="70%"
      top="5vh"
      :before-close="handleClose"
    >
      <div v-loading="isLoading" class="edit-img">
        <vueCropper
          ref="cropper"
          :img="editImgUrl"
          :info="false"
          :output-type="'png'"
          :info-true="true"
          :can-move="true"
          :can-scale="true"
          :can-move-box="true"
          :auto-crop-width="400"
          :auto-crop-height="400"
          :mode="'cover'"
          :center-box="true"
          :enlarge="2"
          :full="true"
          :max-img-size="200000"
          @imgLoad="imgLoadCrop"
        />
        <div v-if="isMosaic" class="tumo-img">
          <canvas id="canvas" />
        </div>
        <div class="button-group">
          <div class="button-item" @click="rotateHandle(1)">左旋90</div>
          <div class="button-item" @click="rotateHandle(2)">右旋90</div>
          <div class="button-item" @click="cropHandle">{
   
   { indexTab==1?'裁 剪':'取消裁剪' }}</div>
          <div class="button-item" @click="mosaicHandle">{
   
   { !isMosaic?'打 码':'取消打码' }}</div>
          <div class="button-item" @click="saveHandle">保 存</div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>

import { VueCropper } from 'vue-cropper'
import Mosaic from 'image-mosaic'
import { upLoad1 } from '@/api/files-management'
export default {
  components: {
    VueCropper
  },
  props: {
    dialogImg: {
      type: Boolean,
      default: () => false
    },
    imgPath: {
      type: String,
      default: () => ''
    }
  },
  data() {
    return {
      editImgUrl: '', // 编辑后的图片
      indexTab: 1, // 1是裁剪,2是取消裁剪
      isMosaic: false, // 是否打码
      isLoading: true
    }
  },
  watch: {
    imgPath (val) {
      this.editImgUrl = val
    }
  },
  methods: {
    imgLoadCrop() {
      this.isLoading = false
    },
    // 裁剪
    cropHandle() {
      if (this.indexTab === 1) {
        this.indexTab = 2
        setTimeout(() => {
          this.$refs.cropper.goAutoCrop()
        }, 0)
      } else {
        this.$refs.cropper.clearCrop()
        this.indexTab = 1
      }
    },
    // 旋转
    rotateHandle(val) {
      this.$refs.cropper.getCropData((data) => {
        this.editImgUrl = data
        this.$refs.cropper.clearCrop()
        setTimeout(() => {
          if (val === 1) this.$refs.cropper.rotateLeft()
          else this.$refs.cropper.rotateRight()
        }, 0)
      })
    },
    // 马赛克
    mosaicHandle() {
      this.isMosaic = !this.isMosaic
      if (this.isMosaic) {
        this.$refs.cropper.getCropData((data) => {
          this.editImgUrl = data
          this.indexTab = 1
          this.$refs.cropper.clearCrop()
          setTimeout(() => {
            this.initMosaic()
          }, 0)
        })
      }
    },
    handleClose() {
      this.$refs.cropper.clearCrop()
      this.editImgUrl = ''
      this.indexTab = 1
      this.isMosaic = false
      this.$emit('closeDialog')
    },
    drawImageToCanvas(imageUrl) {
      const canvas = document.querySelector('#canvas')
      const ctx = canvas.getContext('2d')
      return new Promise((resolve, reject) => {
        const image = new Image()
        image.crossOrigin = 'Annoymous'
        image.onload = function() {
          const w = image.width
          const h = image.height
          const yw = document.body.clientWidth * 0.7
          const yh = 733
          if ((w / yw) >= (h / yh)) {
            image.width = yw
            image.height = (yw / w) * h
          } else {
            image.height = yh
            image.width = (yh / h) * w
          }
          canvas.width = image.width
          canvas.height = image.height
          ctx.drawImage(this, 0, 0, image.width, image.height)
          resolve(ctx)
        }
        image.src = imageUrl
      })
    },
    initMosaic() {
      this.drawImageToCanvas(this.editImgUrl).then((ctx) => {
        const mosaic = new Mosaic(ctx)
        const MouseEvents = {
          init() {
            mosaic.context.canvas.addEventListener(
              'mousedown',
              MouseEvents.mousedown
            )
          },
          mousedown() {
            mosaic.context.canvas.addEventListener(
              'mousemove',
              MouseEvents.mousemove
            )
            document.addEventListener('mouseup', MouseEvents.mouseup)
          },
          mousemove(e) {
            if (e.shiftKey) {
              mosaic.eraseTileByPoint(e.layerX, e.layerY)
              return
            }
            mosaic.drawTileByPoint(e.layerX, e.layerY)
          },
          mouseup() {
            mosaic.context.canvas.removeEventListener(
              'mousemove',
              MouseEvents.mousemove
            )
            document.removeEventListener('mouseup', MouseEvents.mouseup)
          }
        }
        MouseEvents.init()
      })
    },
    saveHandle() {
      if (this.isMosaic) {
        var dataURL = document.querySelector('#canvas').toDataURL('image/png')
        this.editImgUrl = dataURL
        setTimeout(() => {
          this.uploadImg()
        }, 1000)
      } else {
        this.uploadImg()
      }
    },
    // 上传图片
    uploadImg() {
      const formData = new FormData()
      this.$refs.cropper.getCropBlob(data => {
        formData.append('file', data, '自定义文件名')
        upLoad1(formData)
          .then(res => {
            if (res.message === 'ok') {
              this.$message.success('图片编辑成功')
            } else {
              this.$message.warning(res.message)
            }
            this.$refs.cropper.clearCrop()
            this.editImgUrl = ''
            this.indexTab = 1
            this.isMosaic = false
            this.$emit('closeDialog')
          })
      })
    }
  }
}
</script>

<style lang="scss" scoped>

.edit-img {
    width: 100%;
    height: 733px;
    position: relative;
}

.tumo-img {
    position: absolute;
    width: 100%;
    height: 733px;
    top: 0;
    left: 0;
    border-radius: 2px solid red;
}
.button-group {
    position: absolute;
    bottom: 30px;
    display: flex;
    .button-item {
        width: 100px;
        height: 38px;
        border-radius: 4px;
        text-align: center;
        line-height: 38px;
        background-color: rgba($color: #000000, $alpha: 0.5);
        color: #FFFFFF;
        margin-left: 10px;
        cursor: pointer;
    }
}
::v-deep {
.cropper-modal {
    background: rgba(0, 0, 0, .4) !important;
}

}
</style>

3,组件写好后直接在页面中调用。

<template>
   <div>
     <div @click="imgUrlEdit('图片地址')">图片编辑</div>
     <image-edit
       :dialog-img="imgEditShow"
       :img-path="imgPath "
       @closeDialog="closeDialog"
      />
  </div>
</template>

<script>
   import ImageEdit from '@/components/imageEdit'
   export default {
        components: {
            ImageEdit

          },
     data() {
        return {
              imgEditShow: false, // 图片编辑框
              imgPath: '' //  图片编辑源
        }
     },
       method: {
            closeDialog() {
              this.imgEditShow = false
            },
            // 图片编辑
            imgUrlEdit(img) {
              this.imgEditShow = true
              this.imgPath = img
            }
        }
   }
</script>

这样,一个简单的裁剪,打码,选择就完成了

猜你喜欢

转载自blog.csdn.net/pleasantsheep_/article/details/123877507