自定义滚动条拇指超出范围
Custom scrollbars thumb goes out of bounds
我试图创建一个拇指滚动与默认滚动(动画)一起滚动。我希望最终能够实现它,唯一的问题是,自定义滚动条不能在精确位置滚动。如果你一直向下滚动,拇指滚动条就会越过它的父元素。
同时,拇指滚动条比默认滚动条大。计算方法如下:
scrollBarThumb.style.height = (innerWrapper.parentElement.offsetHeight * innerWrapper.parentElement.offsetHeight / innerWrapper.scrollHeight) + 'px';
scrollBarPosition = clamp(scrollBarPosition, 0, scrolledToBottom)
scrollBarPosition = scrollBar.offsetHeight * scrollBarPosition / innerWrapper.scrollHeight;
我使用的公式是可接受的自定义滚动条公式。
这两个问题是:(它们可能是一个问题,因为我认为如果高度固定,那么滚动位置也会自动固定。)首先,滚动条的拇指比默认值大。其次,当你向下滚动时,滚动条的拇指会越过它的父节点。
我做错了什么,我该如何修复它?
JSFiddle
console.clear();
var innerWrapper = document.getElementById('innerWrapper');
var scrollBar = document.getElementById('scrollbar');
var scrollBarThumb = scrollBar.firstElementChild
scrollBarThumb.style.height = (innerWrapper.parentElement.offsetHeight * innerWrapper.parentElement.offsetHeight / innerWrapper.scrollHeight) + 'px';
innerWrapper.addEventListener('mousewheel', handleScroll);
innerWrapper.addEventListener('DOMMouseScroll', handleScroll);
var duration = 35,
scrollSpeed = 2,
animateAmount = 30;
var scrolledToBottom = 0,
scrollDirection = 0, // 1 = scroll down, -1 = scroll up
animationID;
function handleScroll(e) {
// Cancel previous animation
cancelAnimationFrame(animationID);
// Scroll faster
scrollSpeed += 2;
// Reason for negative `-.wheelDelta` because Firefox
// return oposite value. See http://phrogz.net/js/wheeldelta.html
// Get 1 or -1
var delta = Math.max(-1, Math.min(1, (-e.wheelDelta || e.detail)));
// Check if scroll direction changed
if (scrollDirection != delta) {
scrollSpeed = 2; // Start slowly - restart speed
scrollDirection = delta;
}
var start = innerWrapper.parentElement.scrollTop,
end = start + animateAmount * scrollSpeed * delta, // Where to end the scroll
change = end - start, // base change in one scroll
step = 0, // current step in animation
tempScrollPosition; // Cannot assign any number yet (i.e. 0), because `scrollPosition` may be 0.
// Get amount of scrolled to bottom
scrolledToBottom = innerWrapper.scrollHeight - innerWrapper.parentElement.offsetHeight;
animationID = requestAnimationFrame(smoothScrollAnim); // Start animation
function smoothScrollAnim() {
animationID = requestAnimationFrame(smoothScrollAnim); // Restart animation
// Get scroll position
var scrollBarPosition = easeOut(step++, start, change, duration);
scrollBarPosition = clamp(scrollBarPosition, 0, scrolledToBottom)
scrollBarPosition = scrollBar.offsetHeight * scrollBarPosition / innerWrapper.scrollHeight;
// Apply scroll movement
scrollBarThumb.style.top = scrollBarPosition + 'px';
// Check if scroll finished (either animation finished, or bumped to top or bottom)
if (step >= duration || tempScrollPosition === scrollBarPosition) {
// Clean up
tempScrollPosition = null;
scrollSpeed = 2;
cancelAnimationFrame(animationID);
} else {
tempScrollPosition = scrollBarPosition;
}
}
}
function easeOut(time, begin, change, duration) {
time /= duration;
return -change * time * (time - 2) + begin;
}
function clamp(val, min, max) {
if (typeof min !== 'number') min = 0;
if (typeof max !== 'number') max = 1;
return Math.min(Math.max(val, min), max);
}
html {
height: 100%;
overflow-y: hidden;
}
body {
height: 100%;
overflow-y: hidden;
display: flex;
}
#outerWrapper {
height: 400px;
overflow: auto;
background-color: black;
}
#content {
background-image: url("http://images.freeimages.com/images/premium/previews/3037/30376024-beautiful-flower-portrait.jpg");
width: 400px;
}
#scrollbar {
height: 400px;
width: 50px;
background-color: orange;
border: 2px solid green;
}
#scrollbar_thumb {
background-color: yellow;
border: 2px solid blue;
position: relative;
}
<div id="outerWrapper">
<div id="innerWrapper">
<div id="content">
Lorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero
sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus
Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus
enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar
justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames
ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque
Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem
lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor Lorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie
vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum
vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque
Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci
Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla.
Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet
consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet
risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat
Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor
dolor
</div>
</div>
</div>
<div id="scrollbar">
<div id="scrollbar_thumb"></div>
</div>
对于滚动,只需注册"scroll"
事件,
对于捕获延迟效果,使用CSS3 transition
对于简单的数学,请参见下面的示例:
const el = (sel, par) => (par || document).querySelector(sel);
const
elContent = el("#content"),
elHandler = el("#handler");
// FROM ELEMENT SCROLL TO HANDLER POSITION
const moveScrollbar = () => {
const
height = elContent.clientHeight,
scrollHeight = elContent.scrollHeight,
handlerHeight = height ** 2 / scrollHeight,
handlerTop = elContent.scrollTop / height * handlerHeight;
Object.assign(elHandler.style, {
height: `${handlerHeight}px`,
top: `${handlerTop}px`
});
}
moveScrollbar(); // At init
elContent.addEventListener("scroll", moveScrollbar); // and on scroll
* { margin: 0; box-sizing: border-box; }
#area {
display: flex;
}
#content {
height: 160px;
width: 300px;
font-size: 3rem;
background: #eee;
padding: 1rem;
}
#content {
overflow-y: scroll;
scrollbar-width: none;
-ms-overflow-style: none;
}
#content::-webkit-scrollbar {
width: 0;
height: 0;
}
#scrollbar {
flex: none;
position: relative;
background: #333;
width: 1rem;
}
#handler {
position: absolute;
top: 0;
background: orange;
width: 100%;
transition: 0.2s; /* smooth move */
}
<div id="area">
<div id="content">
Scroll and see the custom scrollbar move.<br>Lorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis.
</div>
<div id="scrollbar">
<div id="handler"></div>
</div>
</div>
然后,要使处理程序可拖动,公式如下:
// FROM HANDLER POSITION TO ELEMENT SCROLL:
const
height = elContent.clientHeight,
scrollHeight = elContent.scrollHeight,
scrollPos = scrollHeight / height * elHandler.clientTop;
相关文章:
- CSS-若窗口太小,滚动条会出现在“表格”单元格上
- 禁用(而不是隐藏)浏览器滚动条
- 在firefox和chrome中的左侧显示iframe滚动条
- jquery:将动画绑定到滚动条位置的更好方法
- 在窗口中添加滚动条
- 如何查明鼠标按下事件是否发生在滚动条上或元素中的其他任何位置
- 使用没有插件的javascript自定义滚动条
- CodeMirror.禁用垂直滚动条
- 在滚动时,在隐藏滚动条和隐藏溢出的同时触发事件
- 可以'无法使滚动条正常工作
- 强制滚动条覆盖页面内容
- 如何隐藏滚动条,但希望它继续工作
- 滚动所有嵌套的滚动条,使HTML元素进入视图
- 使用浏览器滚动条而不是iframe滚动条
- 滚动条在关闭引导对话框后消失
- javascript/获取滚动条位置的回调
- 可调整滚动条大小
- 去掉滚动条
- 如何在点击按钮时隐藏/显示高图表的滚动条和范围选择器
- 自定义滚动条拇指超出范围