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数据。

结束语:来公司一年了,年后好几个同事都离职了,自己也不知道未来要怎么走,庆幸的是自己发现了自己有很多的不足,最近也完成了一件对自己来说的“大事”,自己也在慢慢地努力中,一直在朝那个优秀的自己努力着。。。。。

发布了165 篇原创文章 · 获赞 139 · 访问量 38万+

猜你喜欢

转载自blog.csdn.net/CodingNoob/article/details/90140120