vue实现列表滚动的过渡动画

本文实例为大家分享了Vue实现列表滚动过渡动画的具体代码,供大家参考,具体内容如下

效果图

失帧比较严重,在手机上效果更佳。

原理分析

这个滚动页面由两个部分布局(底部固定的Tab页面除外)。一个是顶部的banner轮播,一个是下面的列表。这里的重点是做列表的动画,banner轮播的网上资料很多,请自行查找。

vue实现列表滚动的过渡动画_第1张图片

这个动画最重要的是在滚动中实时计算startIndex和endIndex,动画比较简单,就是scale和opacity的变化。向下滚动时,startIndex变小;向上滚动时,endIndex变大时,新露脸的项做该动画。当滚动连起来,就是一个完整的动画了。

涉及的技术

使用better-scroll做滚动以及轮播图

使用create-keyframe-animation做动画控制

实现步骤

1、vue的template部分

注意:由于IOS渲染速度比较快, 必须把没有展现在首屏的页面上的item隐藏掉,即index比startIndex小、比endIndex大的item都应该隐藏,避免页面动画混乱。

{{item.num}}

{{item.name}}

{{item.desc}}

高度预设。用于计算startIndex、endIndex

const AreaItemHeight = 119 // 每一项的高度(这里默认一致,如果不一致请自行修改startIndex、endIndex的计算方式)
const MarginBottom = 15   // 列表项的底部边距
const TopHeight = 160    // banner的高度
const BottomHeight = 50   // 底部Tab的高度

监听滚动。并实时计算startIndex、endIndex

scroll (position) {
  const scrollY = position.y
  if (scrollY < 0) {
    // startIndex计算
    const currentStartIndex = Math.abs(scrollY) <= TopHeight ? 0 : parseInt((Math.abs(scrollY) - TopHeight) / (AreaItemHeight + MarginBottom))
    // endIndex计算
    let currentEndIndex = Math.floor((window.innerHeight - (TopHeight + scrollY) - BottomHeight) / (AreaItemHeight + MarginBottom))
    if (currentEndIndex > this.areaList.length - 1) {
      currentEndIndex = this.areaList.length - 1
    }
    // 这里使用vue的watch属性监听更好
    if (currentStartIndex !== this.startIndex) {
      if (currentStartIndex < this.startIndex) {
        // 运行动画
        this.runAnimation(currentStartIndex)
      }
      this.startIndex = currentStartIndex
    }
    // 这里使用vue的watch属性监听更好
    if (currentEndIndex !== this.endIndex) {
      if (currentEndIndex > this.endIndex) {
      this.runAnimation(currentEndIndex)
      }
      this.endIndex = currentEndIndex
    }
  }
}

运行动画

runAnimation (index) {
  animations.registerAnimation({
    name: 'scale',
    animation: [
      {
      scale: 0.5,
      opacity: 0
      },
      {
      scale: 1,
      opacity: 1
      }
    ],
    presets: {
      duration: 300,
      resetWhenDone: true
    }
  })
  animations.runAnimation(this.$refs['area-' + index], 'scale')
}

完整代码

.vue文件





本地json文件,请自行修改图片路径

bannerAddress.json

[
 {
  "id": 1,
  "contentId": 111111,
  "type": 1,
  "thumbUrl": "./static/img/banner/banner_address_1.jpg"
 },
 {
  "id": 2,
  "contentId": 111111,
  "type": 1,
  "thumbUrl": "./static/img/banner/banner_address_2.jpg"
 },
 {
  "id": 3,
  "contentId": 111111,
  "type": 1,
  "thumbUrl": "./static/img/banner/banner_address_3.jpg"
 }
]

areaList.json

[
 {
  "id": "ba062c32fdf611e7ba2d00163e0c27f8",
  "name": "凯里",
  "desc": "这是凯里哟~",
  "num": 17,
  "thumbUrl": "./static/img/area/kaili.png"
 }, {
  "id": "ba5287a7fdf611e7ba2d00163e0c27f8",
  "name": "丹寨",
  "desc": "这是丹寨哟~",
  "num": 8,
  "thumbUrl": "./static/img/area/danzai.png"
 }, {
  "id": "ba9da079fdf611e7ba2d00163e0c27f8",
  "name": "麻江",
  "desc": "这是麻江哟~",
  "num": 12,
  "thumbUrl": "./static/img/area/majiang.png"
 }, {
  "id": "baeb0926fdf611e7ba2d00163e0c27f8",
  "name": "黄平",
  "desc": "这是黄平哟~",
  "num": 7,
  "thumbUrl": "./static/img/area/huangping.png"
 }, {
  "id": "bb357191fdf611e7ba2d00163e0c27f8",
  "name": "施秉",
  "desc": "这是施秉哟~",
  "num": 6,
  "thumbUrl": "./static/img/area/shibing.png"
 }, {
  "id": "bb842d8ffdf611e7ba2d00163e0c27f8",
  "name": "镇远",
  "desc": "这是镇远哟~",
  "num": 3,
  "thumbUrl": "./static/img/area/zhenyuan.png"
 }, {
  "id": "bbce67dffdf611e7ba2d00163e0c27f8",
  "name": "岑巩",
  "desc": "这是岑巩哟~",
  "num": 23,
  "thumbUrl": "./static/img/area/cengong.png"
 }, {
  "id": "bc198ca9fdf611e7ba2d00163e0c27f8",
  "name": "三穗",
  "desc": "这是三穗哟~",
  "num": 66,
  "thumbUrl": "./static/img/area/sansui.png"
 }, {
  "id": "bc64498bfdf611e7ba2d00163e0c27f8",
  "name": "天柱",
  "desc": "这是天柱哟~",
  "num": 128,
  "thumbUrl": "./static/img/area/tianzhu.png"
 }, {
  "id": "bcaf466bfdf611e7ba2d00163e0c27f8",
  "name": "锦屏",
  "desc": "这是锦屏哟~",
  "num": 107,
  "thumbUrl": "./static/img/area/jinping.png"
 }, {
  "id": "bcfa6f1bfdf611e7ba2d00163e0c27f8",
  "name": "黎平",
  "desc": "这是黎平哟~",
  "num": 211,
  "thumbUrl": "./static/img/area/liping.png"
 }, {
  "id": "bd44cca9fdf611e7ba2d00163e0c27f8",
  "name": "从江",
  "desc": "这是从江哟~",
  "num": 17,
  "thumbUrl": "./static/img/area/congjiang.png"
 }, {
  "id": "bd8f5cd4fdf611e7ba2d00163e0c27f8",
  "name": "榕江",
  "desc": "这是榕江哟~",
  "num": 17,
  "thumbUrl": "./static/img/area/rongjiang.png"
 }, {
  "id": "bdda2928fdf611e7ba2d00163e0c27f8",
  "name": "雷山",
  "desc": "这是雷山哟~",
  "num": 17,
  "thumbUrl": "./static/img/area/leishan.png"
 }, {
  "id": "be25afc0fdf611e7ba2d00163e0c27f8",
  "name": "台江",
  "desc": "这是台江哟~",
  "num": 17,
  "thumbUrl": "./static/img/area/taijiang.png"
 }, {
  "id": "be702db5fdf611e7ba2d00163e0c27f8",
  "name": "剑河",
  "desc": "这是剑河哟~",
  "num": 17,
  "thumbUrl": "./static/img/area/jianhe.png"
 }
]

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

你可能感兴趣的:(vue实现列表滚动的过渡动画)