微信小程式實現圖片放大縮小,並擷取指定區域圖片
要在小程式中實現圖片放大縮小是著實不容易呀,還要把使用者選擇的指定區域生成圖片,簡直令人髮指。
不多說,上燒雞(程式碼)
首先還是先來看看要實現的效果
使用者可以在指定的區域中滑動,放大,縮小自己的圖片,點選確定之後,把方框中的區域生成圖片。這個和上傳頭像功能差不多。
首頁我們要做的就是怎麼才能讓照片完美的顯示在頁面。圖片一般分為橫版和豎版圖片,這兩種情況要分開顯示。
wx.chooseImage({
count: 1,
sizeType: ['original'],
success: function (res) {
wx.getImageInfo({
src: res.tempFilePaths[0 ],
success: function (res) {
//console.log(res.width);
//console.log(res.height);
var str = res.width / res.height;
if(str > 1){//橫版圖片
}else{//豎版圖片
}
}
})
}
})
呼叫wx.getImageInfo方法,拿到使用者選擇的圖片的寬高,用寬除以高就可以判斷圖片的型別了。
接下來就是處理圖片的寬高了,假設方框的大小是400*400,那麼:
wx.chooseImage({
count: 1,
sizeType: ['original'],
success: function (res) {
wx.getImageInfo({
src: res.tempFilePaths[0],
success: function (res) {
//console.log(res.width);
//console.log(res.height);
var str = res.width / res.height;//圖片的寬高比
if(str > 1){//橫版圖片
_this.data.height = 400;//圖片的顯示高度為400
_this.data.width = str * _this.data.height; //圖片的寬度 = 寬高比 * 圖片的顯示高度
}else{//豎版圖片
_this.data.width = 400;//圖片的顯示寬度為400
_this.data.height = str * _this.data.width; //圖片的高度 = 寬高比 * 圖片的顯示寬度
}
}
})
}
})
這樣,當是橫版圖片的時候,使用者能左右滑動自己的圖片,上下不讓他滑動,豎版同理。
關於怎麼讓圖片和方框居中顯示,我是用的padding填充,不是啥難事,這個就自己去摸索吧。
完成了圖片的顯示之後,接下來就是進入正題了,首先我們先完成圖片的放大縮小功能。
在小程式中提供了touchstart,touchmove,touchend這三個方法,分別是手指觸控動作開始,手指觸控後移動,手指觸控動作結束,我們要用到這三個方法來完成圖片的放大縮小功能。
wxml:
<scroll-view scroll-y="true" scroll-x="true" class = "FilePath" bindtouchmove="scroll" bindtouchstart='scroll' bindtouchend='endTou'>
<image src='{{src}}' style="width: {{width}}px;height: {{height}}px;" bindtouchmove="touch"></image>
</scroll-view>
監聽手指觸控的方法:
olddistance,//上一次兩個手指的距離
newdistance:"",//本次兩手指之間的距離,兩個一減咱們就知道了滑動了多少,以及放大還是縮小(正負嘛)
diffdistance:'', //這個是新的比例,新的比例一定是建立在舊的比例上面的,給人一種連續的假象
Scale: 1,//圖片放大的比例,
baseHeight:'', //原始高
baseWidth:'', //原始寬
//手指在螢幕上移動
scroll: function (e) {
var _this = this;
//當e.touches.length等於1的時候,表示是單指觸控,我們要的是雙指
if (e.touches.length == 2) {//兩個手指滑動的時候
var xMove = e.touches[1].clientX - e.touches[0].clientX;//手指在x軸移動距離
var yMove = e.touches[1].clientY - e.touches[0].clientY;//手指在y軸移動距離
var distance = Math.sqrt(xMove * xMove + yMove * yMove);//根據勾股定理算出兩手指之間的距離
if (_this.data.olddistance == 0) {
_this.data.olddistance = distance; //要是第一次就給他弄上值,什麼都不操作
// console.log("第一次");
}else {
_this.data.newdistance = distance; //第二次就可以計算它們的差值了
_this.data.diffdistance = _this.data.newdistance - _this.data.olddistance;//兩次差值
_this.data.olddistance = _this.data.newdistance; //計算之後更新比例
_this.data.Scale = _this.data.oldscaleA + 0.005 * _this.data.diffdistance;//這條公式是我查閱資料後找到的,按照這條公式計算出來的比例來處理圖片,能給使用者比較好的體驗
if (_this.data.Scale > 2.5){//放大的最大倍數
return;
} else if (_this.data.Scale < 1) {//縮小不能小於當前
return;
}
//重新整理.wxml ,每次相乘,都是乘以圖片的顯示寬高
_this.setData({
height: _this.data.baseHeight * _this.data.Scale,
width: _this.data.baseWidth * _this.data.Scale
})
_this.data.oldscaleA = _this.data.Scale;//更新比例
}
}
},
//手指離開螢幕
endTou: function (e) {
this.data.olddistance = 0;//重置
this.getRect();
}
getRect()是我用來獲取節點資訊的方法,用於得到wx.canvasToTempFilePath方法的座標點。(不懂得朋友可以點進去看看)
getRect: function () {
var _this = this;
wx.createSelectorQuery().select('.FilePath').boundingClientRect(function (rect) {
_this.data.x = Math.abs(rect.left);//x座標
_this.data.y = Math.abs(rect.top);//y座標
}).exec()
}
估計看到這裡有人就蒙了,其實rect.left和rect.top分別是節點的左邊界座標和節點的上邊界座標,這個座標可以視為偏移量,就是說’.FilePath’這個節點也就是我放圖片的標籤往左邊和上邊偏移了多少,再取他們的絕對值,就得到了我們需要的座標點了。
接下來就是最後一步了,我們要來擷取圖片,
wxml:
<canvas canvas-id="myCanvas_A" style="width: {{width}}px;height: {{height}}px;"/>
js:
generate: function () {
var _this = this;
const ctx_A = wx.createCanvasContext('myCanvas_A');
var baseWidth = _this.data.baseWidth * _this.data.Scale;//圖片放大之後的寬
var baseHeight = _this.data.baseHeight * _this.data.Scale;//圖片放大之後的高
ctx_A.drawImage(_this.data.src, 0, 0, baseWidth, baseHeight);//我們要在canvas中畫一張和放大之後的圖片寬高一樣的圖片
ctx_A.draw();
wx.showToast({
title: '擷取中...',
icon: 'loading',
duration: 10000
});//
setTimeout(function(){//給延時是因為canvas畫圖需要時間
wx.canvasToTempFilePath({//呼叫方法,開始擷取
x: _this.data.x,
y: _this.data.y,
width: 400,
height: 400,
destWidth: 400,
destHeight: 400,
canvasId: 'myCanvas_A',
success: function (res) {
console.log(res.tempFilePath);
}
})
}, 2000)
},
終於,世界都安靜了,完成!!!!!!!!!!
我該開始接到這個任務的時候,我的內心其實是挺崩潰的,後來靜下心來,一個功能一個功能的慢慢來,最終,還是弄出來了,挺開心的。
弄出來之後,發現其實也不難,只要處理好了圖片的縮放,其他的都不是啥難事,就是除錯的時候特別坑爹,只能在手機上除錯,在控制檯打了很多輸出,慢慢看著來弄的。
總結:
圖片的縮放就是監聽使用者雙指滑動的距離,在通過公式得到比例,然後拿這個比例和圖片的基本寬高相乘就可以了。擷取圖片這個就很簡單了,就是wx.canvasToTempFilePath的開始座標這個我是廢了一番腦子才想到方法取得的。世上無難事,只怕有心人啊。
再廢話一句,這個頁面的功能的實現,可頁面的樣式也是有關的喲。照片的寬高,照片父節點的寬高。。。