p-seamless-scroll 是一个创建无缝滚动效果的 js 插件。它有着轻量且高效的特性,支持丰富的自定义配置选项,它能够帮助你快速创建无缝滚动效果
示例代码
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width" />
<meta name="format-detection" content="telephone=no" />
<meta name="format-detection" content="email=no" />
<meta name="format-detection" content="address=no">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<title>无缝滚动</title>
<style type="text/css">
#box {
width: 800px;
margin: 0 auto;
height: 800px;
overflow: auto;
border: 2px solid #f00;
}
.box-body {
width: 700px;
height: 300px;
margin: 40px;
background: #ccc;
font-size: 50px;
line-height: 300px;
text-align: center;
}
#div {
width: 800px;
margin: 0 auto;
}
</style>
</head>
<body>
<div id="box">
<div class="box-body">1</div>
<div class="box-body">2</div>
<div class="box-body">3</div>
<div class="box-body">4</div>
</div>
<div id="div">
<button onclick="play()">开始滚动</button>
<button onclick="pause()">暂停滚动</button>
<button onclick="reload()">重载配置</button>
<button onclick="destroy()">销毁滚动</button>
</div>
<script src="p-seamless-scroll.umd.js"></script>
<script type="text/javascript">
// 假设已经有一个滚动容器的 DOM 元素,ID 为 'box'
var box = document.getElementById("box");
// 实例化 pSeamlessScroll
var ps = new pSeamlessScroll({
el: box,
speed: 200
});
// 开始滚动。如果配置自动开始滚动则初始化后无需调用此方法
function play() {
ps.play();
}
// 暂停滚动。
function pause() {
ps.pause();
}
// 重载配置。接受一个配置对象 e,并更新当前实例的配置。
function reload() {
ps.reload();
}
//销毁滚动实例,清除定时器并释放资源。
function destroy() {
ps.destroy();
}
</script>
</body>
</html>
p-seamless-scroll.umd.js 文件
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).pSeamlessScroll=t()}(this,(function(){"use strict";function e(e,t){return"down"==e.config.direction||"up"==e.config.direction?t.offsetHeight:"left"==e.config.direction||"right"==e.config.direction?t.offsetWidth:0}function t(e){"up"==e.config.direction||"down"==e.config.direction?e.el.firstElementChild.animate({transform:"translate(0px, "+e.distance+"px)"},{duration:0,fill:"forwards"}):"left"!=e.config.direction&&"right"!=e.config.direction||e.el.firstElementChild.animate({transform:"translate("+e.distance+"px, 0px)"},{duration:0,fill:"forwards"})}function i(e,i){!function n(){if(e.state.isPause)return;if("up"==i.config.direction||"left"==i.config.direction)if(Math.abs(i.distance)>=i.contentDistance){if(i.distance=0,t(i),!i.config.loop)return void(e.state.isPause=!0);n()}else if(i.contentDistance-Math.abs(i.distance)<i.step){let e=(i.contentDistance-Math.abs(i.distance))/i.step*i.config.speed;i.distance=-i.contentDistance,o(e)}else i.distance-=i.step,o(i.config.speed);else if("down"==i.config.direction||"right"==i.config.direction)if(i.distance>=0){if(i.distance=-i.contentDistance,t(i),!i.config.loop)return void(e.state.isPause=!0);n()}else if(Math.abs(i.distance)<i.step){let e=Math.abs(i.distance)/i.step*i.config.speed;i.distance=0,o(e)}else i.distance+=i.step,o(i.config.speed);function o(t){i.config.rest&&(i.restDistance+=i.step*t/i.config.speed,function(e,t,i){t.restDistance>=t.config.rest.distance&&(t.restDistance=0,e.state.isPause=!0,t.restTimer&&clearTimeout(t.restTimer),t.restTimer=setTimeout((()=>{e.state.isPause=!1,i()}),t.config.rest.time))}(e,i,n)),function(e,t){"up"==e.config.direction||"down"==e.config.direction?e.el.firstElementChild.animate({transform:"translate(0px, "+e.distance+"px)"},{duration:t,fill:"forwards"}):"left"!=e.config.direction&&"right"!=e.config.direction||e.el.firstElementChild.animate({transform:"translate("+e.distance+"px, 0px)"},{duration:t,fill:"forwards"})}(i,t),i.timer&&clearTimeout(i.timer),i.timer=setTimeout((()=>{n()}),t)}}()}function n(t,n){if(function(e){if(!e.el||!e.el instanceof HTMLElement)return console.error("ErrCode:101"),!1;if(e.raw_el=e.el.innerHTML,!e.config.directionList.includes(e.config.direction))return console.error("ErrCode:102"),!1;if(e.config.speed<1||e.config.speed>1e5)return console.error("ErrCode:103"),!1;if(e.config.loop&&1!=e.config.loop&&0!=e.config.loop)return console.error("ErrCode:104"),!1;if(e.config.hoverStop&&1!=e.config.hoverStop&&0!=e.config.hoverStop)return console.error("ErrCode:105"),!1;if(e.config.auto&&1!=e.config.auto&&0!=e.config.auto)return console.error("ErrCode:106"),!1;if(e.config.rest){if(!e.config.rest.distance||e.config.rest.distance<10||e.config.rest.distance>1e5||e.config.rest.distance%10!=0)return console.error("ErrCode:107-1"),!1;if(!e.config.rest.time||e.config.rest.time<1||e.config.rest.time>1e5)return console.error("ErrCode:107-2"),!1}return!0}(n)){if(function(e,t){e.state={isHover:!1,isPause:!1},t.timer=null,t.restTimer=null,t.isHoverShield=!1,t.contentDistance=0,t.viewDistance=0,t.step=10,t.distance=0,t.restDistance=0,t.isInit=!1}(t,n),function(e){let t=document.createElement("div");t.style.display="inline-flex","up"!=e.config.direction&&"down"!=e.config.direction||(t.style.flexDirection="column"),t.append(...e.el.children),e.el.append(t),t=null}(n),n.contentDistance=e(n,n.el.firstElementChild),n.viewDistance=e(n,n.el),n.contentDistance<n.viewDistance)return console.error("ErrCode:108");if(n.viewDistance<n.step)return console.error("ErrCode:109");!function(t){let i=t.el.firstElementChild.children.length,n=0;for(let o=0;o<i&&(n+=e(t,t.el.firstElementChild.children[o]),t.el.firstElementChild.append(t.el.firstElementChild.children[o].cloneNode(!0)),!(n>=t.viewDistance));o++);}(n),function(e,t,i){function n(e,t){let i;return function(){const n=this,o=arguments;clearTimeout(i),i=setTimeout((function(){e.apply(n,o)}),t)}}t.el.onmouseover=n((()=>{e.state.isHover||(e.state.isHover=!0,t.isHoverShield||t.config.hoverStop&&(e.state.isPause=!0,i()))}),100),t.el.onmouseout=n((()=>{e.state.isHover&&(e.state.isHover=!1,t.isHoverShield||t.config.hoverStop&&(e.state.isPause=!1,i()))}),100)}(t,n,(()=>{i(t,n)})),n.isInit=!0,n.config.auto&&i(t,n),function(e,t){e.state=new Proxy(e.state,{set:function(e,i,n){e[i]=n;for(let e=0;e<t.watchs.length;e++){let{ks:o,f:r}=t.watchs[e];o==i&&r(n)}return e}})}(t,n)}}function o(e){if(!e.isInit)return console.error("ErrCode:110");e.isInit=!1,e.el.innerHTML=e.raw_el,e.timer&&clearTimeout(e.timer),e.restTimer&&clearTimeout(e.restTimer),e.config.hoverStop&&e.el.onmouseover&&(e.el.onmouseover=null,e.el.onmouseout=null)}return class{constructor(e){let t={el:e.el,raw_el:null,config:{direction:e.direction||"up",directionList:["up","down","left","right"],hoverStop:!1!==e.hoverStop,speed:e.speed||100,auto:!1!==e.auto,loop:!1!==e.loop,rest:e.rest||null},timer:null,restTimer:null,isHoverShield:!1,contentDistance:0,viewDistance:0,step:10,distance:0,restDistance:0,isInit:!1,watchs:[]};this.state={isHover:!1,isPause:!1},this.play=()=>{!function(e,t){if(!t.isInit)return console.error("ErrCode:110");e.state.isPause=!1,t.isHoverShield=!1,i(e,t)}(this,t)},this.pause=()=>{!function(e,t){if(!t.isInit)return console.error("ErrCode:110");e.state.isPause=!0,t.isHoverShield=!0}(this,t)},this.reload=e=>{if(o(t),e)for(let i in e)"el"!=i&&(t.config[i]=e[i]);n(this,t)},this.destroy=()=>{o(t)},this.getState=()=>this.state,this.on=(e,i)=>{"hover"==e?t.watchs.push({es:e,ks:"isHover",f:i}):"pause"==e&&t.watchs.push({es:e,ks:"isPause",f:i})},this.off=e=>{let i=t.watchs.filter((t=>t.es!==e));t.watchs=i},n(this,t)}}}));
p-seamless-scroll 说明
基础配置
el: 滚动容器的 DOM 元素。
direction: 滚动方向,可选值包括 'up' (默认) 、 'down' 、 'left' 、 'right'。
speed: 滚动速度,以毫秒为单位,默认为 100。
hoverStop: 是否在鼠标移入时停止滚动,默认为 true。
auto: 是否自动开始滚动,默认为 true。
loop: 是否循环滚动,默认为 true。
rest: 在滚动一段距离后停留一段时间,默认为 null,例如{distance: 100, time: 2000}。
distance: 停留前滚动的距离,以 px 为单位,必须为 10 的整数倍,默认为 100。
time: 停留的时间,以毫秒为单位,默认为 2000。
属性
state: 对象的状态信息,包含以下属性:
isHover: 是否鼠标移入滚动容器。
isPause: 是否暂停滚动。
方法
play(): 开始滚动。如果配置自动开始滚动则初始化后无需调用此方法。
pause(): 暂停滚动。
reload(e): 重载配置。接受一个配置对象 e,并更新当前实例的配置。
destroy(): 销毁滚动实例,清除定时器并释放资源。
getState(): 获取当前状态对象。
事件监听
on(event, callback): 监听事件。event 可以是以下值:
hover: 鼠标移入或移出滚动容器时触发。
pause: 滚动暂停或继续时触发。
off(event): 移除事件监听。event 可以是以下值:
hover
pause
错误码
101
请挂载正确的 el 元素!例如:document.getElementById("id")。
102
请配置正确的 direction 滚动方向!可选值包括 'up' (默认) 、 'down' 、 'left' 、 'right'。
103
请配置正确的 speed 滚动速度!可选值在 1-100000 之间。
104
请配置正确的 loop 是否循环滚动!可选值包括 true、false。
105
请配置正确的 hoverStop 是否鼠标移入停止!可选值包括 true、false。
106
请配置正确的 auto 是否自动滚动!可选值包括 true、false。
107
请配置正确的 rest 是否在滚动一段距离后停留一段时间!可选值包括 null、{distance: 100, time: 2000}。
107-1: 请配置正确的 rest.distance 停留前滚动距离!可选值在 10-100000 之间 10 的整数倍。
107-2: 请配置正确的 rest.time 停留时间!可选值在 1-100000 之间。
108
滚动元素长度小于滚动视口长度,无需开启滚动。
109
滚动视口长度小于 10px,无需开启滚动。
110
实例已销毁或未完成初始化,无法执行此方法,请先初始化实例或执行 reload() 重载配置。