本文实例为大家分享了vue实现锚点定位的具体代码,供大家参考,具体内容如下

这里主要是实现了一个简单的滚动触发锚点高亮,以及点击锚点触发滚动的功能
如果是获取浏览器的滚动高度,各个浏览器有所差异,使用以下几种方式:

Chrome: document.body.scrollTop
Firefox: document.documentElement.scrollTop
Safari: window.pageYOffset

我这里是局部元素滚动,因此稍有差异。先附上html及css代码块:

scroll-content为滚动区域, operation-btn为控制锚点行为的按钮。

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

<template>

  <div class="anchor-point">

    <!-- 滚动区域 -->

    <div class="scroll-content" @scroll="onScroll">

      <div class="scroll-item" style="height: 500px;background: #3a8ee6;">一层</div>

      <div class="scroll-item" style="height: 500px;background: red;">二层</div>

      <div class="scroll-item" style="height: 500px;background: #42b983">三层</div>

      <div class="scroll-item" style="height: 1000px;background: yellow;">四层</div>

    </div>

    <!-- 按钮 -->

    <div class="operation-btn">

      <div v-for="(item, index) in ['一层','二层','三层','四层']" :key="index" @click="jump(index)"

           :style="{background: activeStep === index ? '#eeeeee' : '#ffffff'}">{{item}}

      </div>

    </div>

  </div>

</template>

<style lang="scss" scoped>

  .anchor-point {

    flex-basis: 100%;

    display: flex;

    overflow: hidden;

    .scroll-content {

      height: 100%;

      width: 90%;

      overflow: scroll;

    }

    .operation-btn {

      width: 10%;

      height: 100%;

    }

  }

</style>

通过监听滚动事件,高亮显示锚点按钮

这里是通过遍历滚动项,判断滚动条滚动距离是否大于当前项的可滚动距离(即距离其offsetParent顶部的距离,这里是body)

1

2

3

4

5

6

7

8

9

10

11

12

// 滚动触发按钮高亮

onScroll (e) {

  let scrollItems = document.querySelectorAll('.scroll-item')

  for (let i = scrollItems.length - 1; i >= 0; i--) {

    // 判断滚动条滚动距离是否大于当前滚动项可滚动距离

    let judge = e.target.scrollTop >= scrollItems[i].offsetTop - scrollItems[0].offsetTop

    if (judge) {

      this.activeStep = i

      break

    }

  }

},

添加点击事件,根据锚点滚动至对应区域并实现平滑滚动

这里参考网上的方法,将滚动距离细分为多个小段,并考虑向上向下的的滚动,实现滚动的过渡动画。
本来是打算使用scrollIntoView实现滚动动画,scrollIntoView在各个浏览器已经有很好的支持性,但是ScrollIntoViewOptions在浏览器的兼容性上还有问题,所以改用如下距离分割的方式。

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

// 点击切换锚点

jump (index) {

 let target = document.querySelector('.scroll-content')

 let scrollItems = document.querySelectorAll('.scroll-item')

 // 判断滚动条是否滚动到底部

 if (target.scrollHeight <= target.scrollTop + target.clientHeight) {

   this.activeStep = index

 }

 let total = scrollItems[index].offsetTop - scrollItems[0].offsetTop // 锚点元素距离其offsetParent(这里是body)顶部的距离(待滚动的距离)

 let distance = document.querySelector('.scroll-content').scrollTop // 滚动条距离滚动区域顶部的距离

 // let distance = document.body.scrollTop || document.documentElement.scrollTop || window.pageYOffset // 滚动条距离滚动区域顶部的距离(滚动区域为窗口)

 // 滚动动画实现, 使用setTimeout的递归实现平滑滚动,将距离细分为50小段,10ms滚动一次

 // 计算每一小段的距离

 let step = total / 50

 if (total > distance) {

   smoothDown(document.querySelector('.scroll-content'))

 } else {

   let newTotal = distance - total

   step = newTotal / 50

   smoothUp(document.querySelector('.scroll-content'))

 }

 // 参数element为滚动区域

 function smoothDown (element) {

   if (distance < total) {

     distance += step

     element.scrollTop = distance

     setTimeout(smoothDown.bind(this, element), 10)

   } else {

     element.scrollTop = total

   }

 }

 // 参数element为滚动区域

 function smoothUp (element) {

   if (distance > total) {

     distance -= step

     element.scrollTop = distance

     setTimeout(smoothUp.bind(this, element), 10)

   } else {

     element.scrollTop = total

   }

 }

 // document.querySelectorAll('.scroll-item').forEach((item, index1) => {

 //   if (index === index1) {

 //     item.scrollIntoView({

 //       block: 'start',

 //       behavior: 'smooth'

 //     })

 //   }

 // })

}

Logo

前往低代码交流专区

更多推荐