vue實現自定義裁剪圖片大小組件

最近在做一個項目,要實現用戶上傳人臉圖片給後端,大小和人臉都有一定的要求,需要使用到在web端實現圖片裁剪功能,也就是將圖片裁剪到對應大小,然後發送給後端。識別這個人的人臉!

於是想了一下要用canvas的drawImage實現這樣功能。

原理很簡單就是通過放大縮小和移動,確定放大縮小後的圖片的寬高和相對截圖canvas左邊和上邊的位置的值,對應使用canvas的api就可以實現。

上代碼:

<template>
  <div class="cropper" id="cropper"
    :style="{width: (cropperWidth + 20) + 'px', height: (cropperHeight + 100) + 'px'}"
  >
    <div class="box"
      @mousedown="boxMousedown($event)"
      @mousemove="boxMousemove($event)"
      @mouseup="boxMouseup($event)"
      :style="{width: cropperWidth + 'px', height: cropperHeight + 'px'}"
    >
      <canvas id="cropperCan" :width="cropperWidth" :height="cropperHeight" ref="canvas"></canvas>
      <img
        draggable="false"
        :src="imgUrl"
        :style="{
          height: cpheight + 'px',
          width: cpwidth + 'px',
          left: cpleft + 'px',
          top: cptop + 'px'
        }"
        ref="phone"
      />
    </div>
    <div class="contr">
      <el-slider v-model="scale" @change="scaleImg"></el-slider>
    </div>
    <div class="btn">
      <el-button type="primary">取消</el-button>
      <el-button type="primary" @click="savePic">保存</el-button>
    </div>
  </div>
</template>
<script>
// import { base64 } from './base64.js';
let orginLeft = 0;
let orginTop = 0;
export default {
  data () {
    return {
      // base64Img: base64,
      mouseStartX: 0, // 鼠標按鈕的X坐邊
      mouseStartY: 0, // 鼠標按下的Y座標
      mouseEndX: 0,
      mouseEndY: 0,
      ismpuseMove: false, // 是否移動標識
      scale: 100, // 放大縮小倍數
      // cropperHeight: 400, // 畫布高度輸出的圖片大小
      // cropperWidth: 400,  // 畫布寬度輸出圖片的寬度
      height: 700, // 外部計算得出圖片的高度尺寸傳進來
      width: 933, // 外部計算得出圖片的寬度尺寸傳進來
      left: 0,
      top: 0
    };
  },
  props: ['cropperHeight', 'cropperWidth', 'imgUrl'],
  computed: {
    // 計算圖片放大縮小的寬度
    cpwidth: function () {
      let scaleVal = this.scale / 100;
      return this.width * scaleVal;
    },
    // 計算圖片放大縮小的高度
    cpheight: function () {
      let scaleVal = this.scale / 100;
      return this.height * scaleVal;
    },
    // 計算圖片移動後的相對截圖左邊的位置
    cpleft: function () {
      let scaleVal = 1;
      return this.left * scaleVal;
    },
    // 計算圖片移動後的相對截圖頂部邊的位置
    cptop: function () {
      let scaleVal = 1;
      return this.top * scaleVal;
    }
  },
  beforeCreate () {
  },
  mounted () {
    this.height = this.$refs.phone.getBoundingClientRect().height;
    this.width = this.$refs.phone.getBoundingClientRect().width;
  },
  methods: {
    // 鼠標按下
    boxMousedown (event) {
      this.ismpuseMove = true;
      this.mouseStartX = event.clientX;
      this.mouseStartY = event.clientY;
      orginLeft = this.left;
      orginTop = this.top;
    },
    // 鼠標拖動圖片跟着拖動
    boxMousemove (event) {
      if (this.ismpuseMove) {
        let x = event.clientX;
        let y = event.clientY;
        this.left = orginLeft + (x - this.mouseStartX);
        this.top = orginTop + (y - this.mouseStartY);
      }
    },
    // 鼠標點擊
    boxMouseup (event) {
      this.ismpuseMove = false;
      this.mouseStartX = 0;
      this.mouseStartY = 0;
    },
    scaleImg (val) {
    },
    savePic () {
      let can = this.$refs.canvas; // canvas對象
      let cpImg = new Image();
      let sx = this.cpleft;
      let sy = this.cptop;
      let cwidth = this.cpwidth;
      let cheight = this.cpheight;
      cpImg.src = this.$refs.phone.src;
      cpImg.width = this.cpwidth;
      cpImg.height = this.cpheight;
      can.getContext('2d').clearRect(0, 0, 478, 500); // 清空畫布
      can.getContext('2d').drawImage(cpImg, sx, sy, cwidth, cheight); // 繪製畫布
      let dataURL = can.toDataURL('image/png');
      this.$emit('cropperImg', dataURL); // 拋出截圖base64對象數據

      // 調試預覽截圖
      let preImg = new Image();
      preImg.src = dataURL;
      document.querySelector('#mainBox').appendChild(preImg);
    }
  }
};
</script>
<style lang="less" scoped>
  #cropper{
    padding: 10px;
    border:1px solid #ccc;
    margin:20px 0 0 600px;
    background: #fff;
    .box {
      position: relative;
      height: 500px;
      width: 100%;
      overflow: hidden;
      background: url('./bg.png');
      #cropperCan {
        position: absolute;
        left: 0;
        display: none;
        height: 500px;
        width: 100%;
      }
      img {
        position: relative;
      }
    }
    .contr {
      padding: 0 20px;
    }
    .btn {
      text-align: right;
    }
  }
</style>

最後運行結果:

使用的時候可以直接調用組件:

<cropper
   :cropperHeight="400"
   :cropperWidth="400"
   :imgUrl="img"
   @cropperImg="cropperImg"
/>

cropperHeight、cropperWidth代表要裁剪的高和寬,imgUrl爲圖片的src地址 base64或者URL都可以,cropperImg則爲截圖保存後拋出的裁剪後的圖片base64數據。

結束語:來公司一年了,年後好幾個同事都離職了,自己也不知道未來要怎麼走,慶幸的是自己發現了自己有很多的不足,最近也完成了一件對自己來說的“大事”,自己也在慢慢地努力中,一直在朝那個優秀的自己努力着。。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章