scrollTo代替锚点定位并且通过scroll事件让滚动时导航栏始终可见

a标签有一个锚点定位,用到了#符号,这个定位会影响到路由,所以可以用一个scrollTo方法代替
scrollTo() 方法可把内容滚动到指定的坐标。
语法:

winodw.scrollTo(x,y)

html页面布局

<div class = "banner"></div>
  <!-- navBox固定定位 -->
  <div class = "preHeight" style="height: 80px;width: 100%"></div>
  <div class="navBox">
    <div class = "navigation-bar">
      <a class="active">模块一</a>
      <a>模块二</a>
      <a>模块三</a>
      <a>模块四</a>
      <a>模块五</a>
      <a>模块六</a>
    </div>
  </div>
  <div class="contain">
    <div id = 'm1'></div>
    <div id = 'm2'></div>
    <div id = 'm3'></div>
    <div id = 'm4'></div>
    <div id = 'm5'></div>
    <div id = 'm6'></div>
  </div>

首先
我们设置scrollTop为滚动条到窗口顶端的距离

const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop

接着
我们需要点击a标签,让元素滚动到指定的坐标
此时我们需要获取元素顶端距离浏览器窗口的高度

这里有四种高度:

  • offsetTop:返回当前元素的上边界到它的包含元素的上边界的偏移量,以像素为单位。offsetTop是相对于离它最近的具有绝对或相对定位的父级元素的距离
    offsetY则是一个鼠标事件的值,它是相对于你所点击的那个元素的左上角的Y坐标
  • scrollHeight, scrollWidth
    返回元素的完整的高度和宽度,以像素为单位。
    当一个元素拥有滚动条时,当你把滚动条滚到底部的时候,scrollHeight = scrollTop + clientHeight;
  • offsetHeight 和 offsetWidth
    只是报告元素的可见部分的大小。
    当没有滚动条时scrollHeight = clientHeight,IE则是等于内容的高度;
  • scrollTop, scrollLeft
    设置或返回已经滚动到元素的左边界或上边界的像素数。只有在元素有滚动条的时候这些像素才有用。这些属性也只在文档的 <body> 或 <html> 标记上定义(这和浏览器有关),并且一起来制定滚动文档的位置。注意,这些属性并不会指定一个 <iframe> 标记的滚动量。这是非标准的但却得到很好支持的属性

我们如何利用这些高度呢?

  • 如果你的元素的高度是固定的
window.addEventListener('scroll', ()=>{
     //在外面设置scrollTop是无效的
      const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
      //打印滚动条距浏览器顶部高度
      console.log(scrollTop)
})

当用户滚动指定的元素时,会发生 scroll 事件。
scroll 事件适用于所有可滚动的元素和 window 对象(浏览器窗口)。
我们可以通过scroll事件,让滚动浏览器的滚动条时实时显示滚动条距离页面顶端的距离,而当元素顶端移动到你想它在的位置时的scrollTop就是你想得到的元素顶部距浏览器窗口距离

  • 如果你的元素的高度不固定,就需要累加offsetTop
    我设计的页面中,需要移动的元素的父元素是body
const height1 = document.getElementById('m1').offsetTop
const height2 = document.getElementById('m2').offsetTop
const height3 = document.getElementById('m3').offsetTop
const height4 = document.getElementById('m4').offsetTop
const height5 = document.getElementById('m5').offsetTop
const height6 = document.getElementById('m6').offsetTop

首先要完成的功能是:点击导航栏中的a标签,a标签变色(加上active的样式),并且a标签对应的模块出现在导航栏的a标签下面
使用的方法:window.scrollTo(x,y)

   const navbar = document.querySelector('.navBox')
   const btns = document.querySelector('.navigation-bar').children
   navbar.addEventListener('click',e => {
      let btn = e.target
     //点击导航栏中的某个a标签,该a标签变色
      if(btn.nodeName === "A"){
        for(let i=0; i<btns.length; i++){
          if (btn === btns[i]){
            btns[i].className="active"
          }else{
            btns[i].className=""
          }
        }
        let element
        //60px为导航栏高度
        switch (btn.innerHTML) {
          case '模块一':
            element = height1 - 60
            break
          case '模块二':
            element = height2 - 60
            break
          case '模块三':
            element = height3 - 60
            break
          case '模块四':
            element = height4 - 60
            break
          case '模块五':
            element = height5 - 60
            break
          default:
            element = height6 - 60
            break
        }
       //跳转到指定位置
        window.scrollTo(0, element)
      }
    })

紧接着要完成第二个功能:元素滚动到指定位置,对应的a标签变色
在[h1,h2)内,btn的颜色变色

function handleScroll(h1,h2,btn){
      const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
      if (scrollTop < h2 && scrollTop >= h1) {
        let title = btn
        for (let i = 0; i < btns.length; i++){
          if (title === btns[i].innerHTML){
            btns[i].className = 'active'
          }else{
            btns[i].className = ''
          }
        }
      }
    }

我们可以在发生scroll事件时使用该方法,同时保持导航栏一直在可视范围内

window.addEventListener('scroll', ()=>{
      const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
      //滚动条距浏览器顶部高度
      console.log(scrollTop)
      //保持导航栏一直在视窗顶部
      if(scrollTop>=400){
        navbar.style.position = 'fixed'
        navbar.style.top = '0'
      }else{
        navbar.style.position = 'absolute'
        navbar.style.top = '400px'
      }
      //滚动条滚动,导航栏颜色随之切换
      handleScroll(0,height2-100,'模块一')
      handleScroll(height2-100,height3-100,'模块二')
      handleScroll(height3-100,height4-100,'模块三')
      handleScroll(height4-100,height5-100,'模块四')
      handleScroll(height5-100,height6-150,'模块五')
      handleScroll(height6-150,height6+document.getElementById('m6').clientHeight,'模块六')
      console.log(height6-150)
    })

完整代码:
https://github.com/evaSpec/scroller

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容