好吧,想象一下我这里有一个非常简单的场景。<div>一个CSS 属性为 的容器overflow-x: scroll,宽度为 500px(不溢出的可见宽度),并且有 9 个子容器。1 至 4 号和 6 至 9 号儿童的宽度为 100 像素,5 号(中间一个)的宽度为 200 像素,总共 1200 像素(总滚动宽度)。
<nav class="scrollable">
<div style="width: 100px;">1</div>
<div style="width: 100px;">2</div>
<div style="width: 100px;">3</div>
<div style="width: 100px;">4</div>
<div style="width: 100px;">5</div>
<div style="width: 100px;">6</div>
<div style="width: 100px;">7</div>
<div style="width: 100px;">8</div>
<div style="width: 100px;">9</div>
</nav>
Run Code Online (Sandbox Code Playgroud)
.scrollable {
position: relative;
display: flex;
flex-shrink: 0;
width: 500px;
overflow-x: scroll;
}
.scrollable > div {
flex-shrink: 0;
text-align: center;
cursor: pointer;
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,一切都很好。所以现在的目标是,每当我们单击这些子元素<div>(1 到 9)之一时,父元素的滚动位置都会将其自身移动到尽可能靠近被单击的子元素,正如我在下面尝试说明的那样。浅蓝色的子项是当前选定的子项:
正如您所看到的,元素 1-3 和 7-9 的滚动保持不变,元素 4 和 6 的滚动左右移动,子元素 5 的滚动到达绝对中心。
我们可以通过属性来控制父元素的滚动位置parent.scrollLeft。除此之外,我们还可以分别使用parent.clientWidth和获取它的可见宽度或总宽度(包括溢出) parent.scrollWidth。
除此之外,每个子元素都有自己的可见宽度,并且.offsetLeft正确地告诉我们它距离父元素左角有多远。
有了所有这些信息,我几乎就实现了我最初的目标。
// event handler for the inner tabs
document.body.addEventListener('click', function (event) {
if (event.target.closest('.scrollable > div')) {
// the parent <div>
const parent = event.target.closest('.scrollable');
// the selected/clicked <div>
const selected = event.target.closest('.scrollable > div');
// center the parent's scrollbar around the selected/clicked child
parent.scrollLeft = selected.offsetLeft - (selected.offsetWidth * 2);
}
});
Run Code Online (Sandbox Code Playgroud)
但这里唯一的问题是,只有当所有元素具有相同的宽度时,此计算才有效。但是一旦我更改单个元素的宽度,滚动条就不再正确对齐。如下例所示,5号子节点的宽度为200px,其余的仍为100px:
显然这const selected = event.target.closest('.scrollable > div');不是我需要在这里使用的正确公式,但是在花了几个小时研究这个公式和多种变体之后,我无法找出正确的公式。
任何帮助将不胜感激。谢谢。
解决方案:
好吧,我必须承认这超出了我的想象,但是经过大量的头脑风暴和试验结束错误后,以下是在将来有人偶然发现同样问题的奇怪机会时需要做的事情。
首先你得到parent.clientWidth,即容器的可见区域scrollable(没有溢出),然后.offsetWidth从中减去被单击元素自己的宽度( )。
将该值除以二。
最后,将 设为parent.scrollLeft等于单击的子项的值.offsetLeft,并从中减去我们之前计算的值。
const remainingSpace = parent.clientWidth - target.offsetWidth;
const spaceLeftAndRight = remainingSpace / 2;
parent.scrollLeft = target.offsetLeft - spaceLeftAndRight;
Run Code Online (Sandbox Code Playgroud)
2022 年末编辑:
如果滚动未按您预期的方式工作且未正确居中,请确保父容器 ( scrollable) 已position设置为relative。否则,offsetLeft每个子项的属性<div>在测量时将考虑整个视口,而不仅仅是其父项 ( scrollable)。
| 归档时间: |
|
| 查看次数: |
2539 次 |
| 最近记录: |