欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

实操动态锚点,避开常见陷阱

最编程 2024-08-02 14:47:05
...

锚点的基本实现方法

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
        }
    }
}

好!然后,你就看到????这种效果了(只在个人博客有效果),掘金自己的动态锚点????这种,我觉得很厉害但是还没试着去弄弄