vue中实现锚点定位以及平滑滚动到指定位置

这里主要是实现了一个简单的滚动触发锚点高亮,以及点击锚点触发滚动的功能

如果是获取浏览器的滚动高度,各个浏览器有所差异,使用以下几种方式:
Chrome: document.body.scrollTop
Firefox: document.documentElement.scrollTop
Safari: window.pageYOffset

//scroll-content为滚动区域, operation-btn为控制锚点行为的按钮。
<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>
<script>
export default {
	data() {
		 return {
		 	activeStep:0
		 }
	},
 	methods: {
 		//通过监听滚动事件,高亮显示锚点按钮
		//这里是通过遍历滚动项,判断滚动条滚动距离是否大于当前项的可滚动距离(即距离其offsetParent顶部的距离,这里是body)
	    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在浏览器的兼容性上还有问题,所以改用如下距离分割的方式。
	    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 + 10 // 锚点元素距离其offsetParent(这里是body)顶部的距离(待滚动的距离)
	      let distance = document.querySelector('.scroll-content').scrollTop + 10// 滚动条距离滚动区域顶部的距离
	      // 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
	        }
	      }
	    },
 	}
}
</script>
<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>
效果图

在这里插入图片描述

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值