gpt4 book ai didi

javascript - 自定义滚动条,在拇指周围具有灵活、扩展的轨迹,就像引力透镜一样

转载 作者:行者123 更新时间:2023-12-04 11:29:03 25 4
gpt4 key购买 nike

我想实现一个带有灵活轨道的自定义滚动条,该轨道使用 CSS 围绕拇指展开。我试图实现类似引力透镜的效果,就好像拇指(红点)扭曲了它周围的空间(见下图)。引力透镜应随拇指移动。
我怎样才能做到这一点?
enter image description here

最佳答案

第一:可以仅使用 HTML 和 CSS 构建滚动条,但使用时需要 Javascript。

简单的滚动条
您可以使用 position 实现外观, borderborder-radius .轨道在左侧和右侧获得边框,拇指在所有侧面获得 border-radius: 50%另外还有一个白色 mask (轨道的宽度减去它的边界)用于隐藏轨道内的拇指边界。当然,您还需要红点。所有五个元素都得到一个 position: absolute .

<div id="scrollbar">
<div id="track"></div>
<div id="thumb">
<div class="white_mask"></div>
<div id="red_dot"></div>
</div>
</div>
基本 CSS (无尺寸)
#scrollbar {
position: absolute;
}

#track {
position: absolute;
border-right: 3px solid #000;
border-left: 3px solid #000;
}

#thumb {
position: absolute;
border: 1px solid #000;
border-radius: 50%;
background-color: white;
}

.white_mask {
position: absolute;
background-color: white;
}

#red_dot {
position: absolute;
border-radius: 50%;
background-color: #9c0000;
}

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

#container {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
}

#scrollbar {
position: absolute;
right: 100px;
top: 0;
width: 120px;
height: 100%;
z-index: 10;
}

#track {
position: absolute;
top: 0;
right: 20px;
width: 80px;
height: 100%;
border-right: 12px solid #000;
border-left: 12px solid #000;
}

#thumb {
position: absolute;
top: 0;
right: 0;
width: 120px;
height: 128px;
border: 4px solid #000;
border-top: 8px solid #000;
border-bottom: 8px solid #000;
border-radius: 50%;
background-color: white;
}

.white_mask {
position: absolute;
top: -8px;
right: 28px;
width: 56px;
height: 128px;
background-color: white;
}

.white_mask.big {
top: -16px;
right: 12px;
width: 88px;
height: 144px;
}

#thumb_mask {
position: absolute;
top: -16px;
left: 8px;
width: 96px;
height: 144px;
overflow: hidden;
}

.quarter_border {
position: absolute;
width: 80px;
height: 100px;
border-right: 12px solid #000;
border-left: 12px solid #000;
border-radius: 50%;
background-color: white;
}

.quarter_border.top {
top: -52px;
}

.quarter_border.right {
right: -60px;
}

.quarter_border.bottom {
bottom: -52px;
}

.quarter_border.left {
left: -60px;
}

#red_dot {
position: absolute;
top: 0;
left: 0;
width: 112px;
height: 112px;
border: 8px solid white;
border-radius: 50%;
background-color: #9c0000;
}
<div id="container">
<div id="scrollbar">
<div id="track"></div>
<div id="thumb">
<div class="white_mask"></div>
<div id="red_dot"></div>
</div>
</div>
</div>


高级滚动条
由于存在拇指和轨道彼此相遇的小 Angular ,您可以使用 overflow: hidden 在屏蔽 div 中添加四个带有圆形边框的额外 div。这样四个 div 中只有四分之一是可见的。您还需要在四个 div 下使用第二个白色 mask 来隐藏 Angular 落。
用于增加和减少 border-width您需要为上/下边框和左/右边框定义不同的值。此外,红点需要一个白色边框来平滑拇指边框的内部。
<div id="scrollbar">
<div id="track"></div>
<div id="thumb">
<div class="white_mask"></div>
<div class="white_mask small"></div>
<div id="thumb_mask">
<div class="quarter_border top right"></div>
<div class="quarter_border bottom right"></div>
<div class="quarter_border top left"></div>
<div class="quarter_border bottom left"></div>
</div>
<div id="red_dot"></div>
</div>
</div>
附加 CSS (无尺寸)
#thumb {
...
border-top: 2px solid #000;
border-bottom: 2px solid #000;
}

#thumb_mask {
position: absolute;
overflow: hidden;
}

.quarter_border {
position: absolute;
border-right: 3px solid #000;
border-left: 3px solid #000;
border-radius: 50%;
background-color: white;
}

#red_dot{
...
border: 2px solid white;
}

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

#container {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
}

#scrollbar {
position: absolute;
right: 100px;
top: 0;
width: 120px;
height: 100%;
z-index: 10;
}

#track {
position: absolute;
top: 0;
right: 20px;
width: 80px;
height: 100%;
border-right: 12px solid #000;
border-left: 12px solid #000;
}

#thumb {
position: absolute;
top: 0;
right: 0;
width: 120px;
height: 128px;
border: 4px solid #000;
border-top: 8px solid #000;
border-bottom: 8px solid #000;
border-radius: 50%;
background-color: white;
}

.white_mask {
position: absolute;
top: -4px;
right: 28px;
width: 56px;
height: 128px;
background-color: white;
}

.white_mask.big {
top: -16px;
right: 12px;
width: 88px;
height: 144px;
}

#thumb_mask {
position: absolute;
top: -16px;
left: 8px;
width: 96px;
height: 144px;
overflow: hidden;
}

.quarter_border {
position: absolute;
width: 80px;
height: 100px;
border-right: 12px solid #000;
border-left: 12px solid #000;
border-radius: 50%;
background-color: white;
}

.quarter_border.top {
top: -52px;
}

.quarter_border.right {
right: -60px;
}

.quarter_border.bottom {
bottom: -52px;
}

.quarter_border.left {
left: -60px;
}

#red_dot {
position: absolute;
top: 0;
left: 0;
width: 112px;
height: 112px;
border: 8px solid white;
border-radius: 50%;
background-color: #9c0000;
}
<div id="container">

<div id="scrollbar">
<div id="track"></div>
<div id="thumb">
<div class="white_mask"></div>
<div class="white_mask big"></div>
<div id="thumb_mask">
<div class="quarter_border top right"></div>
<div class="quarter_border bottom right"></div>
<div class="quarter_border top left"></div>
<div class="quarter_border bottom left"></div>
</div>
<div id="red_dot"></div>
</div>
</div>

</div>

不幸的是,宿舍并不完全适合拇指和跟踪。因此,将滚动条构建为 SVG 并操纵其组件可能是一种更好的方法。

基本的Javascript
有许多可能性和功能可以操作具有不同属性的滚动条,例如 top , scrollToptransform .我在这里仅用于演示 top以及一些基本功能(例如我省略了对 resize 上滚动位置的调整)。
基本常数
为了让滚动条首先工作,你需要三个常量 thumb_height (包括它的边界), scroll_range (最大拇指位置)和 diff_height (隐藏内容)。
const thumb_height = thumb.getBoundingClientRect().height;
const scroll_range = window.innerHeight - thumb_height;
const diff_height = content.scrollHeight - window.innerHeight
滚动功能
然后您需要滚动功能,如果拇指在滚动范围内,您可以在其中计算新的拇指位置和内容滚动和样式这两个元素。
内容滚动是初始隐藏内容的可见百分比。百分比计算方式为:拇指位置除以其最大值,滚动范围。
用于拖动拇指:
您可以从 mousedown 中的鼠标光标位置获得拇指位置。事件: e.clientY (由拇指高度的一半校正)。
您还必须确保当拇指位置变得太小或太大时,拇指不会消失,例如离开容器(这里是窗口)时。因此,您必须检查位置是否低于 0 或高于滚动范围,如果不是,则仅对元素进行样式设置。
function dragThumb(e) {
const thumb_pos = e.clientY - (thumb_height / 2);
const content_scroll = -diff_height * thumb_pos / scroll_range;

if (thumb_pos >= 0 && thumb_pos <= scroll_range) {
thumb.style.top = thumb_pos + 'px';
content.style.top = content_scroll + 'px';
}
}
鼠标滚轮:
您可以从实际 top 获得拇指位置拇指的属性增加或减少(取决于 wheel 事件中的鼠标滚轮方向: e.deltaY)固定数量 100 (您可以修改该值以更快或更慢地滚动)。
对于样式,您还必须处理两种极端情况,因为重击位置(以固定量计算)有时不会准确地“降落”在 0 或滚动范围上。你可以用 if 做到这一点块像 dragThumb() (您需要 3 个)或者您可以使用三元运算符 ? :就像在下面的代码片段中一样。
function scrollContent(e) {
const thumb_pos = parseInt(thumb.style.top) + (e.deltaY < 0 ? -100 : 100);
const content_scroll = -diff_height * thumb_pos / scroll_range;

thumb.style.top = thumb_pos < 0 ? 0 : (thumb_pos > scroll_range ? scroll_range : thumb_pos) + 'px';
content.style.top = thumb_pos < 0 ? 0 : (thumb_pos > scroll_range ? -diff_height : content_scroll) + 'px';
}
事件监听器
最后,您需要一个事件监听器,您可以在其中调用滚动函数。
鼠标滚轮:
document.addEventListener('wheel', scrollContent);
用于拖动拇指:
您需要两个额外的事件监听器,一个用于仅在最初单击拇指时监听鼠标移动,另一个用于在释放鼠标按钮时删除该鼠标移动监听器。
thumb.addEventListener('mousedown', function(e) {
e.preventDefault(); // fixed a bug with 'mouseup'
document.addEventListener('mousemove', dragThumb);
});

document.addEventListener('mouseup', function() {
document.removeEventListener('mousemove', dragThumb);
});

工作示例:
两个滚动函数都合并到函数 scrollContent() 中.拇指位置在两个事件处理程序(调用 scrollContent() )中计算: dragThumb()以及 wheel 的匿名函数事件。
这三个常数在复位函数 resetScroll() 中计算(因此定义为具有 let 的普通变量),在页面加载和窗口调整大小时调用。该函数还调用滚动函数 scrollContent()与实际拇指位置。
因为 mouseup 的事件监听器如果事件发生在堆栈片段之外,则为“聋”,我将其匿名函数转换为函数 stopDrag()被称为 mouseup 的事件处理程序和 mouseleave .

document.addEventListener('DOMContentLoaded', function() {

const thumb = document.getElementById('thumb');
const content = document.getElementById('content');
let thumb_height, scroll_range, diff_height;

function resetScroll() {
thumb_height = thumb.getBoundingClientRect().height;
scroll_range = window.innerHeight - thumb_height;
diff_height = content.scrollHeight - window.innerHeight;

scrollContent(parseInt(thumb.style.top));
}

function scrollContent(thumbPos) {
const newScroll = -diff_height * thumbPos / scroll_range;

thumb.style.top = thumbPos < 0 ? 0 : (thumbPos > scroll_range ? scroll_range : thumbPos) + 'px';
content.style.top = thumbPos < 0 ? 0 : (thumbPos > scroll_range ? -diff_height : newScroll) + 'px';
}

function dragThumb(e) {
scrollContent(e.clientY - (thumb_height / 2));
}

function stopDrag(e) {
document.removeEventListener('mousemove', dragThumb);
}

thumb.addEventListener('mousedown', function(e) {
e.preventDefault();
document.addEventListener('mousemove', dragThumb);
});

document.addEventListener('mouseup', stopDrag);
document.addEventListener("mouseleave", stopDrag);

document.addEventListener('wheel', function(e) {
if (!e.ctrlKey) {
scrollContent(parseInt(thumb.style.top) + (e.deltaY < 0 ? -100 : 100));
}
});

window.addEventListener('resize', resetScroll);

//initial reset
document.scrollTop = 0;
thumb.style.top = 0;

resetScroll();

});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

#container {
position: relative;
overflow: hidden;
}

#content {
position: relative;
top: 0;
right: 0;
width: 100vw;
height: 100vh;
padding-right: 40px;
}

#scrollbar {
position: absolute;
right: 5px;
top: 0;
width: 30px;
height: 100%;
z-index: 10;
}

#track {
position: absolute;
top: 0;
right: 5px;
width: 20px;
height: 100%;
border-right: 3px solid #000;
border-left: 3px solid #000;
}

#thumb {
position: absolute;
top: 0;
right: 0;
width: 30px;
height: 32px;
border: 1px solid #000;
border-top: 2px solid #000;
border-bottom: 2px solid #000;
border-radius: 50%;
background-color: white;
}

.white_mask {
position: absolute;
top: -3px;
right: 6px;
width: 14px;
height: 30px;
background-color: white;
}

.white_mask.big {
top: -4px;
right: 3px;
width: 22px;
height: 36px;
}

#thumb_mask {
position: absolute;
top: -4px;
left: 2px;
width: 24px;
height: 36px;
overflow: hidden;
}

.quarter_border {
position: absolute;
width: 20px;
height: 25px;
border-right: 3px solid #000;
border-left: 3px solid #000;
border-radius: 50%;
background-color: white;
}

.quarter_border.top {
top: -13px;
}

.quarter_border.right {
right: -15px;
}

.quarter_border.bottom {
bottom: -13px;
}

.quarter_border.left {
left: -15px;
}

#red_dot {
position: absolute;
top: 0;
left: 0;
width: 28px;
height: 28px;
border: 2px solid white;
border-radius: 50%;
background-color: #9c0000;
}
<div id="container">

<div id="scrollbar">
<div id="track"></div>
<div id="thumb">
<div class="white_mask"></div>
<div class="white_mask big"></div>
<div id="thumb_mask">
<div class="quarter_border top right"></div>
<div class="quarter_border bottom right"></div>
<div class="quarter_border top left"></div>
<div class="quarter_border bottom left"></div>
</div>
<div id="red_dot"></div>
</div>
</div>

<div id="content">
<p>first</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>last</p>
</div>

</div>

关于javascript - 自定义滚动条,在拇指周围具有灵活、扩展的轨迹,就像引力透镜一样,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61214763/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com