应用场景

仅仅应用于单页应用的滑动操作,用swiper4.x接管页面的滚动操作。用来支持顶部和尾部的回弹效果,进一步来支持常见那种下拉刷新动画效果。不适用于轮播图那种应用场景。

虽然只是针对swiper4.x,但相关原理,在别的框架中也是有参考意义的。

出现的问题

一、惯性动画不会在触摸时停止

快速滑动页面,手离开屏幕时产生的惯性动画还在运行时,此时触摸屏幕,动画不会停止。导致连续快速滑动页面,看起来有跳来跳去的感觉。

二、快速滑动手势大概率识别成慢滑动手势

连续快速多滑几下,有那么1、2下明显能够感知到滑动惯性动画变慢的情景,给人的感觉就是滑动不流畅。

三、惯性动画时长不合理

不管是很慢的滑动,还是很快的滑动,惯性动画时长只能设置一个固定值。慢慢移动松手后也会有一个很长的动画,快速滑的时候动画又有点短,综合看起来给人很卡的感觉。

解决手段

除了第一个问题,另外两个问题不修改swiper4.x源码似乎无法克服。

一、解决惯性动画不会在触摸时停止的问题

滑动时手离开屏幕时产生的惯性动画是css动画,并未直接提供停止动画的方法。动画还在运行时如果触摸屏幕,不改源代码,那我们就监听一下touchStart事件。

setTranslate(translate)可以移除这个动画css,需要提供页面当前的滚动位置。用getTranslate()就行了:

这与通过属性mySwiper.translate 获取到的数值稍有不同,即使是在过渡时(animating)也能获取到,而后者精度较高

解决方案代码

//在touchStart事件中执行
mySwiper.setTranslate(mySwiper.getTranslate());

二、解决快速滑动手势大概率识别成慢滑动手势问题

这个必须修改源代码才能解决,问题出在计算惯性动画起始速度时的计算参数精度不足。

原代码

if (params.freeModeMomentum) {
if (data.velocities.length > 1) {
var lastMoveEvent = data.velocities.pop();
var velocityEvent = data.velocities.pop(); //此处取值方式会导致精度不够 var distance = lastMoveEvent.position - velocityEvent.position;
var time = lastMoveEvent.time - velocityEvent.time;
swiper.velocity = distance / time;
swiper.velocity /= 2;

可以看出,他计算起始速度velocity参考的是onTouchMove最后记录的两个点,单纯取最后两个点是不可靠的,可能因为最后两次onTouchMove触发间隔比较长,导致计算出来的速度过低。从而导致偶尔会快速滑动但惯性效果是慢滑动的效果。

如果触发间隔很短,导致动画速度变快,变快了其实感知上并无区别。最要命的还是变慢,感觉很卡一样。

解决方案

一个很短的时间内,人的滑动方向不太可能会产生变化,但这个短时间内产生的滑动位移能够很好的代表手势结尾的滑动速度。

经过反复尝试,用100毫秒内的位移来计算惯性起始速度最好,100毫秒内,如果是快速滑动,会触发多次onTouchMove,计算出来的速度是很接近实际的手势速度。

问题的解决指向了100毫秒内的第一个点。解决代码:

if (params.freeModeMomentum) {
if (data.velocities.length > 1) {
//fix 惯性动画
var velos=data.velocities;
var firstEvent=velos[0];
var lastMoveEvent = velos.pop();
var velocityEvent =velos.pop();
for(var i=velos.length-1;i>=0;i--){//找出100毫秒内的起始位置
var velo=velos[i];
if(lastMoveEvent.time-velo.time>100){
break;
}
velocityEvent=velo;
} var distance = lastMoveEvent.position - velocityEvent.position;
var time = lastMoveEvent.time - velocityEvent.time;
swiper.velocity = distance / time;
swiper.velocity /= 2;

三、解决惯性动画时长不合理问题

慢滑动时惯性应该很小,动画很短;快速滑动时惯性应该很大,动画很长。swiper4.x只能提供一个固定的惯性动画时长,不改源代码是解决不了的。

原代码在第二问代码下面一点点

var momentumDuration = 1000 * params.freeModeMomentumRatio; //写死了固定动画时长

优化动画

其实也简单,小的就小,大的就大,用初始速度velocity来做乘法运算即可达到效果。

var momentumDuration = Math.abs(swiper.velocity) * 1000 * params.freeModeMomentumRatio;

结果:比原代码好很多,但跟别的app里面的滑动还是区别蛮大,慢滑时还是太快了点。

App原生滑动动画,感知上是慢的更慢,快的更快。轻微滑动慢的要死,快速动一点点,飞快。

对数曲线!1-0范围蛮符合,缓的地方比线性的还缓,陡的地方奇陡无比。在上面优化的结果基础上用对数加持一下,效果非常不错。另外限定最长动画不超过3秒。

//取对数曲线优化一下0.5-1.5倍之间,慢的越慢,快的越快
momentumDuration*=-Math.log10(Math.min(0.3,Math.max(0.03,(3000-momentumDuration)/3000)));

解决方案代码

//根据初始速度来确定惯性动画时长
var momentumDuration = Math.min(3000,Math.abs(swiper.velocity) * 1000 * params.freeModeMomentumRatio);
//取对数曲线优化一下0.5-1.5倍之间,慢的越慢,快的越快
momentumDuration*=-Math.log10(Math.min(0.3,Math.max(0.03,(3000-momentumDuration)/3000)));
momentumDuration=Math.min(3000,momentumDuration);

最终结果

应用swiper4.x修改后的单页滚动效果,已经很接近App的滚动效果,虽然还是会有些细微的抖动卡顿感,但要做到完全和App一样的流畅效果,估计蛮难,当前算是已经蛮优了。

还是iscroll省心些,但已经上了swiper4.x这条船了就算了,迁移过来又迁移过去白折腾。

改良后的滚动效果,目前[2019-02-27]号以后可以到 https://jiebian.life/start/xcx/tool_jieri 体验(这个时间之前新版本应该还没有上线),小程序和H5共用的页面。

记录一下对swiper4.x.js在H5单页中的滑动优化的更多相关文章

  1. 新手教程:不写JS,在MIP页中实现异步加载数据

    从需求谈起:在 MIP 页中异步加载数据 MIP(移动网页加速器) 的 加速原理 除了靠谱的 MIP-Cache CDN 加速外,最值得一提的就是组件系统.所有 JS 交互都需要使用 MIP 组件实现 ...

  2. 记H5单页遇到的几个ios兼容问题

    最近写一个H5活动页,安卓里的表现很不错,写下来很少出现兼容性问题,ios就不一样了,好多问题都出现在ios上(手动狗头)

  3. 前后端分离最佳实现,使用Nuxt.js快速搭建单页SSR应用

    通常我们搭建ssr应用需要自己选择多个组件集成到一起 webpack babel loaders router server-render 各种入口配置等 如果是基于vue+vuex+vue-rout ...

  4. 偏前端 - div+mui+vue.js 制作问卷调查单页 ——题目答案由后台随机给出10道

    封装的ajax获取数据.代码可能有些是多余的,没做处理!!点击提交后有弹框,在这里我没有贴出来.第一次写博客,这些也是别人教我的,经理解后,贴出来于大家分享 ——html—— <script t ...

  5. 浅谈单页应用和多页应用——Vue.js向

    浅谈单页应用和多页应用--Vue.js向 多页面 多页面应用:每次页面跳转,后台都会返回一个新的HTML文档,就是多页面应用. 在以往传统开发的应用(网站)大多都是多页面应用,路由由后端来写. 页面跳 ...

  6. HTML5单页框架View.js介绍

    什么是单页应用单页应用,是指将用户视觉上的多个页面在技术上使用一个载体来实现的应用. 换句话来讲,用户视觉效果,与技术实现的载体,并不是一定要一一对应的.采取哪种技术方案,取决于产品设计.技术组成以及 ...

  7. 纯css、js 的H5页面对接echarts

    做项目时,会遇到一些零碎的技术点.记录下来以防忘记 需求:做可视化界面,但是需要兼容ie8,需要用纯css.js 的H5页面对接echarts,下面为效果图(带定时器循环显示tooltip). 实现方 ...

  8. 前端视频直播技术总结及video.js在h5页面中的应用

    全手打原创,转载请标明出处:https://www.cnblogs.com/dreamsqin/p/12557070.html,多谢,=.=~ (如果对你有帮助的话请帮我点个赞啦) 目前有一个需求是在 ...

  9. 详细解剖大型H5单页面应用的核心技术点

    项目 Xut.js 阐述下开发中一个比较核心的优化技术点,这是一套平台代码,并非某一个插件功能或者框架可以直接拿来使用,核心代码大概是6万行左右(不包含任何插件) .这也并非一个开源项目,不能商业使用 ...

随机推荐

  1. appium + java + WebDriverAgent实现IOS app启动

    Appium v1.8.1 <dependency>    <groupId>io.appium</groupId>    <artifactId>ja ...

  2. redis_字符串对象

    Redis总共支持五种数据类型:string,hash,list,set及zset.这里介绍字符串类型的实现 首先了解字符串对象的结构 // redis对象内存分配,列出主要相关的属性 redisOb ...

  3. appium安装问题集锦

    问题一: MacBook-Air:Cellar$ npm -v dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.61.dyl ...

  4. 《java多线程编程核心技术》(一)使用多线程

    了解多线程 进程和多线程的概念和线程的优点: 提及多线程技术,不得不提及"进程"这个概念.百度百科对"进程"的解释如下: 进程(Process)是计算机中的程序 ...

  5. OC协议、代理的简单使用

    在不同类之间传递数据,我所学到的有三种,1.代理,2.block,3.通知.在这里,我们先来讲一下代理的使用,后面我会继续讲到block和通知.代理通常和协议是一起使用的,协议通常写在代理类里面,被代 ...

  6. Shell输入和输出功能-3

  7. C#-Database-连接

    using System.Data; using System.Data.SqlClient; //先打开两个类库文件 SqlConnection con = new SqlConnection(); ...

  8. CentOS 5 常见的configure error的解决方法

    仅限于CentOS 5 configure: error: No curses/termcap library found 网上有的说法是: --with-named-curses-libs=/usr ...

  9. 在Ubuntu16上安装mininet和floodlight过程,超全篇

    第一歩:更改root密码 第二歩:更新源           sudo apt-get update.sudo apt-get upgrade 第三步:安装git sudo apt install g ...

  10. jquery validate 校验使用总结

    一.jquery.validator表单验证id和name问题 因为后台是struts,表单提交,所有输入框的值保存在name=对象.名字中,而jquery.validator表单验证用的是name, ...