博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何做活动页面的滚动动画?让用户体验MAX的demo在这里!
阅读量:6916 次
发布时间:2019-06-27

本文共 2609 字,大约阅读时间需要 8 分钟。

hot3.png

本文由云+社区发表

最近的一个活动页面需要做一个可以左右滑动的抽签效果,故通过用css的transform属性和js结合来模拟可以无限滚动的效果。

先上效果:

img

demo地址:

实现过程

1. 结构与样式

结构:卡片分前后两排,每列插入10个div结点,以便做左右位移效果。

样式:设置每一列都恰好好在中间位置(或中间位置附近),如下所示。

a. 前排(cardFrond)相对于视口的初始位置(left:-255.5%;):

img

b. 后排(backFrond)相对于视口的初始位置(left:-228.3%;):

img

2. 无限滚动原理

由于这里的停止位置是固定的,前排永远是当前卡片相对于视口居中,后排永远是两个卡片相对于视口居中,且每个卡片是一样的,所以当卡片列表向前或向右移动到一个目标位置时,都将列表重置为初始位置继续滚动。如下图以前排卡片为例:

img

所以当滚动停止后会统一将列表样式设置为transform: translateX(0)。而对于用户这一操作是无感知的,认为已经滑动到了新的位置。

3.滑动过程实现

a. 目标位移与帧位移

为了做出滑动后到停留位置的缓动效果,所以当用户左右滑动屏幕时,会记录滑动距离,计算出卡片该到的目标位移位置,目标位移位置是有规则的,因为这里有10张卡片均分宽度,位置必须是(100%/10)的整数倍,例如-40%、-30%、……40%,这样才能保证目标位置与初始位置相重合。

目标位移代码片段

onDocumentMouseUp : function(e){    //如果是点击事件 不设置移动    if (!this.fingerTouch)      return;    this.moveDirect = this.lon > 0 ? 1 : -1;    this.transNum = this.lon/10 + this.moveDirect;    this.lon = Math.round(this.transNum) * 10;    this.fingerTouch = false;   }

记录了目标位移后,每一帧会以一定的帧位移不断靠近目标位移,使其在手指离开屏幕时仍有慢慢滑动到目标位置的缓动效果。此时需要判断当前位置是否大于40%或者小于-40%,若超过这个极限值需要重设目标位移及帧位移,使其在极限值内。

animate: function(){    this.prePos += (this.lon - this.prePos) * 0.1;    if (this.prePos > 40) {      this.lon = this.lon - 40;      this.prePos = this.prePos - 40;    }else if (this.prePos < -40) {      this.lon = this.lon + 40;      this.prePos = this.prePos + 40;    }    //判断是否到达了目标位置    if (Math.abs(this.prePos - this.lon) < 0.01 && Math.abs(this.lon) > 0.01 && (!this.fingerTouch))    {        this.ani_move = false;        this.prePos = 0;        this.frondCard.style = "transform: translateX("+ this.prePos +"%)";        this.backCard.style = "transform: translateX("+ this.prePos +"%)";    }else{        this.frondCard.style = "transform: translateX("+ this.prePos +"%)";        this.backCard.style = "transform: translateX("+ (-this.prePos) +"%)";        requestAnimationFrame(this.animate.bind(this));    }  },

b. 连续滑动判断

当在上次滑动动画还未播放结束时用户又进行了第二次滑动时,需要执行一下操作:

​ 1). 判断滑动时机处于上次滑动手指已离开屏幕但动画还未结束,此时需要记录两个flag,一个是ani_move,记录动画是否仍在进行,fingerTouch记录手指是否停留屏幕。

​ 2). 判断第二次滑动是否与第一次不同方向,若不同向需重置上次帧位移为0。以免上次帧位移太大影响移动方向。

1)与2)代码片段:

if( this.ani_move && this.fingerTouch == false) {    // 判断是否不同向    if (((e.clientX - prex) > 0 ? 1: -1) == -this.moveDirect ) {        this.lon = 0;        this.prePos = 0;        this.moveDirect = -this.moveDirect;    }}

3). 取消第二次滑动时的动画播放和位移重置

// 若是上次动画未结束不需要再次启动动画和重置目标位移if( this.ani_move && this.fingerTouch == false) {}else {    this.lon = 0;     cardAnimate.animate();}

写在最后

目前这个滑动效果只能针对卡片相同,停留位置固定的情况,因为需要做到位置重合。使用css transform来做无限滚动的效果,可以避免改变dom结点带来的页面重新布局。

下图是chrome cpu6倍减速调试效果,没有触发layout,FPS基本维持在60左右。

img

代码地址:

此文已由作者授权腾讯云+社区发布


转载于:https://my.oschina.net/qcloudcommunity/blog/2991708

你可能感兴趣的文章
VUE 使用笔记
查看>>
(转)Android studio 多渠道打包(超简洁版)
查看>>
SpringBoot源码解析-内嵌Tomcat容器的启动
查看>>
阿里Java面试题剖析:关于系统拆分,为什么要进行系统拆分?
查看>>
Application 详解
查看>>
朋友,这里有个仓库需要你 PR 一下
查看>>
nginx-kafka 数据采集
查看>>
30年分布,30年集中——高校认证计费的变革
查看>>
我的友情链接
查看>>
Python-w3
查看>>
jpeg note
查看>>
一个例子告诉你什么是CLR(JVM同理),以及版本兼容
查看>>
文章记录
查看>>
ESXi中的虚拟机如何使用U盘
查看>>
把别人的Tcl/Tk代码加入到Go语言里13 游戏6 消除方块
查看>>
zend studio中vim的安装
查看>>
实施微服务,我们需要哪些基础框架
查看>>
Linux 简单创建用户并指定文件夹权限
查看>>
openstack cobbler Icehouse ks 配置文件
查看>>
C++基本的数据类型
查看>>