微信小程序动画 animation 实现轮播

目录

一 场景

二 思路

三 实现

总结:


一 场景

需要实现小程序的轮播图。目标如下

要求:图片数量可变(最少3个,最多不限),有动画效果

效果预览:

二 思路

查看小程序api:

问题1,每一个animations都绑定在一个view上,不能遍历获取。

所以对不确定数量的图片时,不能保证每个图片都绑定一个animations。

所以这里定义5个容器(可以看见3个,剩余两个隐藏在后面),用着5个容器装图片,每次滚动容器,容器带动图片,然后更新图片。

问题2,偏移量计算

有5个容器,每个容器动画实现的时候的偏移量计算是多少?

从图中可以看出,一共3个可视位置,每个位置对应的位移量分别为0,40,100(这里是百分比单位)

所以5个容器在三个位置的位移量分别为0(or 40 or 100)- 100 * index

三 实现

1.wxss

.video-box {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 30rpx;
}

.icon {
  width:24px;
  height:24px;
}

.box {
  width: 90%;
  z-index: 0;
  white-space: nowrap;
  display: flex;
  flex-direction: row;
}

.box .club {
  width: 335rpx;
  position: relative;
}

.club image {
  height: 370rpx;
  width: 335rpx;
}

.club text {
  display: block;
  width: 100%;
  font-size: 24rpx;
  line-height: 40rpx;
  text-align: center;
}

.box .club:nth-child(1) {
  transform-origin: center center;

}

.box .club:nth-child(2) {
  transform-origin: center center;

}

.box .club:nth-child(3) {
  transform-origin: center center;

}

2.wxml

<view class='video-box'>
  <view bindtap="scrollLeft"><image class='icon' src='../../images/left.png' mode='widthFit'></image></view>
  <view class="box" bindtouchstart="touchstart" bindtouchmove="touchmove" bindtouchend="touchend"
  >
  <block>
     <view class="club" animation="{{animation1}}" style='z-index:{{zindex[0]}};opacity:{{opacities[0]}};'>
      <image src="{{container[0].image}}"/>
      <text>{{container[0].name}}</text>
    </view>
    <view class="club" animation="{{animation2}}" style='z-index:{{zindex[1]}};opacity:{{opacities[1]}};'>
      <image src="{{container[1].image}}"/>
      <text>{{container[1].name}}</text>
    </view>
    <view class="club" animation="{{animation3}}" style='z-index:{{zindex[2]}};opacity:{{opacities[2]}};'>
      <image src="{{container[2].image}}"/>
      <text>{{container[2].name}}</text>
    </view>
    <view class="club" animation="{{animation4}}" style='z-index:{{zindex[3]}};opacity:{{opacities[3]}};'>
      <image src="{{container[3].image}}"/>
      <text>{{container[3].name}}</text>
    </view>
    <view class="club" animation="{{animation5}}" style='z-index:{{zindex[4]}};opacity:{{opacities[4]}};'>
      <image src="{{container[4].image}}"/>
      <text>{{container[4].name}}</text>
    </view>
  </block>
  </view>
  <view bindtap="scrollRight"><image class='icon' src='../../images/right.png'></image></view>
</view>

<view class="container">
  <view animation="{{animation}}" class="view">我在做动画</view>
</view>

3.js

a.数据准备

data: {
    clubs: [], //原始数据
    animations: [],
    touchDot: '',
    done: false,
    time: 0,
    container: [], //记录当前5个位置为哪5个item,理解为5个容器
    curPos: 2, //记录当前显示位置是第几个容器(从0开始)
    zindex: [0, 10, 100, 10, 0], //与container中的对应
    curIndex:1,//从显示位置的item在clubs中的index
    postions: [0,1,2,3,4],//container中5个容器所在位置
    opacities:[0,0.8,1,0.8,0],
  },

b.onload初始化

onLoad: function() {
    var data = [{ //原始数据,可为动态
        image: '../../images/a.png',
        name: '1美女'
      },
      {
        image: '../../images/b.png',
        name: '2美女'
      },
      {
        image: '../../images/c.png',
        name: '3美女'
      }, {
        image: '../../images/d.png',
        name: '4美女'
      },{
        image: '../../images/e.png',
        name: '5美女'
      }
    ]

    this.setData({
      clubs: data
    })
    //给5个容器赋值clubs0,1,2去到pos
    //pos的0,1,2,3,4为clubs的last,0,1,2,2+1
    //即pos的2(显示)位置是clubs的1位置
    this.setPos(2,1);

    //初始化到正确的位置
    var animation1 = wx.createAnimation({
      duration: 500,
      timingFunction: "ease",
      delay: 0
    })
    var animation2 = wx.createAnimation({
      duration: 500,
      timingFunction: "ease",
      delay: 0
    })
    var animation3 = wx.createAnimation({
      duration: 500,
      timingFunction: "ease",
      delay: 0
    })
    var animation4 = wx.createAnimation({
      duration: 500,
      timingFunction: "ease",
      delay: 0
    })
    var animation5 = wx.createAnimation({
      duration: 500,
      timingFunction: "ease",
      delay: 0
    })

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

    this.animation1.translateX('0%').opacity(0).scale(0).step();
    this.animation2.translateX('-100%').opacity(0.4).scale(0.8).step();
    this.animation3.translateX('-160%').opacity(1).scale(1).step();
    this.animation4.translateX('-200%').opacity(0.4).scale(0.8).step();
    this.animation5.translateX('-300%').opacity(0).scale(0).step();

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

  },

c.一些方法

//设置位置
  /**
   * pos:显示位置在container中的位置
   * index:显示位置的clubs索引
   */
  setPos: function(pos,index) {
    let container = [];
    let p2 = pos;
    let p1 = this.findPrePos(p2);
    let p0 = this.findPrePos(p1);
    let p3 = this.findNextPos(p2);
    let p4 = this.findNextPos(p3);
    let i2 = index;
    let i1 = this.findPreIndex(i2);
    let i0 = this.findPreIndex(i1);
    let i3 = this.findNextIndex(i2);
    let i4 = this.findNextIndex(i3);
    container[p0] = this.data.clubs[i0];
    container[p1] = this.data.clubs[i1];
    container[p2] = this.data.clubs[i2];
    container[p3] = this.data.clubs[i3];
    container[p4] = this.data.clubs[i4];
    this.setData({
      container
    })
  },
  /**
   * container中的位置
   */
  findNextPos: function(pos) {
    if (pos != 4) {
      return pos + 1;
    }
    return 0;

  },
  findPrePos: function(pos) {
    if (pos != 0) {
      return pos - 1;
    }
    return 4;
  },
 /**
   * newPos:新的他要到的的位置
   */
  findNewDistance(newPos,index) {
    let newDistances = [];
    switch (newPos) {
      case 0:
        newDistances = [0 - 100 * index + '%', 0, 0];
        break;
      case 1:
        newDistances = [0 - 100 * index + '%', 0.4, 0.8];
        break;
      case 2:
        newDistances = [40 - 100 * index + '%', 1, 1];
        break;
      case 3:
        newDistances = [100 - 100 * index + '%', 0.4, 0.8];
        break;
      case 4:
        newDistances = [100 - 100 * index + '%', 0, 0];
        break;
    }
    return newDistances;
  },
  setNewZindex(newPos) {
    let zindexes = [];
    zindexes[newPos] = 100;
    let nextPos = this.findNextPos(newPos);
    zindexes[nextPos] = 10;
    let nnextPos = this.findNextPos(nextPos);
    zindexes[nnextPos] = 0;
    let prePos = this.findPrePos(newPos);
    zindexes[prePos] = 10;
    let pprePos = this.findPrePos(prePos);
    zindexes[pprePos] = 0;
    this.setData({
      zindex: zindexes
    })
  },
  findNextIndex(index) {
    if (index != this.data.clubs.length - 1) {
      return index + 1;
    }
    return 0;
  },
  findPreIndex(index) {
    if (index != 0) {
      return index - 1;
    }
    return this.data.clubs.length - 1;
  }

d.右划事件

 //向右滑动事件
  scrollRight() {
    let container = this.data.container;
    let oldPos = this.data.curPos;
    let newPos = oldPos == 0 ? 4 : oldPos - 1;
    let newIndex = this.findPreIndex(this.data.curIndex);
    //先滑动,再赋值
    var animation1 = wx.createAnimation({
      duration: 500,
      timingFunction: "ease",
      delay: 0
    })
    var animation2 = wx.createAnimation({
      duration: 500,
      timingFunction: "ease",
      delay: 0
    })
    var animation3 = wx.createAnimation({
      duration: 500,
      timingFunction: "ease",
      delay: 0
    })
    var animation4 = wx.createAnimation({
      duration: 500,
      timingFunction: "ease",
      delay: 0
    })
    var animation5 = wx.createAnimation({
      duration: 500,
      timingFunction: "ease",
      delay: 0
    })

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

    let distances = [];
    let newPostions = [];
    let newOpacities = [];
    //用新位置找位移量
    for (let i = 0; i < container.length; i++) {
      let newPos = this.findNextPos(this.data.postions[i]);
      let distance = this.findNewDistance(newPos, i);
      distances.push(distance);
      newPostions.push(newPos);
      newOpacities.push(distance[1]);
    }
    this.animation1.translateX(distances[0][0]).opacity(distances[0][1]).scale(distances[0][2]).step();
    this.animation2.translateX(distances[1][0]).opacity(distances[1][1]).scale(distances[1][2]).step();
    this.animation3.translateX(distances[2][0]).opacity(distances[2][1]).scale(distances[2][2]).step();
    this.animation4.translateX(distances[3][0]).opacity(distances[3][1]).scale(distances[3][2]).step();
    this.animation5.translateX(distances[4][0]).opacity(distances[4][1]).scale(distances[4][2]).step();

    this.setData({
      opacities: newOpacities,
      postions: newPostions,
      animation1: animation1.export(),
      animation2: animation2.export(),
      animation3: animation3.export(),
      animation4: animation4.export(),
      animation5: animation5.export()
    })
    //赋值

    this.setPos(newPos, newIndex)
    this.setNewZindex(newPos)
    this.setData({
      curPos: newPos,
      curIndex:newIndex,
    })
  },

总结:

滑动触发借鉴了https://blog.csdn.net/sinat_22014829/article/details/76539612这篇博客,但是在图片数量不确定的情况下感觉有些不太够用,于是自己又写了一个。有些借鉴的代码没有写出来。整个项目可以到https://github.com/xing3gg/wx_littleProject_animation上去下载,如果有所启发记得打星哟!

猜你喜欢

转载自blog.csdn.net/qq_26444943/article/details/81483849
今日推荐