zoukankan      html  css  js  c++  java
  • vue2.0模拟锚点实现定位平滑滚动

    vue2.0模拟锚点实现定位平滑滚动

      效果为点击哪一个标题,平滑滚动到具体的详情。

      如果是传统项目,这个效果就非常简单。但是放到 Vue 中,就有两大难题:

      1. 在没有 jQuery 的 animate() 方法的情况下,如何实现平滑滚动?

      2. 如何监听页面滚动事件?

      进行多次尝试之后,终于解决了这些问题

      期间主要涉及到了 setTimeout 的递归用法,和 Vue 生命周期中的 mounted

      首先导航处

    <h3 class="current"><a href="javascript:;" class="button" @click="jump(0)">产品详情</a></h3>
                        <h3><a href="javascript:;" class="button" @click="jump(1)">预定须知</a></h3>
                        <h3><a href="javascript:;" class="button" @click="jump(2)">费用明细</a></h3>
                        <h3><a href="javascript:;" class="button" @click="jump(3)">温馨提示</a></h3>

      添加一个 jump 方法

    jump (index) {
        let jump = document.querySelectorAll('.d_jump')
    // 获取需要滚动的距离
        let total = jump[index].offsetTop
        // Chrome
        document.body.scrollTop = total
        // Firefox
    document.documentElement.scrollTop = total
    // Safari
    window.pageYOffset = total
    },

    通过 offsetTop 获取对象到窗体顶部的距离,然后赋值给 scrollTop,就能实现锚点的功能

    需要注意的是,各浏览器下获取 scrollTop 有所差异

    Chrome: document.body.scrollTop

    Firefox: document.documentElement.scrollTop

    二、平滑滚动

    将总距离分成很多小段,然后每隔一段时间跳一段

    只要每段的时间足够短,频次足够多,在视觉上就是正常的平滑滚动了

    实际情况下,得考虑向上滚动和向下滚动两种情况,完整的代码为:

            /**
                * 锚点连接平滑滚动
                **/
                jump(index){
                    // 用 class="instance_title" 添加锚点
                    let jump = document.querySelectorAll('.instance_title');
                    let total = jump[index].offsetTop;
                    let distance = document.documentElement.scrollTop || document.body.scrollTop;
                    // 平滑滚动,时长500ms,每10ms一跳,共50跳
                    let step = total / 50;
                    if (total > distance) {
                        smoothDown();
                    } else {
                        let newTotal = distance - total;
                        step = newTotal / 50;
                        smoothUp();
                    }
                    function smoothDown () {
                        if (distance < total) {
                            distance += step;
                         document.body.scrollTop = distance;
                            document.documentElement.scrollTop = distance;
                            setTimeout(smoothDown, 10);
                        } else {
                            document.body.scrollTop = total;
                            document.documentElement.scrollTop = total;
                        }
                    }
                    function smoothUp () {
                        if (distance > total) {
                            distance -= step;
                        document.body.scrollTop = distance;
                            document.documentElement.scrollTop = distance;
                            setTimeout(smoothUp, 10);
                        } else {
                            document.body.scrollTop = total;
                            document.documentElement.scrollTop = total;
                        }
                    } 
                },

    三、修改锚点状态

    在上面展示的效果中,当页面滚动的时候,锚点的激活状态会有相应的改变

    其实这个效果并不难,只需要监听页面滚动事件,然后根据滚动条的距离修改锚点状态就可以了

    但是在 Vue 中,应该在什么地方监听滚动事件呢?

    mounted: function () {
        this.$nextTick(function () {
          window.addEventListener('scroll', this.onScroll)
        })
      },
      methods: {
        onScroll () {
          let scrolled = document.documentElement.scrollTop || document.body.scrollTop
        // 586、1063分别为第二个和第三个锚点对应的距离
          if (scrolled >= 1063) {
            this.steps.active = 2
          } else if (scrolled < 1063 && scrolled >= 586) {
            this.steps.active = 1
          } else {
            this.steps.active = 0
          }
        }
      }

    上面的代码中,我先写了一个修改锚点状态的方法 onScroll,然后在 mounted 中监听 scroll 事件,并执行 onScroll 方法

    mounted 是 Vue 生命周期中的一个状态,在这个状态下,$el (vue 实例的根元素)已经创建完毕,但还没有加载数据

    从结果上看,也可以在 created 状态下监听 scroll 事件

    扩展:页面的平缓返回顶部

    scrollTop() {
                let distance = document.documentElement.scrollTop || document.body.scrollTop;
                let step = distance / 50;
                let total = 0;
                if (total < distance) {
                    let newTotal = distance - total;
                    step = newTotal / 50;
                    smoothUp();
                }
                function smoothUp () {
                    if (distance > 1) {
                        distance -= step;
                    document.body.scrollTop = distance;
                        document.documentElement.scrollTop = distance;
                        setTimeout(smoothUp, 10);
                    } else {
                        document.body.scrollTop = 1;
                        document.documentElement.scrollTop = 1;
                    }
                } 
            }
  • 相关阅读:
    免费的视频、音频转文本
    Errors are values
    Codebase Refactoring (with help from Go)
    Golang中的坑二
    Cleaner, more elegant, and wrong(msdn blog)
    Cleaner, more elegant, and wrong(翻译)
    Cleaner, more elegant, and harder to recognize(翻译)
    vue控制父子组件渲染顺序
    computed 和 watch 组合使用,监听数据全局数据状态
    webstorm破解方法
  • 原文地址:https://www.cnblogs.com/haonanZhang/p/9517636.html
Copyright © 2011-2022 走看看