简体   繁体   中英

Scrolltop animation is not working on IOS

I have made a JS effect to increase the line-height of each li of my website while you scroll. It is working nicely on my Macbook and my Android Smartphone but it doesn't on an iPhone. Does someone has a solution ?

function throttled(delay, fn) {
    let lastCall = 0;
    return function(...args) {
      const now = (new Date).getTime();
      if (now - lastCall < delay) {
        return;
      }
      lastCall = now;
      return fn(...args);
    }
  }

  const testElement = document.querySelectorAll("li");
  console.log(testElement.offsetTop);

  window.addEventListener("scroll", throttled(10, (e) => {
    for(let i = testElement.length-1;i>=0;i--){
      let posTopElement = (testElement[i].offsetTop)-600;
      if (document.documentElement.scrollTop > posTopElement) {
        window.requestAnimationFrame(function() {
          let minLineHeight = 4;
          let lineHeight = (window.scrollY - posTopElement) * 0.1;
          if (lineHeight < minLineHeight) lineHeight = minLineHeight;
          else if (lineHeight > 36) lineHeight = 36;
          testElement[i].style.lineHeight = lineHeight + "px";
        });
      } 
    }
  }));

So when I take your example js and drop it on top of some random list elements, it works for me in iOS Safari just as well as it does in macOS Chrome. But both are horribly chunky/janky because you're asking the browser to recalculate layout/flow in an almost recursive manner. When you update the line-height of a single li, you are reflowing the layout of all subsequent li elements. This is really expensive/inefficient. Instead of updating layout/flow related properties you should find a way to create the desired effect with paint or better yet composite related properties.

https://www.html5rocks.com/en/tutorials/speed/high-performance-animations/

If it were me, I'd try to find a way to use the transform property with unique translateY values for each li, after initially laying them out with a consistent line-height. This also has the benefit of not altering the height of the whole list with every update, making it so the scrollHeight of the window isn't being recalculated mid scroll over and over again.

 function throttled(delay, fn) { let lastCall = 0; return function(...args) { const now = (new Date).getTime(); if (now - lastCall < delay) { return; } lastCall = now; return fn(...args); } } const testElement = document.querySelectorAll("li"); console.log(testElement.offsetTop); window.addEventListener("scroll", throttled(10, (e) => { for(let i = testElement.length-1;i>=0;i--){ let posTopElement = (testElement[i].offsetTop)-600; if (document.documentElement.scrollTop > posTopElement) { window.requestAnimationFrame(function() { let minLineHeight = 4; let lineHeight = (window.scrollY - posTopElement) * 0.1; if (lineHeight < minLineHeight) lineHeight = minLineHeight; else if (lineHeight > 36) lineHeight = 36; testElement[i].style.lineHeight = lineHeight + "px"; }); } } })); 
 <!DOCTYPE html> <html> <head> <meta name="viewport" content="initial-scale=1, width=device-width, maximum-scale=1, user-scalable=no, shrink-to-fit=no, viewport-fit=cover"> <style> ul { min-height: 200vh; overflow: hidden; } </style> </head> <body> <ul> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> <li>hello world</li> </ul> </body> </html> 

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