应用场景

仅仅应用于单页应用的滑动操作,用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. LwIP-网络接口管理

    netif      各种类型网络接口的抽象------------------netif.c  netif.h ————netif.h————————————————//网络接口最大物理地址长度,这 ...

  2. python 中爬虫 content和text的区别

    一直在想requests的content和text属性的区别,从print 结果来看是没有任何区别 import requests headers = { "User-Agent" ...

  3. 可遇不可求的Question之Sqlserver2005文件组的迁移篇

    Sqlserver2005 文件组的折腾 问题:由于数据庞大,我在数据库里面使用了分区表,建了很多文件组,一个分区对应一个文件组,一个文件组只有一个文件.我在建分区表的时候,在数据库属性里面“文件”选 ...

  4. hdu 1052 Tian Ji -- The Horse Racing【田忌赛马】

    题目 这道题主要是需要考虑到各种情况:先对马的速度进行排序,然后分情况考虑: 1.当田忌最慢的马比国王最慢的马快则赢一局 2.当田忌最快的马比国王最快的马快则赢一局 3.当田忌最快的马比国王最快的马慢 ...

  5. Android中监控USB的插拔

    一.需求 在Android应该开发过程中,用到了USB通讯,需要应用监控USB设备的插入和拔出,从而刷新USB设备列表. 二.实现 在使用时,需要register和unregister. 通过UsbD ...

  6. 利用正则+requests爬取猫眼电影信息

    import json # from multiprocessing import Pool import requests from requests.exceptions import Reque ...

  7. Vue实现懒加载的基本思路

    懒加载是前端开发者的基本功之一.实现懒加载肯定是要直接操作DOM的,这个没得跑,但我们可以想办法让流程尽可能优雅些. 基本结构 父组件是列表容器,子组件是列表中的项,如卡片.帖子等,承载图片的DOM对 ...

  8. 笔记:Zygote和SystemServer进程启动过程

    简述 Android设备启动过程中,先是Linux内核加载完,接着Android中的第一个进程init启动,它会启动一些需要开机启动的进程. Zygote就是进程init启动起来的.Android中所 ...

  9. Android开发 - 掌握ConstraintLayout(七)辅助线(Guideline)

    了解过UI设计的同学都知道,在设计的时候,我们经常在界面上拖进一些辅助线来帮我们对齐UI元素,或者方便我们统一的页边距. 在ConstraintLayout的编辑器中,同样也支持这样的功能,我们可以创 ...

  10. 调皮的程序员:Linux之父雕刻在Linux内核中的故事

    本文内容由公众号“格友”原创分享. 1.引言   (不羁的大神,连竖中指都这么帅) 因为LINUX操作系统的流行,Linus 已经成为地球人都知道的名人.虽然大家可能都听过钱钟书先生的名言:“假如你吃 ...