Skip to content

Repository files navigation

any-scroll NPM VersionNPM Downloadssize-image

模拟滚动插件,支持滚轮和手势, 手势识别基于any-touch.

概念(wrap/content)

any-scroll的滚动实际是通过2个"父子div"的相对位置变化模拟的, 默认使用translate3d, 外层div叫"wrap", 里面用来装载内容的div叫"content".

<div><!-- warp --><div><!-- content -->
content
</div></div>

GIF

⚡⚡⚡ 多个content

如果wrap下有多个元素, 那么any-scroll会把他们都构造成content实例, 但是只有一个"激活"状态的content实例, 只有他可以响应滚动, 当然你也可以切换任意content实例为激活.

<!-- warp --><div><!-- content --><div>content-1<div><!-- content --><divstyle="position: absolute;z-index:1;top:0;left:0;">
content-2
<div><!-- content --><divno-scroll>content-3<div></div>

注意:

  1. 多个content情况下, 请给第二个子元素做一个"初始定位", 比如style="position: absolute;z-index:1;top:0;left:0;", any-scroll内部没有默认定位, 这样你可以自定义"位置"和"层级".
  2. 如果不想某个子元素(content)"可滚动", 使用"no-scroll"进行标记.

🚀返回目录

目录

安装

npm i any-scroll -S

🚀返回目录

使用

首先在页面构造如下html结构, 同时给wrap一个固定尺寸.

<divid="scroll-view" style="height:600px;width:360px;"><!-- wrap --><div><!-- content --><!-- 你的内容写在这里 --><div></div>

初始化:

importAnyScrollfrom'any-scroll';constel=document.getElementById('scroll-view');constas=newAnyScroll(el);// 滚动到x=-100,y=-100的位置.as.scrollTo([-100,-100]);// 只控制Y轴,1s内滑动到目标位置as.scrollTo({y:-100},1000);

🚀返回目录

API

选项

名称默认值说明
allow[true,true]是否允许X或Y轴滚动,数组第一位控制X轴
damping0.1dampScroll的消损系数,范围0~1
overflowDistance100允许超过边界的最大距离,单位"px"
render查看控制content元素位置变化的函数

render

默认通过translate3d控制content的位移, 如有需要也可改为控制margintop(left) 属性.

// 默认functionrender(el,[x,y]){el.style.setProperty('transform',`translate3d(${x}px, ${y}px,0)`);}// 或者改为functionrender(el,[x,y]){el.style.setProperty('marginLeft',x+'px');el.style.setProperty('marginTop',y+'px');}constas=newAnyScroll({render});

🚀返回目录

实例方法

on

监听事件, 默认继承了any-touch的所有手势事件.

事件名说明
scroll每次滚动
scroll-end滚动停止
tap单击
press按压
pan拖拽
swipe快滑
rotate旋转
pinch缩放
as.on('scroll-end',()=>{console.log('滚动停止了');})

🚀 返回目录

scrollTo

滚动到指定位置, 支持时间动画

参数
参数名参考值是否可选说明
distXY[-100,-200]{x:-100,y:-200}必选目标位置
duration1000可选滚动时间,单位毫秒
easing参考可选缓动动画函数, 一般不需要修改
// 3秒钟移动到x=-100,y=-500的位置.as.scrollTo([-100,-500],3000);// 等价写法as.scrollTo({x:100,y:-500},3000);

🚀 返回目录

moveTo

瞬间移动到目标位置

参数名参考值是否可选说明
distXY[-100,-200]{x:-100,y:-200}必选目标位置
as.moveTo([-100,-200]);

🚀 返回目录

scrollToElement

移动元素到wrap左上角.

参数
参数名参考值是否可选说明
elDOM元素必选目标元素
offset[0,0]{x:0,y:0}可选对目标位置修正, 多滚动的距离
duration1000可选滚动时间,单位毫秒
easing参考可选缓动动画函数, 一般不需要修改
// 滚动到content中的子元素(child-1), 让其左上角和wrap的左上角重合.constchildEl=doucument.getElementById('child-1');as.scrollToElement(childEl);// 滚动到child-1下方100px的位置as.scrollToElement(childEl,{y:100});// 等价写法as.scrollToElement(childEl,[,100]);

🚀 返回目录

dampScroll

作用同scrollTo,只是滚动效果不同, 其不能指定时间. 仅供插件开发者使用, 模拟快速划动scrollView产生的滚动.

参数
参数名参考值是否可选说明
distXY[-100,-200]{x:-100,y:-200}必选目标位置
damping默认0.1, 范围0~1可选不断靠近目标位置,每次靠近剩余距离的0.1倍.
as.dampScroll([-100,-200]);

🚀 返回目录

update

如果滚动范围出现异常, 可手动更新.

as.update();

🚀 返回目录

getContentRef

获取content实例, 其上有尺寸等数据.

参数
参数名参考值是否可选说明
elOrIndexnumber或HTML元素可选查看 ↓
elOrIndex不同的值
  1. 如是number, 那么会按照wrap下的子元素索引取对应的content实例.
  2. 如是元素, 那么会递归向上找父元素, 直到找到对应的实例.
  3. 如果不传默认找当前激活状态的content实例.
as.getContentRef(1);as.getContentRef(childEl);as.getContentRef();
返回值

content实例或null.

🚀 返回目录

active

如果有多个content实例, 激活指定content实例, 只有激活的content才会响应滚动.

参数
参数名是否可选
contentRef必选
// 激活第二个content实例.constcontentRef=as.getContentRef(1);as.active(contentRef);

🚀 返回目录

实例属性

el

wrap元素

as.el;// <div class="any-scroll"></div>

🚀返回目录

at

any-scroll内部使用了any-touch手势库, 通过as.at可以访问any-touch的实例,从而修改手势行为等, 详情参考any-touch

// 仅对表单元素阻止触发"默认事件"// 这是any-touch参数的默认值, 在此仅做展示as.at.set({preventDefault(e){if(event.target&&'tagName'inevent.target){const{ tagName }=event.target;return!/^(?:INPUT|TEXTAREA|BUTTON|SELECT)$/.test(tagName);}returnfalse;}})

注意: 普通开发者谨慎使用, 修改不当会影响滚动效果, 如开发中遇到缺少功能, 大家尽量先提Issue

🚀返回目录

size

wrap元素尺寸.

console.log(as.size);

🚀返回目录

事件

as.on('scroll',context=>{// 当前位置信息// context === asconsole.log(context.xy);});
事件名称说明
scroll滚动
scrollEnd滚动结束
tap单击
press按压
pressup按压释放
pan拖拽
swipe滑动
pinch缩放
rotate旋转

除了"scroll"和"scroll-end", 其他事件都是any-touch实现的, 其事件对象上包含当前触点/距离/速度等信息, 更多请参考any-touch

as.on('tap',e=>{// 当前触点x坐标console.log(e.x)})

🚀返回目录

进阶使用

支持更多手势

any-scroll基于any-touch开发, 所以也支持他的所有手势, 但是为了体积默认只加载了swipe/pan, 开启更多方法:

importAScrollfrom'any-scroll';importtapfrom'@any-touch/tap';importswipefrom'@any-touch/swipe';importpinchfrom'@any-touch/pinch';importrotatefrom'@any-touch/rotate';constas=newAScroll();// 加载单击手势as.at.use(tap);// 加载快划as.at.use(swipe);// 加载缩放as.at.use(pinch);// 加载旋转as.at.use(rotate);as.on('tap',e=>{});

🚀返回目录

常见问题

no-scroll

如果wrap下的子元素, 有些你并不想让他"滚动", 可以给其加"no-scroll"标记.

<div><div></div><!-- 能滚动 --><divno-scroll></div><!-- 不能滚动 --></div>

🚀返回目录

监视内容变化

当content中的子元素发生变化(增/减去/尺寸), any-scroll需要重新计算"可滑动范围".

默认any-scroll内部使用ResizeObserver(caniuse)监视wrap/content尺寸变化, 实现自动更新可滑动范围.

image

但其兼容性较差, 所以在不支持ResizeObserver的浏览器会使用MutationObserver(caniuse)降级兼容, 其只能监视content的子元素的增/减, 从而更新滑动范围. image

resize-observer-polyfill

如果不在意体积, 可以使用"resize-observer-polyfill", 其可让ResizeObserver兼容到最低IE9.

importResizeObserverfrom'resize-observer-polyfill';// ⭐注入到全局window.ResizeObserver=ResizeObserver;importAnyScrollfrom'any-scroll';constas=newAnyScroll(el);
手动更新

使用实例上的"update"方法更新"可滑动范围".

🚀返回目录

About

🚀 模拟scrollview, 支持pc/移动端, 让实现Tab/Slider等组件轻而易举.

Topics

Resources

Stars

55 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages