需求简介
自从公司裁员后,每个人手上的活而越来越多,老板给了我个需求,让我尽快实现,不然立马滚蛋!

我大脑飞速思索,1秒后终于反应过来,不就是个滚动条滚动 加css吗,还想辞退我,做梦!不能惯着!
技术方案
技术选型
首先,很快啊,我就实现了静态样式

然后要考虑的就是如何实现点击锚点界面能滚动到对应的模块 ,最简单的就是scrollIntoView方法。
Element 接口的 scrollIntoView() 方法会滚动元素的父容器,使被调用 scrollIntoView() 的元素对用户可见。
至于闪烁突出,那就当元素被选中时,给它动态添加一个类名,写写css动画就行。
以vue为例,我具体展示下实现过程。
实现滚动
点击导航栏的得锚点时,我们可以使用wacth监听到是哪个模块被点击了,然后执行滚动逻辑。
            
            
              js
              
              
            
          
          <template>
    <div class="card-content" >
        <!-- 模块内容 -->
    </div>
</template>
<script setup lang="ts">
    // 监听被点击的模块编码,执行滚动逻辑
    watch(() => scrollModuleCode, (v) => {
        // 滚动逻辑
    })
</script>
        我们先看看scrollIntoView的简单用法
Element.scrollIntoView()
Element 接口的 scrollIntoView() 方法会滚动元素的父容器,使被调用 scrollIntoView() 的元素对用户可见。
语法
            
            
              js
              
              
            
          
          scrollIntoView(scrollIntoViewOptions)
        使用 示例
            
            
              js
              
              
            
          
          const element = document.getElementById("box");
element.scrollIntoView();
element.scrollIntoView({ block: "end" });
element.scrollIntoView({ behavior: "smooth", block: "end", inline: "nearest" });
        属性参数释义
behavior (可选)
定义滚动是立即的还是平滑的动画。该选项是一个字符串,必须采用以下值之一:
- smooth:滚动应该是平滑的动画。
 - instant:滚动应该通过一次跳跃立刻发生。
 - auto:滚动行为由 scroll-behavior 的计算值决定。
 
滚动实现
结合scrollIntoView的用法,要实现滚动就非常容易了
            
            
              js
              
              
            
          
          <template>
    <div class="card-content" ref="scrollRef">
        <!-- 模块内容 -->
    </div>
</template>
<script setup lang="ts">
    const scrollRef = ref()
    // 监听被点击的模块编码,执行滚动逻辑
    watch(() => scrollModuleCode, (v) => {
        // 滚动逻辑
        nextTick(() => {
            scrollRef.value.scrollIntoView({ behavior: "smooth", block: "start" });
        })
    })
</script>
        上述代码中,我们使用scrollRef绑定了元素的dom,当元素被点击时,实现了滚动。看看效果

不错,基本功能实现了,现在我们增加下样式。
闪烁突出实现
要实现闪烁动画,我们可以再模块被点击时,动态添加一个类名,然后给这个类写样式即可。
            
            
              js
              
              
            
          
          <template>
    <div class="card-content" ref="scrollRef" :class="{ 'stroke-flash': flashActive }">
        <!-- 模块内容 -->
    </div>
</template>
<script setup lang="ts">
    const scrollRef = ref()
    const flashActive = ref(false)
    // 监听被点击的模块编码,执行滚动逻辑
    watch(() => scrollModuleCode, (v) => {
        // 开启动画
        flashActive.value = true
        // 滚动逻辑
        nextTick(() => {
            scrollRef.value.scrollIntoView({ behavior: "smooth", block: "start" });
        })
        // 关闭动画
        setTimeout(() => {
            flashActive.value = false
        }, 2200)
    })
</script>
<style>
.stroke-flash {
}
</style>
        上述代码中,当模块被点击时,flashActive 值变为true,组件的stroke-flash 类名被激活,2.2s后,flashActive值变为fasle,类名消失,动画结束。
那么样式如何实现呢?突出闪烁,其实就是给组件加个蓝色的边框,然后使用动画属性改变其透明度。
            
            
              css
              
              
            
          
          @keyframes strokeFlash {
    0%,
    100% {
        border-color: transparent;
    }
    50% {
        border: 3px solid #246FE5;
    }
}
.stroke-flash {
    /* 动画名称、动画时长、缓入缓出效果、循环次数 */
    border-radius: 12px;
    animation: strokeFlash 1100ms ease-in-out 2;
}
        我们看看效果
nice!
仔细观察界面,其实有个非常难受的地方,每次滚动,元素总是滚动到了浏览器视窗的顶部,导致有一部分被导航栏遮住了,非常难受!这要是给老板交付,搞不好直接被裁了!
滚动位置优化
一个很难受的地方就是scrollIntoView()不支持传元素滚动到浏览器顶部的距离,这导致每次滚动元素都定位到了浏览器顶部。比如,我们更希望点击【控制失调空间】时,界面是这样

而不是直接滚动到浏览器顶部

要解决这个问题,其实很简单!注意看,我给每个模块顶部一定高度写了个专门用于定位的div。

            
            
              js
              
              
            
          
          <template>
    <div class="card-content":class="{ 'stroke-flash': flashActive }">
        <div class="anchor" ref="scrollRef"></div>
        <!-- 模块内容 -->
    </div>
</template>
<script setup lang="ts">
    const scrollRef = ref()
    const flashActive = ref(false)
    // 监听被点击的模块编码,执行滚动逻辑
    watch(() => scrollModuleCode, (v) => {
        // 开启动画
        flashActive.value = true
        // 滚动逻辑
        nextTick(() => {
            scrollRef.value.scrollIntoView({ behavior: "smooth", block: "start" });
        })
        // 关闭动画
        setTimeout(() => {
            flashActive.value = false
        }, 2200)
    })
</script>
<style>
.card-content {
    position: relative;
    .anchor {
        top: -177px;
        left: 0;
        width: 20px;
        height: 5px;
        position: absolute;
        background: red;
    }
}
</style>
        由于【控制失调空间】模块的定位元素在浏览器的顶部,滚动时,位置就如同我们想象的那样了!
非常丝滑!现在我么把这个红色的锚点隐藏起来就行!
            
            
              js
              
              
            
          
          <style>
.card-content {
    position: relative;
    overflow: hidden;
    .anchor {
        top: -177px;
        left: 0;
        width: 10px;
        height: 1px;
        position: absolute;
        background: red;
        opacity: 0;
    }
}
</style>
        再试试
这么丝滑,老板肯定不会辞退我了!不说了,去交差了!
写在最后
这个锚点定位+闪烁突出实现的方案比较简单和粗糙,时间紧,任务重,我也没想到很好的方案。。。如果有更好的实现方式,请大家评论区告诉我!我去和老板对线!