js 实现滚动动画到指定元素位置 您所在的位置:网站首页 js滚动动画 js 实现滚动动画到指定元素位置

js 实现滚动动画到指定元素位置

#js 实现滚动动画到指定元素位置| 来源: 网络整理| 查看: 265

总流程图

滚动动画总流程.png

主要步骤是获取需要滚动到位置元素的顶部距离,然后使用 ELement 的 scrollTo 方法滚动到指定位置。

详细流程图

滑动流程图详细.png

(1)首先对滚动容器进行获取,没有传入滚动元素 scrollerid 或获取不到 scrollerid 的 ELement 节点则使用 body 作为滚动的容器进行滚动。

(2)获取滚动容器的 scrollTop 和元素的 offsetTop 进行大小对比,判断是向上还是向下滚动。

(3)window.requestAnimationFrame 设置的滚动动画每一帧都会传入当前的时间戳,根据(和第一帧时间戳的差值 / 动画的时间)* |scrollTop - offsetTop|来获取每一帧的滚动位置。

(4)判断和第一帧时间戳的差值 - 动画的时间 >= 0来判断动画时间是不是已经到了,否则动画会一直执行。

(5)当判断到动画时间结束,需要补上最后一帧的动画,原因是当使用和第一帧时间戳的差值 - 动画的时间 >= 0判断最后一帧的动画,可能出现最后一帧和第一帧差值 !== 动画的时间 && 下一帧和第一帧的差值 〉 动画的时间,就会导致其实有几毫秒的距离是没有滚动的。这个时候需要补上真正的最后一帧的滚动动画。

具体代码 export const scrollTo = (params = {}) => { const baseConfig = { duration: 500, // 滚动的动画的时间 scroller: '', // 滚动容器的 id ,默认为 body id: '', // 滚动到指定位置的元素 id }; const config = { ...baseConfig, ...params, }; const { id, duration, scroller } = config; const ele = document.getElementById(id); if (ele) { const { scrollTop, scrollerOffsetTop } = getScrollTop(scroller); // 需要减去滚动容器到顶部的距离,默认滚动容器是 body ,scrollerOffsetTop 的值为 0 const offsetTop = ele.offsetTop - scrollerOffsetTop; let start; let timeOff = false; const scrollFrame = (timestramp) => { if (start === undefined) { start = timestramp; } const elapsed = timestramp - start; const offset = getOffset({ scrollTop, offsetTop, elapsed, duration, }); if (duration - elapsed >= 0) { window.requestAnimationFrame(scrollFrame); scolling(scroller, offset); } else { // 最后一帧因为时间判断可能不会执行,补上最后一帧 if (!timeOff) { scolling(scroller, offsetTop); timeOff = true; } } }; window.requestAnimationFrame(scrollFrame); } }; const getScrollTop = (scrollerTag) => { let scrollTop; let scrollerOffsetTop = 0; // 滚动容器距离 body 顶部的距离 const ele = document.getElementById(scrollerTag); if (ele) { scrollTop = ele.scrollTop; scrollerOffsetTop = ele.offsetTop; } else { scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop; } return { scrollTop, scrollerOffsetTop }; }; const getOffset = (data) => { const { scrollTop, offsetTop, elapsed, duration } = data; let offset; // 判断是向下还是向上滚动 if (scrollTop > offsetTop) { offset = scrollTop - (elapsed / duration) * (scrollTop - offsetTop); } else { offset = scrollTop + (elapsed / duration) * (offsetTop - scrollTop); } return offset; }; const scolling = (scrollerTag, offset) => { const scroller = getScroller(scrollerTag); scroller.scrollTo(0, offset); }; const getScroller = scrollerTag => document.getElementById(scrollerTag) || window; 复制代码 示例 vue 文件 {{ item }} {{ item }} import { scrollTo } from './secoll'; export default { data() { return { selectList: ['1', '2', '3', '4'], colorList: ['black', 'white', 'blue', 'green'], baseId: 'scroller-child_', }; }, methods: { handleScroll(item) { scrollTo({ id: this.baseId + item, // 注释掉不是 body 为滚动容器 // scroller: 'scroller', }); }, }, }; .select-list { display: flex; justify-content: space-around; flex-direction: row; font-size: 24px; position: fixed; top: 0; width: 100%; } .scroller { margin-top: 40px; // 注释掉不是 body 为滚动容器 // max-height: 600px; // overflow-y: scroll; } .scroller-child { margin: 0 20px 20px 20px; border: 1px solid olivedrab; height: 1550px; } 复制代码


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有