Rosmontis&迷迭香的博客&鹤望兰分部

Rosmontis&迷迭香的博客
僅用於Bing訪客使用,若需要最新的文章,建議訪問rosmontis.com
  1. 首页
  2. 正文

HTML中dom元素滚动条滚动控制小结详解

2021年7月23日 7点热度 0人点赞 0条评论

不知道大家有没有遇到过这样的需求,在某个 dom 元素中添加新的子元素,然后要求如果新添加的新元素超出容器的范围,那么我们需要自动滚动到新添加的子元素的位置,如下图所示效果:

那么接下来我们一边学习一些 dom 元素滚动相关的知识点,一边实现一个上图的效果和一些其他滚动相关的功能。

需要了解的dom属性和方法 scrollTop、clientHeight和scrollHeight

scrollTop 属性是一个描述容器元素内容的top值与容器元素( viewport )视口顶部 top 值之间的差值,即容器中内容向上滑动后超出容器视口的部分。可以通过修改此属性控制滚动状态。

clientHeight 是描述容器高度的 dom 属性。

scrollHeight 是描述容器内容高度的 dom 属性。

三个属性的关系如下图所示:

getBoundingClientRect()

此方法用来获取元素布局所需的一些几何属性,比如 left 、 right 、 top 、 bottom 、 height 、 width 等。

srollBy(x,y)

dom 容器的 scrollTo 方法可以用来直接控制滚动条滚动指定的距离。当需要滚动到指定元素时,使用此方法比较方便。

srollTo(x,y)

dom 容器的 scrollTo 方法可以用来直接控制滚动条滚动到指定位置。在控制滚动条滚动到顶部或者底部的时候使用此方法比较方便。

实现滚动控制 准备

我们先准备一个 html

<!DOCTYPE html>
<html>
<head>
<title>滚动条设置详解</title>
<style>
#scroll_container{
height: 500px;
width: 500px;
overflow-y: scroll;
padding: 50px;
box-sizing: border-box;
}
.scroll_item{
height: 200px;
width: 500px;
margin-top: 20px;
background-color: aquamarine;
display: flex;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<div id="scroll_container">
<div id="scroll_container">
<div id="item1" class="scroll_item">
<span>1</span>
</div>
<div id="item2" class="scroll_item">
<span>2</span>
</div>
<div id="item3" class="scroll_item">
<span>3</span>
</div>
<div id="item4" class="scroll_item">
<span>4</span>
</div>
<div id="item5" class="scroll_item">
<span>5</span>
</div>
</div>
<button onclick="addItem()">添加一个元素</button>
</div>
</body>
<script>
let container=document.getElementById("scroll_container");
let index=5;
//添加一个元素
function addItem(){
index+=1;
let item=`<div id="${'item'+index}" class="scroll_item">
<span>${index}</span>
</div>`;
container.innerHTML+=item;
setTimeout(()=>{
scrollToIndex();
})
}
</script>
</html>

上面的代码包含一个可滚动的区域,并可以为滚动区域添加元素,也可以滚动到指定的元素位置,大致效果如下图。

使用scrollTop实现

基础实现

之前已经说明过 scrollTop 的含义,我们可以通过修改容器元素 scrollTop 值来控制滚动条滚动。 scrollTop 的值越大,滚动条相对于原始状态( scrollTop 为0时)的滚动距离越大。

了解了 scrollTop 的含义,我们就可以利用 scrollTop 来实现滚动条的控制,那么我们先实现一个滚动到底部的实现,为上面的代码添加一个 scrollToBottom() 的方法:

function scrollToBottom(){
let y=container.scrollHeight-container.clientHeight;
container.scrollTop=y;
}

对应的如果想要实现滚动到顶部我们只需要设置 scrollTop 为0即可:

function scrollToTop(){
container.scrollTop=0;
}

结合 getBoundingClientRect() 方法我们也可以轻松实现滚动到指定元素,其中 getBoundingClientRect().top 表示子元素顶部距离父元素视口顶部的距离:

function scrollToElement(el){
container.scrollTop+=el.getBoundingClientRect().top;
}

添加动画

滚动到底部

但是上面代码的滚动未免太生硬了,我们可以为它添加一下动画效果,可以借助 setInterval() 实现一下。分析一下实现动画效果的过程,动画的实现无外乎是把一个变量的变化在一定的时间内完成,因此我们首先需要知道两个变量,变量( scrollTop )偏移量和变化所需时间,而偏移量就是 scrollTop 的最终值减去原始值,变化时长一般设置成可以修改的参数。了解了以上过程,我们先以滚动到底部为例:

//首先编写一个scrollToBottom函数
function scrollToBottom(el){
if(!el){
el=container;
}
//原始值
let startTop=el.scrollTop;
//最终值
let endTop=el.scrollHeight-el.clientHeight;
//生成一个动画控制函数
let scrollAnimationFn=doAnimation(startTop,endTop,300,el);
//执行动画,每10ms执行一次
let interval=setInterval(()=>{
scrollAnimationFn(interval)
},10)
}
/**
* @description: 一个生成动画控制函数的工厂函数(使用闭包)
* @param {
startValue:变量原始值
endValue:变量最终值
duration:动画时长
el:执行滚动动画的元素
}
* @return: null
*/
function doAnimation(startValue,endValue,duration,el){
//使用闭包保存变量dy和step(每次动画滚动的距离)
let dy=0;
let step=(endValue-startValue)/(duration/10);
//返回动画控制函数
return function(interval){
dy+=step;
if(dy>=endValue-startValue){
clearInterval(interval);
}
el.scrollTop+=step;
}
}


修改addItem函数添加滚动到底部动画:

function addItem(){
index+=1;
let item=`<div id="${'item'+index}" class="scroll_item">
<span>${index}</span>
</div>`;
container.innerHTML+=item;
setTimeout(()=>{
// scrollToIndex();
scrollToBottom(container);
})

}

然后为html加入一个滚动到底部的按钮:

<button onclick="scrollToBottom()">滚动到底部</button>

滚动到顶部

按照上面的方法也可以实现一个常用的带动画滚动到顶部:

//编写一个scrollToTop函数
function scrollToTop(el){
if(!el){
el=container;
}
//原始值
let startTop=el.scrollTop;
//最终值
let endTop=0;
//生成一个动画控制函数
let scrollAnimationFn=doAnimation(startTop,endTop,300,el);
//执行动画,每10ms执行一次
let interval=setInterval(()=>{
scrollAnimationFn(interval)
},10)
}

为了适配滚动到底部我们需要修改一下动画停止的时机判断,修改后的 doAnimation() 函数如下:

function doAnimation(startValue,endValue,duration,el){
//使用闭包保存变量dy和step(每次动画滚动的距离)
let dy=0;
let step=(endValue-startValue)/(duration/10);
return function(interval){
dy+=step;
//这里改成使用绝对值判断
if(Math.abs(dy)>=Math.abs(endValue-startValue)){
clearInterval(interval);
}
el.scrollTop+=step;
}
}

最后我们再给 html 添加一个滚动到底部按钮:

<button onclick="scrollToTop()">滚动到顶部</button>

实现效果如下图:

滚动到指定元素

首先为html元素添加所需的按钮和输入框:

<input type="number" placeholder="请输入要滚动到的元素index" style="width: 200px;"/>
<button onclick="scrollToElement()">滚动到指定元素</button>

添加一个滚动指定元素的动画执行函数:

function scrollToElement(containerEl,el){
if(!containerEl){
//父元素
containerEl=container;
}
if(!el){
//获取到要滚动到的元素
let input=document.getElementsByTagName('input')[0];
let id='item'+input.value;
if(!input.value){
id='item'+index;
}
el=document.getElementById(id);
}
let startTop=containerEl.scrollTop;
let endTop=startTop+el.getBoundingClientRect().top;
let scrollAnimationFn=doAnimation(startTop,endTop,300,containerEl);
let interval=setInterval(()=>{
scrollAnimationFn(interval)
},10)
}

实现效果如下:

使用scrollTo()实现

scrollTo(x,y) 的使用方法与 scrollTop 属性的使用方法基本一致,父元素的 scrollTo() 方法可以控制滚动条滚动到指定位置,实际上相当于设置 scrollTop 的值。举个例子说明一下:

//这里以y轴滚动为例
element.scrollTo(0,y);
element.scrollTop=y;
//上面两句的效果相同

所以,使用 scrollTo() 方法控制滚动条与使用scrollTop基本一致,我们只需要简单修改 doAnimation() 函数,代码如下:

function doAnimation(startValue,endValue,duration,el){
//使用闭包保存变量dy和step(每次动画滚动的距离)
let dy=0;
let step=(endValue-startValue)/(duration/10);
return function(interval){
dy+=step;
if(Math.abs(dy)>=Math.abs(endValue-startValue)){
clearInterval(interval);
}
//el.scrollTop+=step;//这行代码修改为如下
el.scrollTo(0,el.scrollTop+step);
}
}

执行效果与使用 scrollTop 实现一致。

使用scrollBy()实现

基础实现

我们同样可以使用 scrollBy(x,y) 实现对滚动条的控制,上面已经说明过, scrollBy() 方法是控制滚动条滚动指定距离(注意不是位置)。使用scrollBy()可以很方便的实现滚动到指定元素的需求,代码如下:

function scrollToElement(containerEl,el){
//因为getBoundingClientRect().top即为子元素顶部距离父元素顶部的距离,所以这个值就是子元素相对于父元素的偏移量,我们传入这个值到scrollBy中,即滚动到指定元素
containerEl.scrollBy(0,el.getBoundingClientRect().top);
}

滚动到底部:

function scrollToBottom(containerEl){
let dy=containerEl.scrollHeight-containerEl.clientHeight;
containerEl.scrollBy(0,dy);
}

滚动到顶部

function scrollToTop(containerEl){
let dy=-(containerEl.scrollHeight-containerEl.clientHeight);
containerEl.scrollBy(0,dy);
}

添加动画

这里我们修改一下动画生成的函数,因为这里我们 scrollBy() 的参数就是变量的偏移量,所以做出如下修改:

function scrollToBottom(containerEl){
if(!containerEl){
containerEl=container;
}
//dy即为偏移量
let dy=containerEl.scrollHeight-containerEl.clientHeight;
let scrollAnimationFn=doAnimation(dy,300,containerEl);
let interval=setInterval(()=>{
scrollAnimationFn(interval)
},10)
}
function scrollToTop(containerEl){
if(!containerEl){
containerEl=container;
}
//dy即为偏移量
let dy=-(containerEl.scrollHeight-containerEl.clientHeight);
let scrollAnimationFn=doAnimation(dy,300,containerEl);
let interval=setInterval(()=>{
scrollAnimationFn(interval)
},10)
}
function scrollToElement(containerEl,el){
if(!containerEl){
containerEl=container;
}
if(!el){
let input=document.getElementsByTagName('input')[0];
let id='item'+input.value;
if(!input.value){
id='item'+index;
}
el=document.getElementById(id);
}
//dy即为偏移量
let dy=el.getBoundingClientRect().top;
let scrollAnimationFn=doAnimation(dy,300,containerEl);
let interval=setInterval(()=>{
scrollAnimationFn(interval)
},10)
}
/**
* @description:
* @param {type}
* @return:
*/
function doAnimation(dy,duration,el){
//使用闭包保存变量exe_dy和step等变量(每次动画滚动的距离)
let exe_dy=0;//已经执行的偏移量
let step=dy/(duration/10);
return function(interval){
exe_dy+=step;
if(Math.abs(exe_dy)>=Math.abs(dy)){
clearInterval(interval);
}
el.scrollBy(0,step);
}
}

执行效果与使用 scrollTop 实现一致。

标签: 暂无
最后更新:2022年6月7日

Rosmontis

这个人很懒,什么都没留下

点赞

文章评论

取消回复

Rosmontis

这个人很懒,什么都没留下

本站文章约1个月与rosmontis.com同步一次

链接可将rosmontis.net改为com查看更多内容

最新 热点 随机
最新 热点 随机
【拉环社】【Onedrive】仰望夜空的星辰Fine Days/抬头看看吧,看那天上的繁星Fine Days(FD)完整汉化+全CG(4.9GB) 【拉环社】【Onedrive】仰望夜空的星辰IF/抬头看看吧,看那天上的繁星IF -Interstellar Focus-(FD)完整汉化+全CG(2.8GB) 【漩涡社】鲸神的提亚斯提拉/鲸神的Tearstilla 鯨神のティアスティラ 完整汉化+全CG(3.2GB) 【拉环社】【Onedrive】仰望夜空的星辰/抬头看看吧,看那天上的繁星(本作) 见上げてごらん、夜空の星を 完整汉化+全CG(6.5GB) 【SAGA PLANETS】【Onedrive】FD:金色loveriche-金色时光- 金色ラブリッチェ -Golden Time- 完整汉化+全CG(5.5GB) 【SAGA PLANETS】【Onedrive】金辉恋曲四重奏/金色Loveriche 金色ラブリッチェ 完整汉化+全CG(5.6GB) 【Onedrive】娇蛮任性HIGHSPEC ワガママハイスペック 完整汉化(7.2GB) 【Alcot】【Onedrive】FD:将军大人芳华正茂 Fandisc 将軍様はお年頃 ふぁんでぃすく -御三家だヨ!全員集合- 完整汉化+全CG(3.0GB) 【Alcot】【Onedrive】将军大人芳华正茂/将军大人风华正茂 将军様はお年顷 完整汉化+全CG(4.20GB) 国产动画《京剧猫》,被运营耽搁的好动画,哀其不幸怒其不争! 【Onedrive】架向星空之桥AA 架向星空之桥FAN DISC 星空へ架かる桥AA 完整汉化(3.6GB) 【Onedrive】架向星空之桥 星空へ架かる桥 完整汉化(4.3GB) 【颜艺社】【Onedrive】寄宿之恋 かりぐらし恋爱 完整汉化+全CG(2.7GB) 【八月社】【Onedrive】秽翼的尤斯蒂娅 秽翼のユースティア 完整汉化(4.7GB) 【橘子社妈妈累】【Onedrive】回家之前的棉花糖 お家に帰るまでがましまろです 完整汉化+全CG(5.8GB) 【SAGA PLANETS】【Onedrive】花之天使的夏日恋歌 フローラル・フローラブ 完整汉化+全CG(3.7GB) 【音符社】【Onedrive】花与乙女的祝福+花与乙女的祝福 皇家花束 完整汉化(共3.9GB) 【2022.06更新】【Onedrive】最全!花吻在上/亲吻那片花瓣 その花びらにくちづけを 1~20本作+3番外共23作 完整汉化(约10.5GB) 【Onedrive】花色温泉乡/花色七芒星 花色ヘプタグラム 完整汉化(3.6GB) 【CRYSTALIA】红月摇曳的恋之星火SS 与旭同往~来自盛夏的某日~ 旭とワンルーム ~とある夏の一日~ 完整汉化+全CG (550MB) 【CRYSTALIA】红月摇曳的恋之星火SS 与红叶同住 ~来自盛夏的某日~ 紅葉とワンルーム ~とある夏の一日~ 完整汉化+全CG (580MB) 【CRYSTALIA】红月摇曳的恋之星火 紅月ゆれる恋あかり 完整汉化+全CG (2.5GB) 【Onedrive】FD:景之海的艾佩莉亚 ~卡萨布兰卡的骑士~ 景の海のアペイリア ~カサブランカの騎士~ 完整汉化+全CG(2.3GB) 【Onedrive】景之海的艾佩莉娅/海景的艾佩利雅 景の海のアペイリア 完整汉化+全CG(3.0GB) 【柚子社】【Onedrive】管乐恋曲!~The bonds of melody~ ぶらばん! ~The bonds of melody~ 完整汉化(3.0GB) 【Onedrive】【妹抱FD】哥哥,早上起床之前都要抱紧我哦!晚上睡觉之前学更多Java吧!完整汉化+全CG(4.4GB) 【Onedrive】哥哥,早上起床之前都要抱紧我哦!(妹抱)お兄ちゃん、朝までずっとギュってして!完整汉化+全CG(7.0GB) 【SLG】夏日狂想曲:乡间的难忘回忆 【拉环社】【Onedrive】在这苍穹展翅/在这苍穹之中展开双翼 この大空に、翼をひろげてIf My Heart Had Wings 完整汉化(4.3GB) 【拉环社】【Onedrive】在这苍穹展翅-飞行日志- If My Heart Had Wings -Flight Diary- この大空に、翼をひろげて FLIGHT DIARY 完整汉化(3.0GB)
【SLG】夏日狂想曲:乡间的难忘回忆【海豹社】【Onedrive】爱之钥系列 爱之钥田园夏日 アイカギ~アフターデイズ~ 完整汉化+全CG(1.4GB)【SAGA PLANETS】【Onedrive】FD:金色loveriche-金色时光- 金色ラブリッチェ -Golden Time- 完整汉化+全CG(5.5GB)【Onedrive】娇蛮任性HIGHSPEC ワガママハイスペック 完整汉化(7.2GB)【Onedrive】骑士系列 恋骑士Purely☆Kiss 完整汉化+全CG(3.6GB)【CRYSTALIA】红月摇曳的恋之星火 紅月ゆれる恋あかり 完整汉化+全CG (2.5GB)【SAGA PLANETS】【Onedrive】金辉恋曲四重奏/金色Loveriche 金色ラブリッチェ 完整汉化+全CG(5.6GB)【拉环社】【Onedrive】仰望夜空的星辰Fine Days/抬头看看吧,看那天上的繁星Fine Days(FD)完整汉化+全CG(4.9GB)【Onedrive】FD:景之海的艾佩莉亚 ~卡萨布兰卡的骑士~ 景の海のアペイリア ~カサブランカの騎士~ 完整汉化+全CG(2.3GB)【Onedrive】景之海的艾佩莉娅/海景的艾佩利雅 景の海のアペイリア 完整汉化+全CG(3.0GB)【Onedrive】哥哥,早上起床之前都要抱紧我哦!(妹抱)お兄ちゃん、朝までずっとギュってして!完整汉化+全CG(7.0GB)【CRYSTALIA】红月摇曳的恋之星火SS 与红叶同住 ~来自盛夏的某日~ 紅葉とワンルーム ~とある夏の一日~ 完整汉化+全CG (580MB)【CRYSTALIA】红月摇曳的恋之星火SS 与旭同往~来自盛夏的某日~ 旭とワンルーム ~とある夏の一日~ 完整汉化+全CG (550MB)【Onedrive】花色温泉乡/花色七芒星 花色ヘプタグラム 完整汉化(3.6GB)【2022.06更新】【Onedrive】最全!花吻在上/亲吻那片花瓣 その花びらにくちづけを 1~20本作+3番外共23作 完整汉化(约10.5GB)【音符社】【Onedrive】花与乙女的祝福+花与乙女的祝福 皇家花束 完整汉化(共3.9GB)【SAGA PLANETS】【Onedrive】花之天使的夏日恋歌 フローラル・フローラブ 完整汉化+全CG(3.7GB)【橘子社妈妈累】【Onedrive】回家之前的棉花糖 お家に帰るまでがましまろです 完整汉化+全CG(5.8GB)【八月社】【Onedrive】秽翼的尤斯蒂娅 秽翼のユースティア 完整汉化(4.7GB)【颜艺社】【Onedrive】寄宿之恋 かりぐらし恋爱 完整汉化+全CG(2.7GB)【Onedrive】架向星空之桥 星空へ架かる桥 完整汉化(4.3GB)【Onedrive】架向星空之桥AA 架向星空之桥FAN DISC 星空へ架かる桥AA 完整汉化(3.6GB)国产动画《京剧猫》,被运营耽搁的好动画,哀其不幸怒其不争!【Alcot】【Onedrive】将军大人芳华正茂/将军大人风华正茂 将军様はお年顷 完整汉化+全CG(4.20GB)【Alcot】【Onedrive】FD:将军大人芳华正茂 Fandisc 将軍様はお年頃 ふぁんでぃすく -御三家だヨ!全員集合- 完整汉化+全CG(3.0GB)【拉环社】【Onedrive】仰望夜空的星辰/抬头看看吧,看那天上的繁星(本作) 见上げてごらん、夜空の星を 完整汉化+全CG(6.5GB)【漩涡社】鲸神的提亚斯提拉/鲸神的Tearstilla 鯨神のティアスティラ 完整汉化+全CG(3.2GB)【拉环社】【Onedrive】仰望夜空的星辰IF/抬头看看吧,看那天上的繁星IF -Interstellar Focus-(FD)完整汉化+全CG(2.8GB)【雪碧社Sprite】【Onedrive】苍之彼方的四重奏EXTRA2 DL Edition 蒼の彼方のフォーリズム EXTRA2 生肉+全CG(3.5GB)【Onedrive】爱因斯坦携爱敬上APOLLOCRISIS アインシュタインより愛を込めて APOLLOCRISIS 汉化本体+全CG(2.3GB)
在html文档中嵌入css的三种常用方式 使用虚拟信用卡VISA外币卡白嫖AWS一年免费云服务器 Zabbix Web页面报错:Received empty response from Zabbix Agent at [xxx.xxx.xxx.xxx]. Assuming that agent dropped connection because of access permission. 日常发椿 【Onedrive】骑士系列 恋骑士Purely☆Kiss 完整汉化+全CG(3.6GB) Python Django 性能测试与优化指南 小丛雨ヾ(≧▽≦*)o 【CRYSTALiA】【Onedrive/百度云】和椿同往-共结情缘的剑舞恋曲SS 椿とワンルーム -絆きらめく恋いろはSS- DL版&特典(400MB) 【拉环社PULLTOP】【Onedrive】白熊铃星群 しろくまベルスターズ♪ 未来数位繁体中文代理版(4.3GB) 【Onedrive】冥契的牧神节-冥契のルペルカリア 汉化 (3.4G) 【雪碧社Sprite】【Onedrive】苍之彼方的四重奏EXTRA2 DL Edition 蒼の彼方のフォーリズム EXTRA2 生肉+全CG(3.5GB) 利用div+CSS3实现一个背景渐变的button按钮的示例代码 【雪碧社Sprite】【Onedrive】苍之彼方的四重奏EXTRA1 蒼の彼方のフォーリズム 完整汉化+全CG(3.3GB) 详解XHTML中的标题标签与段落标签的使用 【鬼畜病毒评测】骨髅病毒视频 【Onedrive】架向星空之桥 星空へ架かる桥 完整汉化(4.3GB) 【Onedrive】爱因斯坦携爱敬上 アインシュタインより愛を込めて 汉化本体+全CG(3.9GB) 【Onedrive】【妹抱FD】哥哥,早上起床之前都要抱紧我哦!晚上睡觉之前学更多Java吧!完整汉化+全CG(4.4GB) html+css实现充电水滴融合特效代码 【音符社】【Onedrive】有少女涂彩的爱之芬芳 乙女が彩る恋のエッセンス (4.5 GB) 用VB实现一个小星星屏保 【明日方舟解包】【spine】帕拉斯 贴图立绘+动态骨架文件 腾讯云TDSQL-C MYSQL版云数据库参数设置详解 【明日方舟】【YOUTUBE转载】轮到蒂蒂给你洗脑了 【Onedrive】吃醋大作战 ヤキモチストリーム 完整汉化+全CG(6.3 GB) Django—使用PyJWT模块实现Token认证 【八月社】【百度云】千之刃涛、桃花染之皇姬-柳暗花明(FD)完整汉化版+全CG存档【5.2G】 【拉环社】【Onedrive】仰望夜空的星辰Fine Days/抬头看看吧,看那天上的繁星Fine Days(FD)完整汉化+全CG(4.9GB) 2022,新年快乐 炫酷的可视化web日志分析工具Logstalgia

COPYRIGHT © 2022 Rosmontis&迷迭香的博客&鹤望兰分部. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang