自定义滚动条拇指超出范围

时间:2016-09-17 00:53:11

标签: javascript scroll formula

我正在尝试创建一个与默认滚动条(带动画)一起滚动的拇指滚动条。我终于能够实现它,唯一的问题是,自定义滚动条不会在确切的位置滚动。如果您完全向下滚动,则拇指滚动条会越过其父元素。

此外,拇指滚动条大于默认滚动条。这是数学:

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>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

我认为你过度复杂化了 对于滚动,只需注册"scroll"事件,
对于捕获延迟效果,请使用CSS3 transition
有关简单的数学,请参阅以下示例:

&#13;
&#13;
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;
&#13;
&#13;

当您决定构建点击拖动以使您的处理程序实际滚动内容时,您的数学也是如此:

// FROM HANDLER POSITION TO ELEMENT SCROLL:
var height = content.clientHeight,
    scrollHeight = content.scrollHeight,
    scrollPos = scrollHeight / height * handler.clientTop;