实操动态锚点,避开常见陷阱
锚点的基本实现方法
1、通过a标签直接跳转
在p标签里增加 id
<p id = 'jumpto'>我要跳转到这里</p>
然后用一个a标签href 绑定这个id
<a href = '#jumpto'>点击这里就能跳转到id的位置</a>
写一个能测试的html,是长这个样子
<br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<a href = '#jumpto'>点击这里就能跳转到id的位置</a>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<p id = 'jumpto'>大概能跳到这里</p>
<br><br><br><br><br><br><br>
但是呢,这样做有个硬伤就是跳转的时候就直接闪到目标的位置,就很丑
2、通过querySelector找到DOM用scrollIntoView方法跳转
还是那个p标签,还是那个id
<p id = 'jumpto'>我要跳转到这里</p>
然后用一个js,querySelector 找到这个id
const jump = document.querySelector('#jumpto');
然后用这个jump的scrollIntoView方法跳转
jump.scrollIntoView();
写一个能测试的html,是长这个样子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<button onclick=jumpjump()>点击这里开始跳转</button>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<p id = 'jumpto'>大概能跳到这里</p>
<br><br><br><br><br><br><br>
</body>
<script>
function jumpjump(){
const jump = document.querySelector('#jumpto');
jump.scrollIntoView();
}
</script>
</html>
如果有人复制了这个下去进行测试就会问了,这不也是一样很突兀吗
所以我们就要用到这个scrollIntoView里的属性了,先来介绍一下
1、behavior
这个属性他有这几种用法
jump.scrollIntoView({behavior:"auto"});
这种是默认的就是一下子跳过去
jump.scrollIntoView({behavior:"instant"});
instant这个单词是什么意思知道吗,瞬间!对他就是跟第一种方法是一样的,我也不知道为什么要弄两个同样效果的属性
jump.scrollIntoView({behavior:"smooth"});
那么剩下这个就是,有滚动动画的效果
2、block
jump.scrollIntoView({block:"start"});
这种是跳转把跳转的目标放到屏幕的顶部
jump.scrollIntoView({block:"center"});
这种是跳转把跳转的目标放到屏幕的中间
jump.scrollIntoView({block:"end"});
这种是跳转把跳转的目标放到屏幕的底部
jump.scrollIntoView({block:"nearest"});
说实话不太懂怎么用
3、inline
这个也是有上面的四个属性,但是说实话还是不太懂怎么用。所以这也也不细说了。
下面是测试用代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p id = 'top'></p>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<button onclick=jumpMeiDongHua()>点击这里没动画跳转</button><br>
<button onclick=jumpYouDongHua()>点击这里有动画跳转</button><br>
<button onclick=jumpStart()>点击这里跳转,目标显示在顶上</button><br>
<button onclick=jumpCenter()>点击这里跳转,目标显示在中间</button><br>
<button onclick=jumpEnd()>点击这里跳转,目标显示在底部</button><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<button onclick=jumpTop()>返回顶部</button>
<p id = 'jumpto'>大概能跳到这里</p>
<button onclick=jumpTop()>返回顶部</button>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</body>
<script>
// 没动画的跳转方法
function jumpMeiDongHua(){
const jump = document.querySelector('#jumpto');
jump.scrollIntoView();
}
// 有动画的跳转方法
function jumpYouDongHua(){
const jump = document.querySelector('#jumpto');
jump.scrollIntoView({behavior:"smooth"});
}
// 跳转,目标显示在顶上的方法
function jumpStart(){
const jump = document.querySelector('#jumpto');
jump.scrollIntoView({block: "start"});
}
// 跳转,目标显示在中间的方法
function jumpCenter(){
const jump = document.querySelector('#jumpto');
jump.scrollIntoView({block: "center"});
}
// 跳转,目标显示在底部的方法
function jumpEnd(){
const jump = document.querySelector('#jumpto');
jump.scrollIntoView({block: "end"});
}
// 返回顶部的方法
function jumpTop(){
const jump = document.querySelector('#top');
jump.scrollIntoView({block: "center",inline: "end"});
}
</script>
</html>
动态锚点的实现方法
那么锚点知道怎么做了,接下来就是要做动态锚点了
首先解释一下是什么个意思
就是你文章嘛不是有个标题目录嘛,然后呢把这个目录放在文章的旁边,你一点它就跳转啦。这个时候你就需要啥呀,需要一个高亮在目录上显示你跳到哪了。然后呢再通过你的上下滚动到下个目录,这个高亮自然就会跟过去在下一个目录高亮。呐这个就是动态锚点了。还不能理解你就看看????左边,如果你是在掘金上看的就看看????右边,对这个目录就是动态锚点做的。
这个先说我的一开始的做法
一开始,我是以网页被卷去的高:document.documentElement.scrollTop
作为判断
如果大于这个,小于那个,页面就激活哪个样式。大于另一个这个,小于另一个那个,激活另一个样式
但是呢这样就会有个问题:
如果页面比例一样就会出现滚动了多少,和你一开始写在代码里做判断的对不上。
那怎么办呢:
一开始,我是想先获取整个页面的高度,然后把高度乘上比例,去做判断,但是我想了想好像好麻烦,我又想了就决定document.querySelector('#ID').getClientRects()[0].y
去获取元素当前高度,而这个是不会随比例改变而改变的,我只需要通过计算得到每个段落的高度,屏幕一半的高度。因为我是用scrollIntoView({block: "center"})
去滚动的,所以需要计算元素经过一半的时候激活当前的菜单。
下面就直接把vue项目里的代码复制过来了
let top = document.querySelector('#top').getClientRects()[0].y
let limit
let half = (window.screen.availHeight -100)/2
let zz = document.querySelector('#bot').getClientRects()[0].y
//首先需要四个变量,一个是返回顶部时用的高度top
//第二个,当最后一段文章不够半屏幕时用来判断激活最后一个菜单的高度limit
//第三个用来判断经过半屏高度的half
//第四个是底部的一个点,用来计算最后一段文章的高度
if(this.profileInfo.munNum[0]){
//this.profileInfo.munNum这个是接口传进来的菜单数组根据菜单的数量去创建高度判断
var aa = document.querySelector('#one').getClientRects()[0].y
if (aa < half&&top!=0){
this.isActive = 1
//isActive是vue里判断激活菜单用的
}
}if(this.profileInfo.munNum[1]){
var bb = document.querySelector('#two').getClientRects()[0].y
if (bb < half){
this.isActive = 2
//这是当这不是最后一段,正常经过点时候激活菜单样式
}
if (!this.profileInfo.munNum[2]){
//当这是最后一个菜单
const secondLastLength = bb-aa //这个是倒数第二段的高
const lastLength = zz-bb //这个是倒数第一段的高
if(secondLastLength>half&&lastLength>half){
limit = half
}
else if(secondLastLength<half&&lastLength>80){
limit = half - lastLength
}else if(secondLastLength>half&&lastLength>80){
limit = half - (secondLastLength-lastLength)
}else{
limit = half - 80
}
if(bb<limit){
this.isActive = 2
}
}
}
好!然后,你就看到????这种效果了(只在个人博客有效果),掘金自己的动态锚点????这种,我觉得很厉害但是还没试着去弄弄
上一篇: 玩转 HTML & JS 锚点定位:多样技巧与利弊分析
下一篇: HTML和CSS中的锚点如何使用?
推荐阅读