前端必备⾃定义滚动库——iScroll 作者真的很懒,这篇⽂章从想法开始到现在都⼏个⽉了。?
iScroll是什么
很多场景,如果使⽤body的滚动会很不⽅便,这时候,就会使⽤某个元素的局部滚动,恶⼼的事情就会发⽣了。
1. pc端web,windows系统的浏览器会出现丑陋的滚动条。(其实也有最新的css样式可以解决,兼容性⽋佳)
2. ⼿机移动端,ios浏览器⽆法惯性和弹性滑动(默认使⽤浏览器滚动,⾮ios系统原⽣滚动),如果加上-webkit-overflow-scrolling:
touch;使⽤系统原⽣滚动,兼容性⽅⾯⽋佳,bug不是⼀个两个?。
3. 不利于实现⼀些个性化需求,例如加载,刷新,贴合滚动等。
巧了,iScroll解决了这些问题。
iScroll的作者是位国际友⼈,他的github飞机票。
遗憾的是,作者⼏乎不再维护这个iScroll插件,⽹上的相关中⽂⽂档很少,但是这并不影响我们拿着这个插件到处浪。
下⾯看看iScroll怎么运作的
iScroll采⽤了css3的transform动画模拟了惯性和弹性滚动的效果,效果和性能完美接近原⽣的滚动效果。同时提供了诸多功能包括⾃定义滚动条,指定滚动到元素等功能,还可以轻松实现下拉刷新,上拉加载。
iScroll的基本使⽤
⾸先肯定是先安装了
npm install iscroll
yarn add iscroll
复制代码
然后引⽤
import IScroll from 'iscroll/build/iscroll'; // 普通版
import IScroll from 'iscroll/build/iscroll-probe'; // 复杂版
import IScroll from 'iscroll/build/iscroll-infinite';
复制代码
iscroll有⼏中不同js⽂件,分别是普通本,复杂版,⽆限滚动版。这⾥常⽤的是复杂版,是⽀持实时监听滚动的位置的,如果不需要实时监听,可以⽤普通版。
初始化使⽤
这⾥以vue框架为例
<div class="wrap">
<div class="scroll-area">
<div v-for="n in 50" class="item">{{ n }}</div>
</div>
</div>
</template>
<script>
import IScroll from 'iscroll/build/iscroll-probe';
export default {
data() {
scroll: null,
},
mounted() {
// 提⽰,因为transform是对dom操作,所以需要在这个⽣命周期操作
this.scroll = new IScroll('.wrap', {
mouseWheel: true, // 允许⿏标滚轮
});
// 第⼀个参数是dom选择器,建议使⽤唯⼀性的id,这⾥以class为例
// 第⼆个参数为参数对象,是iscroll的⼀些配置
// 参数配置可以参考 wiki.jikexueyuan/project/iscroll-5/
}
}
</script>
<style>
.wrap{
height: 400px;
overflow: hidden;
/* 给滚动区域固定可滚动⾼度,并且超出隐藏 */
}
</style>
复制代码
以上代码就完成了简单的iscroll初始化使⽤,可以看下效果
iScroll刷新
注意点,由于滚动内容可能是异步获取并加载dom,如果不刷新iscroll,那么滚动功能可能会受到影响,所以当异步内容加载后,需要调⽤刷新⽅法,刷新iscroll,刷新⽅式如下
<div ref="scroll" class="wrap">
<div class="scroll-area">
<div v-for="n in 50" class="item">{{ n }}</div>
</div>
</div>
</template>
<script>
import IScroll from 'iscroll/build/iscroll-probe';
export default {
data() {
scroll: null,
},
mounted() {
const el = this.$refs.scroll;
this.scroll = new IScroll('.wrap', {
...
});
// ①异步数据刷新
getData().then(_=>{
fresh();
})
// ②⾸次滑动时刷新
el.addEventListener('touchstart', _=>fresh());
}
}
</script>
复制代码
监听位置
this.scroll = new IScroll('.wrap', {
probeType: 3, // 滚动监听级别有3档,3是像素级监听
});
// ⽤iscroll实例注册scroll事件
('scroll', e => {
// 此处不⽤箭头函数可以⽤this.x和this.y访问实时位置,⽤了箭头函数需要从实例上访问 // this.scroll.x
// this.scroll.y
})
复制代码
多的不说,看效果
html滚动效果代码注意取值的正负,监听取得的值是transform的值,确认好正负值所对应的⽅向。滚动到指定元素位置
这⾥需要使⽤iscroll的贴合功能
this.scroll = new IScroll('.wrap', {
snap: '.item',
});
// 当设置snap属性为true时,iscroll会把容器可视区域分割为⼀个page
// 当设置snap属性为元素选择器时,iscroll会把对应的元素设置为⼀个page
// 这⾥我们设置为'.item'
复制代码
然后使⽤iscroll的goToPage⽅法,跳到对应元素
ToPage(0, 30, 1000);
// 参数分别为x, y, 动画时间,
// 注意x,y是传⼊索引,第⼀个是0,类推
复制代码
也可以使⽤prev和next⽅法跳上⼀个或者下⼀个
this.scroll.prev();
();
复制代码
配置滚动条
如果想要滚动条呢,也很简单
this.scroll = new IScroll('.wrap', {
scrollbars: true, // 开启滚动条
shrinkScrollbars: 'scale', // 超出滚动时,缩放滚动条
});
复制代码
/* 因为iscroll的滚动条是定位实现,所以容器需要加⼀个相对定位 */
.wrap{
position: relative;
}
复制代码
点击事件
iscroll默认禁⽤了click事件,如果需要也可以开启
this.scroll = new IScroll('.wrap', {
click: true,
});
复制代码
并且iscroll很⼈性化的内置了tap事件,只要开启tap,就可以在元素上响应tap
this.scroll = new IScroll('.wrap', {
tap: true,
});
复制代码
<template>
<div ref="scroll" class="wrap">
<div class="scroll-area">
<div v-for="n in 50" class="item" @tap="onTap">{{ n }}</div>
</div>
</div>
</template>
复制代码
iScroll的sticky
在基于dom元素的原⽣滚动中,是可以给内容添加position: sticky来实现吸顶效果的。
吸顶: 在⽗元素的滚动过程中,如果⼦元素含有position: sticky和top: 0样式,那么该内容滚到顶部时,会吸附在⽗元素的顶部,不会继续向上滚动。(横向滚动同理)
没玩过position: sticky的,去试下就知道啦。当然这个css并不是⽆敌的,原因就是兼容性不过关。
好了,我们来说iscroll如何实现sticky,因为iscroll使⽤了transform实现滚动,所以容器设置了overflow: hidden,所以没办法⽤css的sticky实现,那么既然是⽗元素transform滚动,那么到达吸顶位置的时候,⼦元素反向transform是不是就可以了呢?
仔细看下⾯的代码呢,很重要,认真看注释
// 这段代码可以理解为是对iscroll类的扩展
// 这⾥的参数为iscroll类
export const extendSticky = (iScroll) => {
let m = Math;
// 这⾥是为了兼容性配置的浏览器css前缀,⽹络上有很多写法呢
let vendor = (/webkit/i).test(navigator.appVersion) ? 'webkit' :
(/firefox/i).test(navigator.userAgent) ? 'Moz' :
'opera' in window ? 'O' : '',
has3d = 'WebKitCSSMatrix' in window && 'm11' in new WebKitCSSMatrix(),
trnOpen = 'translate' + (has3d ? '3d(' : '('),
trnClose = has3d ? ',0)' : ')';
/**
* 这⾥开始拓展iscroll类
* @param selector 需要sticky的对象集合,包含元素和sticky的位置
* @return { iScrollStickyHeaders }
*/
// 在iscroll原型上添加 enableStickyHeaders ⽅法
ableStickyHeaders = function (selector) {
return new iScrollStickyHeaders(this, selector); // 拓展⽅法采⽤新的类并传参
};
// 参数,iscroll实例,需要sticky的元素集合
let iScrollStickyHeaders = function (iscroll, selector) {
if (!iscroll.options.useTransform) {
return;
}
this.iscroll = iscroll;
this.selector = selector;
this.initialize(); // 初始化
};
iScrollStickyHeaders.prototype = {
headers: [], // 存储需要sticky的对象集合
initialize() {
let that = this;
this._augment();
('refresh', function() {
that._refresh() // 每次iscroll刷新,sticky⽅法也刷新
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论