使用 requestAnimationFrame 添加限制?

Adding throttling using requestAnimationFrame?

在下面的代码中,我根据 div (shadeFinder) 在 x 轴上滚动的距离成功地更改了左右箭头的 color。我想在此代码中添加节流。有人可以解释如何吗?我有下面 w3Schools 的示例,但发现很难将其合并到我的代码中。

//change the color of mobile arrows based on where the shadefinder is on X-axis
function changeArrowColor(){
  var shadeFinder = document.querySelector('.fms-wrapper');
  let leftArrow = document.querySelector('.prev');
  let rightArrow = document.querySelector('.next');
  let last_known_scroll_position = 0;
  let ticking = false;

  function doSomething(scroll_pos) {
    scroll_pos = parseInt(scroll_pos/10);
    leftArrow.style.color = `rgb(${scroll_pos},${scroll_pos},${scroll_pos})`;
    rightArrow.style.color = `rgb(${scroll_pos},${scroll_pos},${scroll_pos})`;
  }

  shadeFinder.addEventListener('scroll', function(e) {
    last_known_scroll_position = shadeFinder.scrollLeft;         
    doSomething(last_known_scroll_position);
  });   
}

带节流的 Mozilla 滚动事件示例:

// Reference: http://www.html5rocks.com/en/tutorials/speed/animations/

let last_known_scroll_position = 0;
let ticking = false;

function doSomething(scroll_pos) {
  // Do something with the scroll position
}

window.addEventListener('scroll', function(e) {
  last_known_scroll_position = window.scrollY;

  if (!ticking) {
    window.requestAnimationFrame(function() {
      doSomething(last_known_scroll_position);
      ticking = false;
    });

    ticking = true;
  }
});

requestAnimationFrame API takes a callback function that returns a timestamp(此处我将使用 RAF 作为 shorthand)。如果想用JS做动画,后面可以用时间戳调用cancelAnimationFrame。但如果仅用于节流,您暂时不需要存储此值。

因为您已经有一个名为 last_known_scroll_position 的变量,其范围在 doSomething 内使用,您不必将 scrollLeft 值传递给 RAF 函数,而是传递doSomething 作为滚动事件发生时将 last_known_scroll_position 设置为当前 scrollLeft 值后的回调。

该回调将接收一个 timestamp 参数,但您不需要它。回调可以根据 last_known_scroll_position.

的计算更新颜色

参见下面的示例。

function changeArrowColor(){
    var shadeFinder = document.querySelector('.fms-wrapper');
    let leftArrow = document.querySelector('.prev');
    let rightArrow = document.querySelector('.next');
    let last_known_scroll_position = 0;

    function doSomething(timestamp) {
        let scroll_pos = parseInt(last_known_scroll_position/10);
        let color = `rgb(${scroll_pos},${scroll_pos},${scroll_pos})`;
        console.clear()
        console.log({timestamp, color, last_known_scroll_position});
        leftArrow.style.color = color;
        rightArrow.style.color = color;
    }

    shadeFinder.addEventListener('scroll', function(e) {
        last_known_scroll_position = shadeFinder.scrollLeft;
        requestAnimationFrame(doSomething);
    });   
}

document.addEventListener("DOMContentLoaded", changeArrowColor);
body {
  padding:0;
  margin:20px 0;
}

.fms-wrapper {
  height: 80px;
  width: 100%;
  max-width: 100vw;
  overflow-y: hidden;
  overflow-x: scroll;
  position: relative;
  padding: 0 30px;
  margin: 0 5px;
  box-sizing: border-box;
  z-index:0;
  margin: 0;
}

.prev, .next {
  position: fixed;
  z-index: 5;
  width: 30px;
  height: 50px;
  font-size: 28px;
  line-height: 50px;
  box-sizing: border-box;
  cursor:pointer;
  color: black;
  background: white;
  box-shadow: 0 0 5px rgba(0,0,0,.5);
  text-align: center;
  pointer-events: auto;
}

.prev {
  left: 5px;
}

.next {
  right: 5px;
}

.fms-content {
  width: 400%;
  height: 50px;
  background: linear-gradient(90deg, #f0f0f0 0%, #f0f0f0 25%, #919191 25%, #919191 50%, #f0f0f0 50%, #f0f0f0 75%, #919191 75%, #919191 100%);
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
<div class="fms-wrapper">
  <div class="prev" tabindex="0"><</div>
  <div class="next" tabindex="0">></div>
  <div class="fms-content"></div>
</div>