1. 程式人生 > >微信小程式實現圖片放大縮小,並擷取指定區域圖片

微信小程式實現圖片放大縮小,並擷取指定區域圖片

要在小程式中實現圖片放大縮小是著實不容易呀,還要把使用者選擇的指定區域生成圖片,簡直令人髮指。

不多說,上燒雞(程式碼)

首先還是先來看看要實現的效果

這裡寫圖片描述

使用者可以在指定的區域中滑動,放大,縮小自己的圖片,點選確定之後,把方框中的區域生成圖片。這個和上傳頭像功能差不多。

首頁我們要做的就是怎麼才能讓照片完美的顯示在頁面。圖片一般分為橫版和豎版圖片,這兩種情況要分開顯示。

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的開始座標這個我是廢了一番腦子才想到方法取得的。世上無難事,只怕有心人啊。

再廢話一句,這個頁面的功能的實現,可頁面的樣式也是有關的喲。照片的寬高,照片父節點的寬高。。。