简体   繁体   中英

Adding throttling using requestAnimationFrame?

In the code below I'm successfully changing the color of the left and right arrows based on how far a div (shadeFinder) has scrolled on the x axis. I want to add throttling to this code. Can someone explain how? I have the example from w3Schools below but finding it hard to merge it into my code.

//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 scroll event example with throttling:

// 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;
  }
});

The requestAnimationFrame API takes a callback function that returns a timestamp (I'll use RAF as shorthand hereon). If you wanted to use JS to animate, you can use the timestamp to call cancelAnimationFrame later. But to use just for throttling, you don't necessarily need to store this value, for now.

Since you already have a variable called last_known_scroll_position scoped for used within doSomething , you don't have to pass the scrollLeft value to the RAF function, but instead pass the doSomething as the callback after setting the last_known_scroll_position to the current scrollLeft value at the time of the scroll event.

That callback will receive a timestamp parameter, but you don't need it. The callback can update the color based on a calculation from the last_known_scroll_position .

See the example below.

 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM