给滚动添加反弹效果

7
我正在尝试创建平滑的滚动体验,并在用户过度滚动时添加反弹效果,即向顶部或底部滚动太多。这个答案回答了如何平滑滚动,但我也想在滚动超出边界时反弹。类似于这样:
注意。虽然此gif适用于移动设备,但我希望将其实现在所有浏览器上,包括桌面和移动设备。

enter image description here

我尝试将以下代码添加到间隔中:
// 50 = Padding
if (tgt.scrollTop < 50 || tgt.scrollTop > tgt.scrollHeight - tgt.offsetHeight - 50) {
    pos = Math.bounce(step++, start, change, steps);
} else {
    pos = Math.easeOut(step++, start, change, steps);
}

但是它没有产生期望的效果。它没有在正确的滚动时间弹跳,并且弹跳不够真实,不够大。
(我正在寻找像this effect这样的东西,但我想要自己创建并理解代码。)
如何在滚动到顶部或底部时创建弹跳效果?
我不希望得到一个链接到复杂库的答案,因为我想自己创建,而且我想使用原生 JavaScript。

JSFiddle

console.clear();

/* Smooth scroll */
Math.easeOut = function(t, b, c, d) {
  t /= d;
  return -c * t * (t - 2) + b;
};

// Out Back Quartic
Math.bounce = function(t, b, c, d) {
  var ts = (t /= d) * t;
  var tc = ts * t;
  return b + c * (4 * tc + -9 * ts + 6 * t);
};

(function() { // do not mess global space
  var
    interval, // scroll is being eased
    mult = 0, // how fast do we scroll
    dir = 0, // 1 = scroll down, -1 = scroll up
    steps = 50, // how many steps in animation
    length = 30; // how long to animate
  function MouseWheelHandler(e) {
    e.preventDefault(); // prevent default browser scroll
    clearInterval(interval); // cancel previous animation
    ++mult; // we are going to scroll faster
    var delta = -Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
    if (dir != delta) { // scroll direction changed
      mult = 1; // start slowly
      dir = delta;
    }
    for (var tgt = e.target; tgt != document.documentElement; tgt = tgt.parentNode) {
      var oldScroll = tgt.scrollTop;
      tgt.scrollTop += delta;
      if (oldScroll != tgt.scrollTop) break;
    }
    var start = tgt.scrollTop;
    var end = start + length * mult * delta; // where to end the scroll
    var change = end - start; // base change in one step
    var step = 0; // current step
    interval = setInterval(function() {
      var pos;

      // 50 = Padding
      if (tgt.scrollTop < 50 || tgt.scrollTop > tgt.scrollHeight - tgt.offsetHeight - 50) {
        pos = Math.bounce(step++, start, change, steps);
      } else {
        pos = Math.easeOut(step++, start, change, steps);
      }
      tgt.scrollTop = pos;
      if (step >= steps) { // scroll finished without speed up - stop by easing out
        mult = 0;
        clearInterval(interval);
      }

    }, 10);
  }
  var myP = document.getElementById('myP');
  myP.addEventListener("mousewheel", MouseWheelHandler, false);
  // window.addEventListener("DOMMouseScroll", MouseWheelHandler, false);
})();
p {
  height: 300px;
  overflow: auto;
  background-color: orange;
  padding: 50px 0;
}
<p id="myP">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 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 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 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 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 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 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 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 tempus</p>


为何不对你链接的库进行逆向工程,以便了解他们是如何实现的呢? - The Muffin Man
这对我来说太复杂了。我不知道我应该看哪个实际部分。 - Jessica
如果您查看Github,源代码被分成小模块,例如https://github.com/idiotWu/smooth-scrollbar/blob/develop/lib/overscroll/bounce.js。 - The Muffin Man
2个回答

7

嗯,我是smooth-scrollbar的作者:)

实际上,这个问题可能比你想象的要复杂得多。现在我将展示一种基本的overscroll bouncing实现。演示

我们将使用CSS 3d transform来模拟反弹效果,因此DOM结构将是:

<article class="container">
    <section class="content">
        your content...
    </section>
</article>

首先要做的是创建一个渲染循环,将变换样式应用到.content中:
function render() {
    content.style.transform = `translate3d(...)`;

    requestAnimationFrame(render);
}

render();

现在,让我们初始化两个变量以记录状态:

let offset = 0;     // final position
let rendered = 0;   // rendered part

然后,应用具有阻尼因子的动量滚动:
const damping = 0.8;

function render() {
    ...
    const dis = offset - rendered;

    // throw away float part
    const next = offset - (dis * damping | 0);

    content.style.transform = `translate3d(0, ${-next}px, 0)`;
    rendered = next;
    ...
}

现在,我们可以滚动到想要的偏移量,但是弹回怎么处理呢?

神奇之处在于,在渲染时减少offset,因此offset的变化就像一个正常的曲线 - 从0到最高点,然后回落到0:

function render() {
    ...
    offset = offset / 2 | 0;
    ...
}

现在,render函数如下所示:
function render() {
    const dis = offset - rendered;

    // throw away float part
    const next = offset - (dis * damping | 0);

    content.style.transform = `translate3d(0, ${-next}px, 0)`;

    rendered = next;
    offset = offset / 2 | 0;

    requestAnimationFrame(render);
}

哦,看起来现在好多了!最后一步是处理输入事件(滚轮、触摸...),下面是处理滚轮事件的简单示例:

// wheel events handler
[
    'wheel',
    'mousewheel'
].forEach(name => {
    container.addEventListener(name, evt => {
        const { y } = getDelta(evt);
        const nextScroll = container.scrollTop + y;

        // check if scrolling onto very edge
        if (nextScroll > 0 &&
            nextScroll < container.scrollHeight - container.clientHeight
        ) {
            return;
        }

        evt.preventDefault();

        offset += y;
    });
});

好的,现在我们有了一个基础的弹跳模型。你可以在 Codepen 上检查完整的代码:http://codepen.io/idiotWu/pen/EgNdXK

然而,还有许多问题需要解决。例如,由于我们无法检测到用户是否离开了触摸板(比如 touchend 事件),我们不能像原生的滚动条一样执行回弹操作 - 当用户移开触摸板时向后滚动。因此,当超出滚动范围时,你可能会遇到抖动等问题。

为了避免抖动,可以设置一个标志,防止移动增加,就像我尝试过的那样。主要思想是在向后滚动时忽略鼠标滚轮事件。

===========

至于移动设备,你可以编写自己的触摸事件处理程序。但请记住,它不应该滚动回来,直到你松开手指,因此你可能需要另一个标志来保持offset不减少。这样做会有一点困难,因为有太多的状态要处理。

供参考:smooth-scrollbar/touch.js


4

这里是一个使用 Jquery 的快速尝试 - 可以通过鼠标滚轮来操作;以下是关键点:

  • 捕获“向上”鼠标滚轮事件
  • 增加元素的margin-top并使用transition进行动画处理
  • 设置最大偏移值和重置时间

查看以下代码片段:

$(function() {
  var more = 20;
  $('body').on('mousewheel', function(e) {
    if (e.originalEvent.wheelDelta / 120 > 0) {
      var st = $(window).scrollTop();
      if (st == 0 && more < 160) {
        $('div').css({
          'margin-top': more + 'px'
        });
        more += 20
      } else {
        $('div').css({
          'margin-top': '0'
        });
        more = 0;
      }
      setTimeout(function() {
        $('div').css({
          'margin-top': '0'
        });
        more = 0;
      }, 500)
    }
  })
});
body {
  background: #f6f6f6;
  height: 1000px;
  padding-top: 50px;
}
div {
  width: 80%;
  margin: 0 auto;
  background: white;
  height: 400px;
  transition: .3s margin linear;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>


或者Jsfiddle演示


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接