写了一段JS代码,实现平滑滚动至顶部
代码部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
/** * 滚动分三个阶段 * 第一阶段:加速,开始滚动并不断加速,直到滚动至文档已滚动高度的一半 * 第二阶段:减速滚动至设定的慢速滚动长度 * 第三阶段:慢速滚动,以一个更慢的速度滚动至顶部 * @param scrollToPos 滚动目标位置 * @param scrollSpeed 加速和减速滚动时的加速度 * @param scrollTotalDelay 加速和减速滚动部分总的毫秒数 * @param scrollLowTotalLen 慢速滚动长度 * @param scrollLowStepLen 慢速滚动部分每次滚动的长度 * @param scrollLowTotalDelay 慢速滚动部分总的毫秒数 */ async function scrollSmoothTo(scrollToPos, scrollSpeed, scrollTotalDelay, scrollLowTotalLen, scrollLowStepLen, scrollLowTotalDelay) { return new Promise((resolve) => { let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 当前文档滚动长度 let scrollTotalLen = Math.abs(scrollTop - scrollToPos); // 计算需要滚动的长度 let pm = (scrollTop > scrollToPos) ? 1 : -1; // 正负数标识,正数:向上滚动 负数:向下滚动 // ========= 不需要执行操作,直接滚动部分 if (Math.abs(scrollTotalLen) === 0) // 滚动长度为0 return resolve(); if (scrollTotalLen <= scrollLowStepLen) // 滚动长度小于慢速滚动步进值 { window.scrollTo(0,scrollToPos); return resolve(); } /** * 慢速滚动至设置的满滚长度 * @param len 慢速滚动的长度 * @param to 当前的位置 */ const lowTo = (len, to) => { function scrollStepByStep (delay, scrollTo) { return new Promise((resolve) => { setTimeout(() => { window.scrollTo(0, scrollTo); resolve(); }, delay); }); } let minLowStepNum = Math.round( len / scrollLowStepLen); // 计算至少需要的慢速滚动次数 let delay = Math.floor(scrollLowTotalDelay / minLowStepNum); // 延迟毫秒数 async function asyncFunc() { for (let i = 0; i < minLowStepNum; i++) { to -= scrollLowStepLen*pm; await scrollStepByStep(delay, to); } } asyncFunc().then(() => { resolve(); }) }; // ========= 直接进行慢速滚动 if (scrollTotalLen <= scrollLowTotalLen) return lowTo(scrollTotalLen, scrollTop); let speedUpProgress = true; // 是否处于加速滚动阶段 let stepSpeedUpTotalNum = Math.round(Math.sqrt(scrollTotalLen/scrollSpeed)); // 计算加速需要的滚动次数 let stepNum = 1; // 当前已执行的滚动计数, 默认值:1 (未开始滚动) let scrollStepDelay = Math.floor(scrollTotalDelay / stepSpeedUpTotalNum / 2); // 计算加速和减速阶段,每次滚动的延迟 let scrollTo = scrollTop; // 下一次滚动时,需要滚动至的位置 (默认值:scrollTop,还未开始滚动) /** * 主体滚动部分 */ const step = () => { if (speedUpProgress) speedUpProgress = (stepNum < stepSpeedUpTotalNum); scrollTo -= (stepNum * scrollSpeed) * pm; if (scrollTo*pm <= (scrollToPos + scrollLowTotalLen*pm)*pm || stepNum === 0) { // 已到达慢速滚动阶段 scrollTo = (scrollToPos + scrollLowTotalLen*pm); setTimeout(() => { window.scrollTo(0, scrollTo); // 慢速滚动至顶部 lowTo(scrollLowTotalLen, scrollTo); }, scrollStepDelay); } else { setTimeout(() => { window.scrollTo(0, scrollTo); stepNum += (speedUpProgress ? 1 : -1); step(); }, scrollStepDelay); } }; step(); }) } |
如何使用
1 2 3 4 5 6 7 8 9 10 11 |
/** * 返回顶部 */ document.querySelector('#back-to-top').addEventListener('click', function () { let scrollComplete = scrollSmoothTo(0, 3, 300, 60, 6, 100); scrollComplete.then(() => { // 滚动结束,需要做的事情。比如: 播放提示音 audioPlay_notice(); }) }) |
效果展示
本着互联网开源、开放的精神和宗旨,本站所有内容可以随便传播。如需转载或分享无需说明来源。
有任何疑问或烦恼,欢迎评论区讨论。
859
暂无回复数据