小球飛入購物車動畫及購物車列表彈出,收起

人生中第一次寫博客,寫的很差,各位大佬多多包涵。。。 話很少說,效果圖以下:css

思路:

我是用一個遊離的view標籤來作的,這個view採用fixed定位,默認top: 0; left: 0;css3

注:文中的遊離view均指動畫播放發生運動的view,即下面的圖片中紅色箭頭所指的元素git

當點擊加號的時候,會發生如下操做:github

  1. 獲取當前點擊加號的位置信息,計算出top值和left值,並將這個遊離的view定位到當前點擊的位置,這是動畫開始位置面試

  2. 計算出左下角購物車距離頂端的left, top值,這是動畫結束位置小程序

  3. 而後使用css3動畫,使其移動從開始位置移動到結束位置,left, top, opacity同時發生變化bash

Tips: 至於爲何不用小程序自帶的wx.createAnimation呢?是由於使用這個播放一次動畫以後,不能清除樣式,第二次加入購物車遊離view不能正確設置top, left值,好苦惱。。。css3動畫

這個飛入效果是css3實現的,因此其它的也能夠用,不侷限於小程序,就是獲取top, left的地方各有不一樣xss

接下來分佈介紹:工具

步驟一: 獲取當前點擊加號的top, left值

獲取當前點擊加號的top, left值

加入購物車按鈕綁定的點擊事件爲selectGoods

selectGoods(e) {
    let that = this;
    // 獲取當前點擊位置距離頂部的高度,即圖中標出來的,紅色字體寫的top值,left值
    // top值和left值分別減去40, 是爲了使遊離的view定位到當前點擊位置的左上方,有一種先彈上去,再飛入購物車的感受,這裏懶就不用動畫了,哈哈
    let top = e.detail.y - 40;
    let left = e.detail.x - 40;
    that.setData({
      style: `top: ${top}px;left: ${left}px;`
    })
    that.playAnimation(e, left, top); // 播放動畫
},
複製代碼

遊離的view樣式以下:

<view class="animat" style="{{style}}">
    <image class="icon" src="/resources/images/icon_add01.png"></image>
</view>
複製代碼
.animat{
  position: fixed;
  top: 0px;
  left: 0px;
}
複製代碼

點擊加號的時候動態設置style值設置top, left

這一步結束後的效果圖以下:

步驟二: 計算出左下角購物車距離頂端的left, top值

小程序有提供獲取元素位置的方法,我大概封裝了只須要傳id的一個方法,方便使用,以下:

quertElementSize(id, callback) {
    let query = wx.createSelectorQuery();
    query.select('#' + id).boundingClientRect((rect) => {
      callback && callback(rect);
    }).exec()
}
複製代碼
/**
 * 獲取左下角購物車圖標top, left值
*/
quertShoppingCarSize() {
    let that = this;
    this.quertElementSize('shoppingCar', function (rect) {
      that.setData({
        'shoppingCarSize.top': rect.top + (rect.height / 2),
        'shoppingCarSize.left': rect.left + (rect.width / 2)
      })
    });
},
複製代碼

以下圖:

獲取元素中心點距離頂部top值,和距離左邊left值

因爲這個圖標的位置的固定的,因此這個位置信息能夠提早獲取,存儲到data中,不用每次加入購物車的時候再算

步驟三: 使用css3動畫,使其移動到左下角購物車的位置,left, top, opacity同時發生變化

步驟一和二已經拿到了動畫初始位置的top,left值,和結束位置的top, left值

如今只須要用animation,將這個遊離view從初始位置移動到結束位置就能夠了,代碼以下:

/**
 * 小球飛入購物車動畫
*/
playAnimation(e, left, top) {
    let that = this;
    this.aniTimer = setTimeout(function () {
      that.setData({
        style: `--startLeft: ${left}px;--startTop: ${top}px;
        --endLeft: ${that.data.shoppingCarSize.left}px;
        --endTop: ${that.data.shoppingCarSize.top}px;
        animation: runTop .3s cubic-bezier(.66,.1,1,.41), runLeft .3s linear;`
      })
    }, 5);
    that.setDataAddShoppingCar(e);
},
複製代碼

這裏解釋一下:

  1. --startLeft: ${left}px; 這裏使用了css變量, startLeft, startTop, endLeft, endTop均爲變量,在wxss中的css代碼用var(--startTop)方式使用變量
  2. animation: runTop .3s cubic-bezier(.66,.1,1,.41), runLeft .3s linear; 這裏的top變化和left變化分別是兩個不用的動畫,而且這兩個動畫的速度不一致,可使運行軌跡爲曲線
  3. 這裏加定時器的緣由是,是保證這個動畫是最後執行的,就好比說經典面試題
setTimeout(function(){
    console.log(1);
})
console.log(2);
// 輸入結果爲 2 1
複製代碼

CSS代碼: 動態獲取開始位置top, left值和結束位置top,left值

@keyframes runTop {
  0%{
    top:  var(--startTop);
      opacity: 1;
  }
  90%{
      opacity: 1;
  }
  100%{
    top: var(--endTop);
    opacity: 0;
  }
  }
@keyframes runLeft {
  0%{
    left: var(--startLeft);
      opacity: 1;
  }
  90%{
      opacity: 1;
  }
  100%{
    left: var(--endLeft);
          opacity: 0;
  }
}
複製代碼
/**
   * 更新數據
   */
  setDataAddShoppingCar(e) {
    let that = this;
    let index = e.currentTarget.dataset.index;
    let data = that.data.nowShowData[index];
    data.isSelect = true;

    let nowSelectData = that.data.nowSelectData;
    let tag = 'nowShowData[' + index + '].isSelect';

    nowSelectData.push(data);
    that.setData({
      [tag]: true,
      nowSelectData: nowSelectData
    });
  },
複製代碼

到這裏,飛入購物車效果就完成了,鼓掌👏

接下來就是購物車列表彈出和收起##

這裏就使用的是wx.createAnimation

代碼以下:

/**
   * 購物車列表彈起
   */
  transShoppingCar() {
    let that = this;
    if (this.data.nowSelectData.length === 0) {
      wx.showToast({
        title: '購物車內沒有商品哦~',
        icon: 'none',
        duration: 1500
      })
      return;
    }
    let shoppingCarIsShow = that.data.shoppingCarIsShow;
    shoppingCarIsShow = !shoppingCarIsShow;

    var animation = wx.createAnimation({
      duration: 500,//動畫的持續時間 默認400ms   數值越大,動畫越慢   數值越小,動畫越快
      timingFunction: 'ease',//動畫的效果 默認值是linear
    });
    this.animation = animation;
    if (shoppingCarIsShow) {
      this.setData({
        shoppingCarIsShow: shoppingCarIsShow
      });
      that.fadeIn();//調用顯示動畫

    } else {

      that.fadeDown();//調用隱藏動畫   
      let time = setTimeout(function () {
        this.setData({
          shoppingCarIsShow: shoppingCarIsShow
        });
        clearTimeout(time);
      }.bind(this), 500)//先執行下滑動畫,再隱藏模塊
    }
  },
  //動畫集
  // 進入
  fadeIn: function () {
    this.animation.translateY(0).opacity(1).step()
    this.setData({
      animationData: this.animation.export()
    })
  },
  fadeDown: function () {
    this.animation.translateY(300).opacity(0).step()
    this.setData({
      animationData: this.animation.export(),
    })
  }, 
複製代碼

WXML代碼

<view class="goodsList" animation="{{animationData}}"></view>
複製代碼

思路:

利用translateY實現,初始列表translateY(300),彈出動畫使translateY變爲0,隱藏時translateY又變爲300

因此樣式中要進行初始位置translateY(300),即:

.goodsList {
    background-color: #fff;
    transform: translateY(300px);
}
複製代碼

代碼github自取: github.com/orangleLi/o…

demo文件夾, 下載下來開發者工具直接導入就能夠了

相關文章
相關標籤/搜索