5种回到顶部的写法从实现到增强 - 小火柴的蓝色理想 - 博客园


难度 中等

前面的话

  本文先详细介绍回到顶部的5种写法,然后对其实现功能增加,最后得到最终实现

写法

【1】锚点

  使用锚点链接是一种简单的返回顶部的功能实现。该实现主要在页面顶部放置一个指定名称的锚点链接,然后在页面下方放置一个返回到该锚点的链接,用户点击该链接即可返回到该锚点所在的顶部位置

  [注意]关于锚点的详细信息移步至此

<span><</span><span>body </span><span>style</span><span>="height:2000px;"</span><span>></span>
    <span><</span><span>div </span><span>id</span><span>="topAnchor"</span><span>></</span><span>div</span><span>></span>
    <span><</span><span>a </span><span>href</span><span>="#topAnchor"</span><span> style</span><span>="position:fixed;right:0;bottom:0"</span><span>></span>回到顶部<span></</span><span>a</span><span>></span>
<span></</span><span>body</span><span>></span>

【2】scrollTop

  scrollTop属性表示被隐藏在内容区域上方的像素数。元素未滚动时,scrollTop的值为0,如果元素被垂直滚动了,scrollTop的值大于0,且表示元素上方不可见内容的像素宽度

  由于scrollTop是可写的,可以利用scrollTop来实现回到顶部的功能

  [注意]关于页面的scrollTop的兼容问题详细内容移步至此

复制代码

<span><</span><span>body </span><span>style</span><span>="height:2000px;"</span><span>></span>
    <span><</span><span>button </span><span>id</span><span>="test"</span><span> style</span><span>="position:fixed;right:0;bottom:0"</span><span>></span>回到顶部<span></</span><span>button</span><span>></span>
    <span><</span><span>script</span><span>></span><span>
        test.onclick </span><span>=</span> <span>function</span><span>(){
            document.body.scrollTop </span><span>=</span><span> document.documentElement.scrollTop </span><span>=</span> <span>0</span><span>;
        }
    </span><span></</span><span>script</span><span>></span>
<span></</span><span>body</span><span>></span>

复制代码

【3】scrollTo()

  scrollTo(x,y)方法滚动当前window中显示的文档,让文档中由坐标x和y指定的点位于显示区域的左上角

  设置scrollTo(0,0)可以实现回到顶部的效果

复制代码

<span><</span><span>body </span><span>style</span><span>="height:2000px;"</span><span>></span>
    <span><</span><span>button </span><span>id</span><span>="test"</span><span> style</span><span>="position:fixed;right:0;bottom:0"</span><span>></span>回到顶部<span></</span><span>button</span><span>></span>
    <span><</span><span>script</span><span>></span><span>
        test.onclick </span><span>=</span> <span>function</span><span>(){
            scrollTo(</span><span>0</span><span>,</span><span>0</span><span>);
        }
    </span><span></</span><span>script</span><span>></span>
<span></</span><span>body</span><span>></span>

复制代码

【4】scrollBy()

  scrollBy(x,y)方法滚动当前window中显示的文档,x和y指定滚动的相对量

  只要把当前页面的滚动长度作为参数,逆向滚动,则可以实现回到顶部的效果

复制代码

<span><</span><span>body </span><span>style</span><span>="height:2000px;"</span><span>></span>
    <span><</span><span>button </span><span>id</span><span>="test"</span><span> style</span><span>="position:fixed;right:0;bottom:0"</span><span>></span>回到顶部<span></</span><span>button</span><span>></span>
    <span><</span><span>script</span><span>></span><span>
        test.onclick </span><span>=</span> <span>function</span><span>(){
            </span><span>var</span><span> top </span><span>=</span><span> document.body.scrollTop </span><span>||</span><span> document.documentElement.scrollTop
            scrollBy(</span><span>0</span><span>,</span><span>-</span><span>top);
        }
    </span><span></</span><span>script</span><span>></span>
<span></</span><span>body</span><span>></span>

复制代码

【5】scrollIntoView()

  Element.scrollIntoView方法滚动当前元素,进入浏览器的可见区域 

  该方法可以接受一个布尔值作为参数。如果为true,表示元素的顶部与当前区域的可见部分的顶部对齐(前提是当前区域可滚动);如果为false,表示元素的底部与当前区域的可见部分的尾部对齐(前提是当前区域可滚动)。如果没有提供该参数,默认为true

  使用该方法的原理与使用锚点的原理类似,在页面最上方设置目标元素,当页面滚动时,目标元素被滚动到页面区域以外,点击回到顶部按钮,使目标元素重新回到原来位置,则达到预期效果

复制代码

<span><</span><span>body </span><span>style</span><span>="height:2000px;"</span><span>></span>
    <span><</span><span>div </span><span>id</span><span>="target"</span><span>></</span><span>div</span><span>></span>
    <span><</span><span>button </span><span>id</span><span>="test"</span><span> style</span><span>="position:fixed;right:0;bottom:0"</span><span>></span>回到顶部<span></</span><span>button</span><span>></span>
    <span><</span><span>script</span><span>></span><span>
        test.onclick </span><span>=</span> <span>function</span><span>(){
            target.scrollIntoView();
        }
    </span><span></</span><span>script</span><span>></span>
<span></</span><span>body</span><span>></span>

复制代码

增强

  下面对回到顶部的功能进行增强

【1】显示增强

  使用CSS画图,将“回到顶部”变成可视化的图形(如果兼容IE8-浏览器,则用图片代替)

  使用CSS伪元素伪类hover效果,当鼠标移动到该元素上时,显示回到顶部的文字,移出时不显示  

复制代码

<span><</span><span>style</span><span>></span><span>
.box</span><span>{</span><span>
    position</span><span>:</span><span>fixed</span><span>;</span><span>
    right</span><span>:</span><span>10px</span><span>;</span><span>
    bottom</span><span>:</span><span> 10px</span><span>;</span><span>
    height</span><span>:</span><span>30px</span><span>;</span><span>
    width</span><span>:</span><span> 50px</span><span>;</span><span>    
    text-align</span><span>:</span><span>center</span><span>;</span><span>
    padding-top</span><span>:</span><span>20px</span><span>;</span><span>    
    background-color</span><span>:</span><span> lightblue</span><span>;</span><span>
    border-radius</span><span>:</span><span> 20%</span><span>;</span><span>
    overflow</span><span>:</span><span> hidden</span><span>;</span>
<span>}</span><span>
.box:hover:before</span><span>{</span><span>
    top</span><span>:</span><span>50%
</span><span>}</span><span>
.box:hover .box-in</span><span>{</span><span>
    visibility</span><span>:</span><span> hidden</span><span>;</span>
<span>}</span><span>
.box:before</span><span>{</span><span>
    position</span><span>:</span><span> absolute</span><span>;</span><span>
    top</span><span>:</span><span> -50%</span><span>;</span><span>
    left</span><span>:</span><span> 50%</span><span>;</span><span>
    transform</span><span>:</span><span> translate(-50%,-50%)</span><span>;</span><span>
    content</span><span>:</span><span>'回到顶部'</span><span>;</span><span>
    width</span><span>:</span><span> 40px</span><span>;</span><span>
    color</span><span>:</span><span>peru</span><span>;</span><span>
    font-weight</span><span>:</span><span>bold</span><span>;</span>

<span>}</span><span>    
.box-in</span><span>{</span><span>
    visibility</span><span>:</span><span> visible</span><span>;</span><span>
    display</span><span>:</span><span>inline-block</span><span>;</span><span>
    height</span><span>:</span><span>20px</span><span>;</span><span>
    width</span><span>:</span><span> 20px</span><span>;</span><span>
    border</span><span>:</span><span> 3px solid black</span><span>;</span><span>
    border-color</span><span>:</span><span> white transparent transparent white</span><span>;</span><span>
    transform</span><span>:</span><span>rotate(45deg)</span><span>;</span>
<span>}</span>
<span></</span><span>style</span><span>></span>

<span><</span><span>body </span><span>style</span><span>="height:2000px;"</span><span>></span>
<span><</span><span>div </span><span>id</span><span>="box"</span><span> class</span><span>="box"</span><span>></span>
    <span><</span><span>div </span><span>class</span><span>="box-in"</span><span>></</span><span>div</span><span>></span>
<span></</span><span>div</span><span>></span>    
<span></</span><span>body</span><span>></span>

复制代码

【2】动画增强

  为回到顶部增加动画效果,滚动条以一定的速度回滚到顶部

  动画有两种:一种是CSS动画,需要有样式变化配合transition;一种是javascript动画,使用定时器来实现  

  在上面的5种实现中,scrollTop、scrollTo()和scrollBy()方法可以增加动画,且由于无样式变化,只能增加javascript动画

  定时器又有setIntervalsetTimeoutrequestAnimationFrame这三种可以使用,下面使用性能最好的定时器requestAnimationFrame来实现

  [注意]IE9-浏览器不支持该方法,可以使用setTimeout来兼容

  1、增加scrollTop的动画效果

  使用定时器,将scrollTop的值每次减少50,直到减少到0,则动画完毕

复制代码

<span><</span><span>script</span><span>></span>
<span>var</span><span> timer  </span><span>=</span> <span>null</span><span>;
box.onclick </span><span>=</span> <span>function</span><span>(){
    cancelAnimationFrame(timer);
    timer </span><span>=</span><span> requestAnimationFrame(</span><span>function</span><span> fn(){
        </span><span>var</span><span> oTop </span><span>=</span><span> document.body.scrollTop </span><span>||</span><span> document.documentElement.scrollTop;
        </span><span>if</span><span>(oTop </span><span>></span> <span>0</span><span>){
            document.body.scrollTop </span><span>=</span><span> document.documentElement.scrollTop </span><span>=</span><span> oTop </span><span>-</span> <span>50</span><span>;
            timer </span><span>=</span><span> requestAnimationFrame(fn);
        }</span><span>else</span><span>{
            cancelAnimationFrame(timer);
        }    
    });
}
</span><span></</span><span>script</span><span>></span>

复制代码

 【时间版运动】

  但是,上面的代码有一个问题,就是当页面内容较多时,回到顶部的动画效果将持续很长时间。因此,使用时间版的运动更为合适,假设回到顶部的动画效果共运动500ms,则代码如下所示

复制代码

<span><</span><span>body </span><span>style</span><span>="height: 2000px;"</span><span>></span>
<span><</span><span>button </span><span>id</span><span>="test"</span><span> style</span><span>="position:fixed;right:10px;bottom:10px;"</span><span>></span>回到顶部<span></</span><span>button</span><span>></span>
<span><</span><span>script</span><span>></span>
<span>var</span><span> timer  </span><span>=</span> <span>null</span><span>;
test.onclick </span><span>=</span> <span>function</span><span>(){
    cancelAnimationFrame(timer);
    </span><span>//</span><span>获取当前毫秒数</span>
    <span>var</span><span> startTime </span><span>=</span> <span>+</span><span>new</span><span> Date();     
    </span><span>//</span><span>获取当前页面的滚动高度</span>
    <span>var</span><span> b </span><span>=</span><span> document.body.scrollTop </span><span>||</span><span> document.documentElement.scrollTop;
    </span><span>var</span><span> d </span><span>=</span> <span>500</span><span>;
    </span><span>var</span><span> c </span><span>=</span><span> b;
    timer </span><span>=</span><span> requestAnimationFrame(</span><span>function</span><span> func(){
        </span><span>var</span><span> t </span><span>=</span><span> d </span><span>-</span><span> Math.max(</span><span>0</span><span>,startTime </span><span>-</span><span> (</span><span>+</span><span>new</span><span> Date()) </span><span>+</span><span> d);
        document.documentElement.scrollTop </span><span>=</span><span> document.body.scrollTop </span><span>=</span><span> t </span><span>*</span><span> (</span><span>-</span><span>c) </span><span>/</span><span> d </span><span>+</span><span> b;
        timer </span><span>=</span><span> requestAnimationFrame(func);
        </span><span>if</span><span>(t </span><span>==</span><span> d){
          cancelAnimationFrame(timer);
        }
    });
}
</span><span></</span><span>script</span><span>></span>
<span></</span><span>body</span><span>></span>

复制代码

  2、增加scrollTo()动画效果

  将scrollTo(x,y)中的y参数通过scrollTop值获取,每次减少50,直到减少到0,则动画完毕

复制代码

<span><</span><span>script</span><span>></span>
<span>var</span><span> timer  </span><span>=</span> <span>null</span><span>;
box.onclick </span><span>=</span> <span>function</span><span>(){
    cancelAnimationFrame(timer);
    timer </span><span>=</span><span> requestAnimationFrame(</span><span>function</span><span> fn(){
        </span><span>var</span><span> oTop </span><span>=</span><span> document.body.scrollTop </span><span>||</span><span> document.documentElement.scrollTop;
        </span><span>if</span><span>(oTop </span><span>></span> <span>0</span><span>){
            scrollTo(</span><span>0</span><span>,oTop</span><span>-</span><span>50</span><span>);
            timer </span><span>=</span><span> requestAnimationFrame(fn);
        }</span><span>else</span><span>{
            cancelAnimationFrame(timer);
        }    
    });
}
</span><span></</span><span>script</span><span>></span>

复制代码

  3、增加scrollBy()动画效果

  将scrollBy(x,y)中的y参数设置为-50,直到scrollTop为0,则回滚停止

复制代码

<span><</span><span>script</span><span>></span>
<span>var</span><span> timer  </span><span>=</span> <span>null</span><span>;
box.onclick </span><span>=</span> <span>function</span><span>(){
    cancelAnimationFrame(timer);
    timer </span><span>=</span><span> requestAnimationFrame(</span><span>function</span><span> fn(){
        </span><span>var</span><span> oTop </span><span>=</span><span> document.body.scrollTop </span><span>||</span><span> document.documentElement.scrollTop;
        </span><span>if</span><span>(oTop </span><span>></span> <span>0</span><span>){
            scrollBy(</span><span>0</span><span>,</span><span>-</span><span>50</span><span>);
            timer </span><span>=</span><span> requestAnimationFrame(fn);
        }</span><span>else</span><span>{
            cancelAnimationFrame(timer);
        }    
    });
}
</span><span></</span><span>script</span><span>></span>

复制代码

实现

  由于scrollTop、scrollBy()和scrollTo()方法,都以scrollTop值是否减少为0作为动画停止的参照,且三个动画的原理和实现都基本相似,性能也相似。最终,以最常用的scrollTop属性实现动画增强效果

  当然,如果觉得500ms的时间不合适,可以根据实际情况进行调整

复制代码

<span><!</span><span>DOCTYPE html</span><span>></span>
<span><</span><span>html </span><span>lang</span><span>="en"</span><span>></span>
<span><</span><span>head</span><span>></span>
<span><</span><span>meta </span><span>charset</span><span>="UTF-8"</span><span>></span>
<span><</span><span>title</span><span>></span>Document<span></</span><span>title</span><span>></span>
<span><</span><span>style</span><span>></span><span>
.box</span><span>{</span><span>
    position</span><span>:</span><span>fixed</span><span>;</span><span>
    right</span><span>:</span><span>10px</span><span>;</span><span>
    bottom</span><span>:</span><span> 10px</span><span>;</span><span>
    height</span><span>:</span><span>30px</span><span>;</span><span>
    width</span><span>:</span><span> 50px</span><span>;</span><span>    
    text-align</span><span>:</span><span>center</span><span>;</span><span>
    padding-top</span><span>:</span><span>20px</span><span>;</span><span>    
    background-color</span><span>:</span><span> lightblue</span><span>;</span><span>
    border-radius</span><span>:</span><span> 20%</span><span>;</span><span>
    overflow</span><span>:</span><span> hidden</span><span>;</span>
<span>}</span><span>
.box:hover:before</span><span>{</span><span>
    top</span><span>:</span><span>50%
</span><span>}</span><span>
.box:hover .box-in</span><span>{</span><span>
    visibility</span><span>:</span><span> hidden</span><span>;</span>
<span>}</span><span>
.box:before</span><span>{</span><span>
    position</span><span>:</span><span> absolute</span><span>;</span><span>
    top</span><span>:</span><span> -50%</span><span>;</span><span>
    left</span><span>:</span><span> 50%</span><span>;</span><span>
    transform</span><span>:</span><span> translate(-50%,-50%)</span><span>;</span><span>
    content</span><span>:</span><span>'回到顶部'</span><span>;</span><span>
    width</span><span>:</span><span> 40px</span><span>;</span><span>
    color</span><span>:</span><span>peru</span><span>;</span><span>
    font-weight</span><span>:</span><span>bold</span><span>;</span>

<span>}</span><span>    
.box-in</span><span>{</span><span>
    visibility</span><span>:</span><span> visible</span><span>;</span><span>
    display</span><span>:</span><span>inline-block</span><span>;</span><span>
    height</span><span>:</span><span>20px</span><span>;</span><span>
    width</span><span>:</span><span> 20px</span><span>;</span><span>
    border</span><span>:</span><span> 3px solid black</span><span>;</span><span>
    border-color</span><span>:</span><span> white transparent transparent white</span><span>;</span><span>
    transform</span><span>:</span><span>rotate(45deg)</span><span>;</span>
<span>}</span>
<span></</span><span>style</span><span>></span>
<span></</span><span>head</span><span>></span>
<span><</span><span>body </span><span>style</span><span>="height:2000px;"</span><span>></span>
<span><</span><span>div </span><span>id</span><span>="box"</span><span> class</span><span>="box"</span><span>></span>
    <span><</span><span>div </span><span>class</span><span>="box-in"</span><span>></</span><span>div</span><span>></span>
<span></</span><span>div</span><span>></span>    
<span><</span><span>script</span><span>></span>
<span>var</span><span> timer  </span><span>=</span> <span>null</span><span>;
box.onclick </span><span>=</span> <span>function</span><span>(){
    cancelAnimationFrame(timer);
    </span><span>//</span><span>获取当前毫秒数</span>
    <span>var</span><span> startTime </span><span>=</span> <span>+</span><span>new</span><span> Date();     
    </span><span>//</span><span>获取当前页面的滚动高度</span>
    <span>var</span><span> b </span><span>=</span><span> document.body.scrollTop </span><span>||</span><span> document.documentElement.scrollTop;
    </span><span>var</span><span> d </span><span>=</span> <span>500</span><span>;
    </span><span>var</span><span> c </span><span>=</span><span> b;
    timer </span><span>=</span><span> requestAnimationFrame(</span><span>function</span><span> func(){
        </span><span>var</span><span> t </span><span>=</span><span> d </span><span>-</span><span> Math.max(</span><span>0</span><span>,startTime </span><span>-</span><span> (</span><span>+</span><span>new</span><span> Date()) </span><span>+</span><span> d);
        document.documentElement.scrollTop </span><span>=</span><span> document.body.scrollTop </span><span>=</span><span> t </span><span>*</span><span> (</span><span>-</span><span>c) </span><span>/</span><span> d </span><span>+</span><span> b;
        timer </span><span>=</span><span> requestAnimationFrame(func);
        </span><span>if</span><span>(t </span><span>==</span><span> d){
          cancelAnimationFrame(timer);
        }
    });
}
</span><span></</span><span>script</span><span>></span>
<span></</span><span>body</span><span>></span>
<span></</span><span>html</span><span>></span>

复制代码

  欢迎交流


  目录
分类导航
随笔2 AI27 算法1 计算机基础13 博客搭建7 ChatGPT2 集群63 计算机通信1 数据库34 数据库深入80 DPDK26 Docker11 Elasticsearch4 编辑工具4 FAQ1 Go Web1 hometown2 编程语言16 网络9 OPC1 Linux38 openGauss4 页面12 PostgreSQL54 程序员自我修养1 协议11 成长之路1 stock1 存储5 工具20 VPP18 视频作品1 Vue13 Web1 代码示例11 数据库15 BenchmarkSQL1 PostgreSQL 源码修炼之路14
最热文章
1
13 逻辑复制深入
数据库深入🔥 1570
2
0 Postgresql存储、索引及系统优化、主备切换
PostgreSQL🔥 1495
3
一文读懂openguass dcf网络模块
集群🔥 1420
4
逻辑复制源码分析
数据库深入🔥 1327
5
PostgreSQL 分区表:从一行 `PARTITION BY` 到路由热路径的全链路拆解
数据库🔥 1094
6
applyparallelworker.c 之 LA 端源码深度解析:Leader Apply Worker 的指挥中枢
数据库深入🔥 1082
7
PostgreSQL Background Worker 全解:从 `RegisterBackgroundWorker` 到逻辑复制 4 类 worker 的全生命周期
数据库🔥 1078
8
PostgreSQL的后台进程walsender分析 - 关系型数据库 - 亿速云
PostgreSQL🔥 1033
9
PostgreSQL 逻辑复制的监控:六张视图 + 一组可执行 SQL,把 publisher/subscriber 的速率与健康度彻底看透
数据库🔥 1032
10
PostgreSQL 逻辑复制支持 DDL 之后:DDL 与 DML 的时序难题(重点:分区表)
数据库🔥 999
11
reorderbuffer.c 源码深度解析:PostgreSQL 逻辑复制的"事务重组引擎
数据库深入🔥 953
12
PostgreSQL 内核开发:读取一张表的 9 步标准流程与缓存全景
数据库🔥 938
13
从 `postgres` 二进制到生产级守护 —— PostgreSQL 最外层模块与启动全流程拆解
数据库🔥 936
14
支持逻辑复制同步 DDL 适配 SQL Server 方案
数据库深入🔥 934
15
PostgreSQL 逻辑复制的 ReorderBuffer 与事务机制:从一行 WAL 到一致性变更流的全链路绑定
数据库🔥 913
16
DDL同步架构(美化版)
数据库深入🔥 908
17
PostgreSQL Latch 机制详解:从一行 SetLatch 到 epoll 的内核之旅
数据库🔥 871
18
pgbench 源码全解:一个 C 文件如何撑起 PostgreSQL 官方压测工具
数据库🔥 860
19
PostgreSQL libpq 机制与缓冲区详解
数据库🔥 850
20
PostgreSQL 逻辑复制 spill 文件深度剖析:从 `xid-*.spill` 到 TPC-C 的增长方程
数据库🔥 845