我正在尝试创建一个与默认滚动条(带动画)一起滚动的拇指滚动条。我终于能够实现它,唯一的问题是,自定义滚动条不会在确切的位置滚动。如果您完全向下滚动,则拇指滚动条会越过其父元素。
此外,拇指滚动条大于默认滚动条。这是数学:
scrollBarThumb.style.height = (innerWrapper.parentElement.offsetHeight * innerWrapper.parentElement.offsetHeight / innerWrapper.scrollHeight) + 'px';
scrollBarPosition = clamp(scrollBarPosition, 0, scrolledToBottom)
scrollBarPosition = scrollBar.offsetHeight * scrollBarPosition / innerWrapper.scrollHeight;
我使用的公式是自定义滚动条的可接受公式。
这两个问题是:(它们可能是一个问题,因为我认为如果高度得到修复,那么滚动位置也会自动修复。)首先,滚动条拇指大于默认值。其次,当你一直向下滚动时,滚动条拇指会越过它的父颜色。
我做错了什么,我该如何解决?
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>
&#13;
答案 0 :(得分:0)
我认为你过度复杂化了
对于滚动,只需注册"scroll"
事件,
对于捕获延迟效果,请使用CSS3 transition
有关简单的数学,请参阅以下示例:
var content = document.querySelector("#content"),
scrollbar = document.querySelector("#scrollbar"),
handler = document.querySelector("#handler");
// FROM ELEMENT SCROLL TO HANDLER POSITION
function moveScrollbar() {
// Calculate scrollbar height
var height = content.clientHeight,
scrollHeight = content.scrollHeight,
handlerHeight = height * height / scrollHeight;
// Calculate scrollbar position
var handlerTop = content.scrollTop / height * handlerHeight;
handler.style.height = handlerHeight+'px';
handler.style.top = handlerTop+'px';
}
moveScrollbar(); // At init
content.addEventListener("scroll", moveScrollbar); // and on scroll
&#13;
body {
display: flex;
}
#content{
height:190px;
width:300px;
overflow-y:scroll;
font-size:3em;
}
#scrollbar{
position:relative;
background:orange;
width:30px;
}
#handler{
position:absolute;
top:0;
background:yellow;
width: 100%;
transition: 0.2s; /* ♪ */
}
&#13;
<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. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero
</div>
<div id="scrollbar">
<div id="handler" draggable="true"></div>
</div>
&#13;
当您决定构建点击拖动以使您的处理程序实际滚动内容时,您的数学也是如此:
// FROM HANDLER POSITION TO ELEMENT SCROLL:
var height = content.clientHeight,
scrollHeight = content.scrollHeight,
scrollPos = scrollHeight / height * handler.clientTop;