最近在做一個項目,要實現用戶上傳人臉圖片給後端,大小和人臉都有一定的要求,需要使用到在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數據。
結束語:來公司一年了,年後好幾個同事都離職了,自己也不知道未來要怎麼走,慶幸的是自己發現了自己有很多的不足,最近也完成了一件對自己來說的“大事”,自己也在慢慢地努力中,一直在朝那個優秀的自己努力着。。。。。