应用场景

仅仅应用于单页应用的滑动操作,用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. mysql几种中间件对比

    网上找到的图 重点比较几个 1.atlas 基于mysql-proxy,360团队 优点: 配置简单,支持读写分离 缺点: 年份久,功能有限 地址:https://github.com/Qihoo36 ...

  2. opencv2.4.13+python2.7学习笔记--使用 knn对手写数字OCR

    阅读对象:熟悉knn.了解opencv和python. 1.knn理论介绍:算法学习笔记:knn理论介绍 2. opencv中knn函数 路径:opencv\sources\modules\ml\in ...

  3. python学习,excel操作之xlsxwriter常用操作

    from datetime import datetime import xlsxwriter #打开文件 workbook = xlsxwriter.Workbook('Expenses03.xls ...

  4. CentOS开启telnet服务

    原文地址:https://blog.csdn.net/zhujiangm/article/details/4540778 服务器:CentOS-5.1(192.168.1.87)客户机:FC6(192 ...

  5. Python之路【第四篇】Python基础2

    一.格式化输出 按要求输出信息 name=input("name:") age=int(input("age:")) job=input("job:& ...

  6. 获取resource下文件

    Resource resource = new ClassPathResource(certPath);File file= resource.getFile();

  7. JavaScript的文档对象模型DOM

    小伙伴们之前我们讲过很多JavaScript的很多知识点,可以点击回顾一下: <JavaScript大厦之JS运算符>: <JavaScript工作原理:内存管理 + 如何处理4个常 ...

  8. Android 基本控件相关知识整理

    Android应用开发的一项重要内容就是界面开发.对于用户来说,不管APP包含的逻辑多么复杂,功能多么强大,如果没有提供友好的图形交互界面,将很难吸引最终用户.作为一个程序员如何才能开发出友好的图形界 ...

  9. JavaCV 学习(二):使用 JavaCV + FFmpeg 制作拉流播放器

    一.前言 在 Android 音视频开发学习思路 中,我们不断的学习和了解音视频相关的知识,随着知识点不断的学习,我们现在应该做的事情,就是将知识点不断的串联起来.这样才能得到更深层次的领悟.通过整理 ...

  10. Javascript高级编程学习笔记(71)—— 模拟事件(1)DOM事件模拟

    事件,指的是网页中某个特定的交互时刻 一般来说事件由浏览器厂商负责提供,一般由用户操作或者其它浏览器功能来触发 但是有一类特殊的事件,那就是由我们开发人员通过JS触发的事件 这些事件和浏览器创建的事件 ...