作移動端的時候,各位可能會遇到用戶上傳頭像,而前端的input:file,若是上傳正方形圖片還好,可是若是是矩形的話,在頭像的顯示這塊,就會顯的很不和諧。前端
前端跟進矩形的圖片,實現裁剪成正方形,並把裁剪後的文件上傳給後臺。canvas
1.初始頁面以下,點擊中間默認頭像觸發input:file點擊,彈出選擇文件框.this
![](http://static.javashuo.com/static/loading.gif)
2.開始選擇照片,以下,爲選擇的照片,和選擇照片後的效果圖:3d
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
3.此時圖片的高度大於寬度,所以能夠上下滾動,選擇想要裁剪的範圍,而後點擊選取(下圖從地鐵導航處開始裁剪)。
code
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
此時,已經裁剪到正方形圖片,能夠從新拍攝或者上傳給後臺。component
下面是代碼cdn
setPhoto(e) {//對圖片尺寸作出限制並設置壓縮尺寸
let _this = this;
let file = e.target.files[0];
if (!file) return ''
//大於6兆,不容許上傳
if (file.size > this.maxSize * 6) {
return; this.$toast('圖片過大,不能大於6M')
}
if (file.size > this.maxSize * 3) {//this.maxSize 爲1024 * 1024,設置的一張照片最後
this.ratio = 0.5;
} else if (file.size > this.maxSize * 4) {
this.ratio = 0.4;
}
Lrz(file, { width: 1024, quality: this.ratio })
.then((rst) => { //這裏使用Lrz,防止圖片選中後旋轉,若是沒有這個問題,也能夠不使用Lrz,直接把this.file轉換爲bolb對象的圖片顯示出來
// 把處理的好的圖片給用戶看看唄
// _this.$refs['avatar_img'].src = rst.base64;
_this.$refs['clip_avatar'].src = rst.base64;
_this.$nextTick(() => {
_this.avater_width_larger_height = _this.$refs['clip_avatar'].height < _this.$refs['clip_avatar'].width
})
_this.show_clip_img = true;
return rst;
}).then((rst) => {
this.file= rst.file;
})
},
checkClip(e) {//滑動後點擊選取觸發該方法,獲取滾動的x和Y的距離傳給 setPhotoCanvas,以便canvas裁剪。
let sTop = this.$refs['clip_img'].scrollTop;
let sLeft = this.$refs['clip_img'].scrollLeft;
this.setPhotoCanvas(sTop, sLeft);
},
setPhotoCanvas(sTop, sLeft) {
let reader = new FileReader();
reader.onloadend = (e) => {
let img = new Image();
img.onload = () => {
let w = Math.min(this.maxWidth, img.width);
let h = img.height * (w / img.width);
let [sw, sh, short, sx, sy] = [img.width, img.height, 0, 0, 0, 0]
if (w < h) {
short = w;
sy = (sTop / document.body.clientWidth) * img.width//這裏頭像裁剪的時候,寬度爲屏幕的寬度,所以document.body.clientWidth。若是正方形的寬度不是屏幕寬度,這裏和sx的獲取都須要替換。
sh = sw;
} else { //w>h
short = h;
sx = (sLeft / document.body.clientWidth) * img.height
sw = sh;
}
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
// 設置 canvas 的寬度和高度
canvas.width = short;
canvas.height = short;
ctx.drawImage(img, sx, sy, sw, sh, 0, 0, short, short);
let base64 = canvas.toDataURL('image/png', this.ratio);
// 插入到預覽區
this.$refs[ 'avatar_img'].src = base64;
this.show_clip_img = false;
this.file = this.dataURItoBlob(base64);
console.log('size-------------------' + this.file.size)
};
img.src = e.target.result;
}
reader.readAsDataURL(this.file);
},
dataURItoBlob: function(dataURI) {//把用canvas獲得的base64圖片轉換爲二進制大對象以便傳給後臺
// convert base64/URLEncoded data component to raw binary data held in a string
let byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0) {
byteString = atob(dataURI.split(',')[1]);
} else {
byteString = unescape(dataURI.split(',')[1]);
}
// separate out the mime component
let mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
let ia = new Uint8Array(byteString.length);
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], { type: mimeString });
},