滚动效果
当页面滑动时,左边导航栏会自动定位到当前标题,一级标题展开,二级标题的字体变红色,字体前面有一个小图标。
上图。。。。。。。。。。。 html
Html代码前端
<template> <div id="notes"> <nav-top></nav-top> <!-- 中间部分 --> <div class="notes_detail_page"> <div class="left" id="left_y_scroll" ref="lys"> <div > <div class="side_nav" id="chap_nav"> <ul v-for="NItem1 in chapList" class="side_nav_level1"> <li id="lis" @click="UpClick(NItem1.ordered)" class="first_li" >{{NItem1.ordered}} {{NItem1.title}} <ul class="side_nav_level2" v-show="UnderTitle.id==NItem1.ordered&&UnderTitle.isshow" > <li v-for="(NItem2,index) in NItem1.episodeList" @click.stop :id="'lNav'+(NItem2.id-1)"> <!--@click.stop 阻止事件冒泡 --> <span> <img v-show="isshow==NItem2.id-1" src="@/assets/images/landmark.png"/> </span> <a id="nav_a" @click="jump(NItem2.id-1)" :class="{'a_red':isshow==NItem2.id-1}">{{NItem1.ordered}}.{{NItem2.ordered}} {{NItem2.title}}</a> </li> </ul> </li> </ul> </div> </div> </div> <div class="right"> <div id="hide"> <h1 id="v_title">{{VideoList.title}}</h1> <div class="avatar_items"> <img class="avatar" :src="AuthorList.head_img"/> <div class="items"> <p id="author">{{AuthorList.name}}</p> <span id="c_time">{{VideoList.create_time}}</span> <img class="view" src="@/assets/images/view.png"/> <span id="viewNum">{{VideoList.view_num}}</span> <img class="fabulous" src="@/assets/images/fabulous.png"/> <span id="praise_num">6666</span> </div> </div> <div class="note_list" v-for="NItem1 in chapList"> <div v-for="NItem2 in NItem1.episodeList" class="notes_text" :data-id="NItem1.ordered"> <h2 v-html="NItem1.ordered+'.'+NItem2.ordered+' '+NItem2.title"></h2> <p v-html="NItem2.note"></p> </div> </div> </div> </div> </div> <footer-container></footer-container> </div> </template>
1、明确各类位置vue
图片来源于网络ios
此次项目最经常使用的就是 scrollTop 、offsetTop
其中 srcollTop能够理解为 :页面随着滚动条下滑而隐藏的高度
offsetTop 能够理解为 :当前元素距离它最近的祖先元素顶部的距离,而且这个祖先元素的position不为static。若是没有,则是该元素与body顶部的距离web
2、滚动思路axios
滚动到什么地方,左边导航栏出现样式??
当滚动的高度>=右边第i个div的offsetTop,则左边的第i个标题出现样式。api
3、添加滚动监听事件
1.添加滚动监听事件
知识点:addEventListener() 方法,事件监听
用法:element.addEventListener(event, function, useCapture);
第一个参数是:事件的类型。这个项目是滚动监听,因此event是写“scroll”。(其余项目可根据需求,若是是点击就写“click”,以此类推);
第二个参数是:监听事件时调用的函数。这里调用的是 this.menu 这个函数。
第三个参数是:布尔值。即true/false,这个参数是与事件捕获和事件冒泡有关,与这两个有关通常是点击事件,这个项目是滚动事件,因此第三个参数能够不写。数组
mounted(){ window.addEventListener("scroll",this.menu) }
2.在data里面定义一个字符串scroll存放滚动的高度也就是scrollTop,而且在watch中监听data里面scroll的数据变化。浏览器
data(){ return{ scroll:"" } }, watch(){ srcoll:function(){ //这里放的函数下面讲到 } }
4、在methods定义方法,主要有三个步骤网络
1.触发滚动监听事件时,调用的函数,此函数的做用是获取滚动条的高度
menu:function(){ this.srcoll=window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; } //兼容不一样的三个浏览器版本 //也就是上文调用的函数window.addEventListener("scroll",this.menu)
2.定义一个平滑滚动的方法,参考网络上的大神写的。
定义变量total=div[index].offsetTop,则滚动条就须要滚动这个total的距离。
为了达到平滑滚动的效果,把总距离total分红50个小段,每10ms执行一次。
而且还要区分是向上滑动仍是向下滑动,完整代码以下:
jump:function(index){ //把左边导航栏li的下标传进来。 this.isshow=index;//使左边导航出现相应的样式 let divArr=document.querySelectorAll(".notes_text");//获取右边的div数组 let total=divArr[index].offsetTop;//获取第index个div到窗口顶部的距离 let distance = document.documentElement.scrollTop || document.body.scrollTop || window.pageYOffset//获取滚动条的高度(兼容三种浏览器版本) //平滑滚动的效果,把总距离分红50个小段,每10ms执行一次 let step = total / 50 if (total > distance) { //当divArr.[index]offsetTop的距离>滚动条的距离,向下滑动,此时滑动的距离是total smoothDown() //向下滑动 } else { let newTotal = distance - total //当div到窗口的距离<滚动条的距离,向上滑动,此时滑动的距离是distance - total step = newTotal / 50; smoothUp() } //向下滑动 function smoothDown () { if (distance < total) { distance = distance + step document.body.scrollTop = distance document.documentElement.scrollTop = distance window.pageYOffset = total; setTimeout(smoothDown, 10) } else { document.body.scrollTop = total document.documentElement.scrollTop = total window.pageYOffset = total; } } //向上滑动 function smoothUp () { if (distance > total) { distance -= step document.body.scrollTop = distance document.documentElement.scrollTop = distance window.pageYOffset = total; setTimeout(smoothUp, 10) } else { document.body.scrollTop = total document.documentElement.scrollTop = total window.pageYOffset = total; } } }
3.定义方法实现当滚动条的高度>divArr[index].offsetTop时,左边样式改变的函数
loadSroll: function () { let divArr=document.querySelectorAll(".notes_text");//获取右边div的数组 for (var i = 0; i < divArr.length; i++) { if (this.scroll >= divArr[i].offsetTop) { //滚动条的高度>divArr[index].offsetTop,左边导航栏样式改变 var OrderId = divArr[i].getAttribute("data-id");//获取div中data-id的属性值。为了实现左边一级标题打开的效果 this.UnderTitle={id:OrderId,isshow:true};//实现一级标题打开 this.isshow = i;//实现字体变红,小图标出现 //控制左边内嵌滚动条滚动 var lOffsetTop = document.getElementById("lNav"+i).offsetTop;//获取左边导航栏li距离li最近的祖先元素id为left_y_scroll的元素的顶部的距离。(left_y_scroll的position为fixed),详情见下图 if(lOffsetTop > 300){ //当li的offsetTop大于300时,滚动条须要下滑,由于整个div的高度为350px,因此我这里设置了300 this.$refs.lys.scrollTop = lOffsetTop; //使子滚动条的滚动高度,等于lOffsetTop }else{ this.$refs.lys.scrollTop = 0;//在不大于300的状况下,子滚动条的高度为0. } } } }
这里的这个函数,须要放在watch里面,由于这里的this.srcoll 是data里面的srcoll,而srcoll是靠watch监听。
因此咱们须要在watch()里面写:
watch(){ srcoll:function(){ this.loadSroll() } }
lOffsetTop的距离以下图
滚动监听的效果,就能够实现了
完成代码以下!!!!!
<script> import NavTop from "@/components/NavTop.vue" import FooterContainer from "@/components/FooterContainer.vue" export default{ components:{ NavTop, FooterContainer }, created(){ this.init(); }, data(){ return{ chapList:[],//一级标题和二级标题的数组 VideoList:[], AuthorList:[], epiList:[], UnderTitle:"",//左边导航栏的状态判断,其中isshow为true且id相符时,显示 scroll:"",//存储滚动条的高度 isshow:-1,//默认导航栏小图标不显示,点击以后显示 left_up:false, } }, watch: { scroll: function () { //用来监听data中的scroll字符串的变化 this.loadSroll() } }, mounted() { window.addEventListener('scroll', this.menu);//在mounted钩子中给window添加一个滚动监听事件 }, methods:{ init:function(){ this.getVideoDetail(); }, getVideoDetail:function(){ this.$axios.get(this.GLOBAL.host+"/pub/api/v1/web/video_detail",{ params:{ video_id:this.$route. query.video_id } }).then(res =>{ //console.log(res.data.data); this.VideoList=res.data.data.video; this.AuthorList=res.data.data.author; this.chapList=res.data.data.chapter_list; //console.log(this.chapList); for(var i=0;i<this.chapList.length;i++){ for(var j=0;j<this.chapList[i].episodeList.length;j++){ this.epiList.push(this.chapList[i].episodeList[j]) for(var k=0;k<this.epiList.length;k++){ this.epiList[k].id=k+1; //console.log(k) } } } //console.log(this.epiList); }); }, UpClick:function(id){ if(typeof this.UnderTitle.isshow=="underfine"||this.UnderTitle.id!=id){ this.UnderTitle={id:id,isshow:true} }else{ //当点击两次以上,ul隐藏的状况 this.UnderTitle.isshow=!this.UnderTitle.isshow; } }, menu:function(){ //获取滚动条的高度 this.scroll=window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; }, jump:function(index){ this.isshow=index;//使左边导航出现相应的样式 //console.log(index) let divArr=document.querySelectorAll(".notes_text");//获取右边的div数组 let total=divArr[index].offsetTop;//获取第index个div的offsetTop距离 let distance = document.documentElement.scrollTop || document.body.scrollTop || window.pageYOffset//获取滚动条的高度(兼容三种浏览器版本) //平滑滚动的效果,把总距离分红50个小段,每10ms执行一次 let step = total / 50 if (total > distance) { //当div到窗口的距离>滚动条的距离,向下滑动,此时滑动的距离是total smoothDown() //向下滑动 } else { let newTotal = distance - total //当div到窗口的距离<滚动条的距离,向上滑动,此时滑动的距离是distance - total step = newTotal / 50; smoothUp() } //向下滑动 function smoothDown () { if (distance < total) { distance = distance + step document.body.scrollTop = distance document.documentElement.scrollTop = distance window.pageYOffset = total; setTimeout(smoothDown, 10) } else { document.body.scrollTop = total document.documentElement.scrollTop = total window.pageYOffset = total; } } //向上滑动 function smoothUp () { if (distance > total) { distance -= step document.body.scrollTop = distance document.documentElement.scrollTop = distance window.pageYOffset = total; setTimeout(smoothUp, 10) } else { document.body.scrollTop = total document.documentElement.scrollTop = total window.pageYOffset = total; } } }, loadSroll: function () { let divArr=document.querySelectorAll(".notes_text"); //console.log(divArr) for (var i = 0; i < divArr.length; i++) { if (this.scroll >= divArr[i].offsetTop - 88 ) { //这里其实能够减去一个数值,使其左边的导航栏的样式提早出现,我这里是减去了top栏的高度。 //console.log(i) var OrderId = divArr[i].getAttribute("data-id"); //console.log(OrderId); this.UnderTitle={id:OrderId,isshow:true}; this.isshow = i; var lOffsetTop = document.getElementById("lNav"+i).offsetTop;//获取li到窗口的距离 console.log(lOffsetTop); if(lOffsetTop > 300){ //当li的offsetTop大于300时,滚动条须要下滑,由于整个div的高度为350px,因此我这里设置了300 this.$refs.lys.scrollTop = lOffsetTop; //使子滚动条的滚动高度,等于lOffsetTop }else{ this.$refs.lys.scrollTop = 0;//在不大于300的状况下,子滚动条的高度为0. } } } } }, } </script>
前端新手,代码冗长,有不合理和须要改进的地方麻烦提出