【總結】微信小程式
最近小程式有個需求要做一個類似輪播的自定義樣式,搜了一下外掛們,一般都用到了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~~~