1. 程式人生 > >【總結】微信小程式

【總結】微信小程式

最近小程式有個需求要做一個類似輪播的自定義樣式,搜了一下外掛們,一般都用到了jQuery,但是小程式又不支援操作DOM,所以直接自己捲起袖子幹吧。
如果有任何有問題的地方,歡迎各位看官指出,大家一起討論才能進步地更快XD

文章基本流程:
1.效果圖
2.實現程式碼
3.被放棄的提案及理由(TAT)
4.總結

1.首先放實現的效果圖

因為需求裡只有中間的三張圖,所以之後會把旁邊兩張的opacity調成0,這裡為了方便看就留著啦。

這裡寫圖片描述

2. 程式碼

a. wxml

這裡之前考慮過要使用template,畢竟比較方便。但是每個圖片又會再繫結不同的動畫效果,所以就直接這樣攤大餅展開寫了,如果誰有更好的方法,答應我,一定要告訴我,好嘛 :)

<view style="white-space: nowrap;" class="box" bindtouchstart="touchstart" bindtouchmove="touchmove" bindtouchend="touchend">
    <view class="club" animation="{{animation1}}" bindtap="scrollLeft">
      <image src="{{clubs[0].image}}"/>
      <text>{{clubs[0].name}}</text
>
</view> <view class="club" animation="
{{animation2}}" bindtap="scrollLeft"> <image src="{{clubs[1].image}}"/> <text>{{clubs[1].name}}</text> </view> <view class="club" animation="{{animation3}}"> <image src="{{clubs[2].image
}}
"/> <text>{{clubs[2].name}}</text> </view> <view class="club" animation="{{animation4}}" bindtap="scrollRight"> <image src="{{clubs[3].image}}"/> <text>{{clubs[3].name}}</text> </view> <view class="club" animation="{{animation5}}" bindtap="scrollRight"> <image src="{{clubs[4].image}}"/> <text>{{clubs[4].name}}</text> </view> </view>

b. wxss

這裡因為沒有涉及到圖片互相遮蓋的問題,所以大膽地使用了opacity,但是如果做成了疊加效果的話,我的方法是使用偽類:after或者:before在圖片上加一個白色背景色帶透明度的一層。

有關css的transform3d可以參考【這篇簡單易懂的文章】
transform2d可以參考【這篇附帶演示的文章】

.box {
  height: 340rpx;
  z-index: 0;
  margin: 50rpx 0;
}
.box .club {
  height: 140rpx;
  width: 140rpx;
  position: relative;
  display: inline-block;
}
.club image {
  height: 140rpx;
  width: 140rpx;
}
.club text {
  display: block;
  width: 100%;
  font-size: 24rpx;
  line-height: 40rpx;
  text-align: center;
}
.box .club:nth-child(1) {
  transform: scale(0.8, 0.8) translateX(-120rpx);
  opacity: 0.2;
  z-index: 10;
}
.box .club:nth-child(2) {
  transform: scale(1,1) translateX(-80rpx);
  opacity: 0.5;
  z-index: 100;
}
.box .club:nth-child(3) {
  transform: scale(1.4,1.4);
  z-index: 1000;
}
.box .club:nth-child(4) {
  transform: scale(1,1) translateX(80rpx);
  opacity: 0.5;
  z-index: 100;
}
.box .club:nth-child(5) {
  transform: scale(0.8, 0.8) translateX(120rpx);
  opacity: 0.2;
  z-index: 10;
}
.box .club:nth-child(1) text,
.box .club:nth-child(2) text,
.box .club:nth-child(4) text,
.box .club:nth-child(5) text{
  visibility: hidden;
}

c. js

①首先,要通過js的touchstart,touchmove和touchend事件判斷手指的左右滑動。

//觸控開始事件
  touchstart: function(e) {
    console.log(e.touches[0].pageX);
    this.data.touchDot = e.touches[0].pageX;
    var that = this;
    this.data.interval = setInterval(function(){
      that.data.time+=1;
    },100);
  },
  //觸控移動事件
  touchmove: function(e) {
    let touchMove = e.touches[0].pageX;
    let touchDot = this.data.touchDot;
    let time = this.data.time;
    console.log("touchMove: " + touchMove + ", touchDot: " + touchDot + ", diff: " + (touchMove - touchDot));
    //向左滑動
    if(touchMove - touchDot <= -40 && time<10 &&!this.data.done) {
      console.log("向左滑動");
      this.data.done = true;
      this.scrollLeft();
    }
    //向右滑動
    if (touchMove - touchDot >= 40 && time < 10 && !this.data.done) {
      console.log("向右滑動");
      this.data.done = true;
      this.scrollRight();
    }
  },
  //觸控結束事件
  touchend: function(e) {
    clearInterval(this.data.interval);
    this.data.time = 0;
    this.data.done = false;
  }

②然後寫scrollLeft和scrollRight事件

這裡參考了【這篇文章】中設定動畫的方式。

主要思想:在一定的時間(duration)之內,讓圖片向左(/右)移動,並伴以適當的scale以及opacity變換。然後再在0s之內完成兩件事:一個是瞬間使剛才移動的圖片迴歸原位(scale和opacity自然也不必說),還有一個是在圖片的佇列中shift(/pop)出一個來再push(/unshift)進去,並且在0s內setData。這樣從視覺上看起來就是圖片向左(/右)滑動了。

此處需要注意的是:影象動畫的duration最好大於瞬間還原以及set陣列的定時時間。如果他們的時間都設定為同樣的話(如300),在滑動中肉眼能夠看到明顯的閃動(由於前後的圖片切換)。

//向左滑動事件
  scrollLeft(){
    var animation1 = wx.createAnimation({
      duration: 300,
      timingFunction: "linear",
      delay: 0
    })
    var animation2 = wx.createAnimation({
      duration: 300,
      timingFunction: "linear",
      delay: 0
    })
    var animation3 = wx.createAnimation({
      duration: 300,
      timingFunction: "linear",
      delay: 0
    })
    var animation4 = wx.createAnimation({
      duration: 300,
      timingFunction: "linear",
      delay: 0
    })
    var animation5 = wx.createAnimation({
      duration: 300,
      timingFunction: "linear",
      delay: 0
    })

    this.animation1 = animation1;
    this.animation2 = animation2;
    this.animation3 = animation3;
    this.animation4 = animation4;
    this.animation5 = animation5;

    this.animation1.translateX(-60).opacity(0).step();
    this.animation2.translateX(-140).opacity(0.5).scale(0.8,0.8).step();
    this.animation3.translateX(-110).opacity(0.5).scale(1,1).step();
    this.animation4.translateX(-70).opacity(1).scale(1.4,1.4).step();
    this.animation5.translateX(-30).opacity(0.5).scale(1,1).step();


    this.setData({
      animation1: animation1.export(),
      animation2: animation2.export(),
      animation3: animation3.export(),
      animation4: animation4.export(),
      animation5: animation5.export()
    })

    var that = this;
    setTimeout(function () {
      that.animation1.translateX(-50).opacity(0.2).scale(0.8, 0.8).step({ duration: 0, timingFunction: 'linear'});
      that.animation2.translateX(-40).opacity(0.5).scale(1, 1).step({ duration: 0, timingFunction: 'linear' });
      that.animation3.translateX(0).opacity(1).scale(1.4, 1.4).step({ duration: 0, timingFunction: 'linear' });
      that.animation4.translateX(40).opacity(0.5).scale(1, 1).step({ duration: 0, timingFunction: 'linear' });
      that.animation5.translateX(50).opacity(0.2).scale(0.8, 0.8).step({ duration: 0, timingFunction: 'linear' });
      that.setData({
        animation1: animation1.export(),
        animation2: animation2.export(),
        animation3: animation3.export(),
        animation4: animation4.export(),
        animation5: animation5.export()
      })
    }.bind(this), 195)

    let array = this.data.clubs;
    let shift = array.shift();
    array.push(shift);

    setTimeout(function () {
      this.setData({
        clubs: array
      })
    }.bind(this), 195)
  },

  //向右滑動事件
  scrollRight() {
    var animation1 = wx.createAnimation({
      duration: 300,
      timingFunction: "linear",
      delay: 0
    })
    var animation2 = wx.createAnimation({
      duration: 300,
      timingFunction: "linear",
      delay: 0
    })
    var animation3 = wx.createAnimation({
      duration: 300,
      timingFunction: "linear",
      delay: 0
    })
    var animation4 = wx.createAnimation({
      duration: 300,
      timingFunction: "linear",
      delay: 0
    })
    var animation5 = wx.createAnimation({
      duration: 300,
      timingFunction: "linear",
      delay: 0
    })

    this.animation1 = animation1;
    this.animation2 = animation2;
    this.animation3 = animation3;
    this.animation4 = animation4;
    this.animation5 = animation5;

    this.animation1.translateX(30).opacity(0.5).scale(1,1).step();
    this.animation2.translateX(70).opacity(1).scale(1.4, 1.4).step();
    this.animation3.translateX(110).opacity(0.5).scale(1, 1).step();
    this.animation4.translateX(120).opacity(0.2).scale(0.8, 0.8).step();
    this.animation5.translateX(130).opacity(0).step();


    this.setData({
      animation1: animation1.export(),
      animation2: animation2.export(),
      animation3: animation3.export(),
      animation4: animation4.export(),
      animation5: animation5.export()
    })

    var that = this;
    setTimeout(function () {
      that.animation1.translateX(-50).opacity(0.2).scale(0.8, 0.8).step({ duration: 0, timingFunction: 'linear' });
      that.animation2.translateX(-40).opacity(0.5).scale(1, 1).step({ duration: 0, timingFunction: 'linear' });
      that.animation3.translateX(0).opacity(1).scale(1.4, 1.4).step({ duration: 0, timingFunction: 'linear' });
      that.animation4.translateX(40).opacity(0.5).scale(1, 1).step({ duration: 0, timingFunction: 'linear' });
      that.animation5.translateX(50).opacity(0.2).scale(0.8, 0.8).step({ duration: 0, timingFunction: 'linear' });
      that.setData({
        animation1: animation1.export(),
        animation2: animation2.export(),
        animation3: animation3.export(),
        animation4: animation4.export(),
        animation5: animation5.export()
      })
    }.bind(this), 195)

    let array = this.data.clubs;
    let pop = array.pop();
    array.unshift(pop);

    setTimeout(function () {
      this.setData({
        clubs: array
      })
    }.bind(this), 195)
  }

3. 被放棄的提案

原本的需求是實現一個類似這樣的效果(不要笑我用了opacity,解決辦法我已經寫在了上邊的css部分裡):
這裡寫圖片描述
但是當我滿心歡喜,實現了靜態效果,準備做動畫的時候,發現小程式竟然不支援perspective!!!!!!!
啥?你問什麼是perspective?來看【這篇】或者【上邊wxss中提到的3d的這篇】

簡單說perspective就是透視,如果沒有透視,那麼無論你怎麼翻轉怎麼rotate,他都是一個矩形,或者一個平行四邊形(skew),而不會變成一個梯形,就是沒有近大遠小的效果。perspective就相當於z軸的大小,越大透視效果越強。

如圖(左邊的就是小程式的rotateY):
這裡寫圖片描述

//實現透視狀的css程式碼
.box .club:nth-child(1){
  transform-origin: 100% 50%;
  transform: perspective(600rpx) rotateY(45deg) translateX(420rpx) scale(1.5, 1.3);
  z-index: 0;
  opacity: 0.5;
}
.box .club:nth-child(2){
  transform-origin: 100% 50%;
  transform: perspective(600rpx) rotateY(45deg) translateX(200rpx) scale(1.3, 1);
  opacity: 0.5;
  z-index: 10;
}
.box .club:nth-child(3) {
  transform-origin: 100% 50%;
  transform: perspective(600rpx) rotateY(45deg) translateX(60rpx) scale(1.1, 0.9);
  opacity: 0.5;
  z-index: 100;
}
.box .club:nth-child(4) {
  transform: perspective(600rpx) rotateY(0deg);
  z-index: 1000;
}
.box .club:nth-child(5){
  transform-origin: 0 50%;
  transform: perspective(600rpx) rotateY(-45deg) translateX(-60rpx) scale(1.1, 0.9);
  opacity: 0.5;
  z-index: 100;
}
.box .club:nth-child(6){
  transform-origin: 0 50%;
  transform: perspective(600rpx) rotateY(-45deg) translateX(-200rpx) scale(1.3, 1);
  opacity: 0.5;
  z-index: 10;
}
.box .club:nth-child(7) {
  transform-origin: 0 50%;
  transform: perspective(600rpx) rotateY(-45deg) translateX(-420rpx) scale(1.5, 1.3);
  opacity: 0.5;
  z-index: 0;
}

無動畫實現效果:
這裡寫圖片描述

4. 總結

通過這次補了一下css的transform的知識,還接觸了下小程式的動畫感覺還蠻不錯的。雖然折騰了好幾天,但是感覺很有意義!
感謝閱讀
祝各位都有美好的一天 have a nice day~~~