Анимация Scrolltop не работает на IOS - PullRequest
0 голосов
/ 31 мая 2019

Я сделал эффект JS, чтобы увеличить высоту строки каждого li моего веб-сайта во время прокрутки.Он отлично работает на моем Macbook и Android-смартфоне, но не на iPhone.У кого-нибудь есть решение?

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

1 Ответ

0 голосов
/ 24 июня 2019

Поэтому, когда я беру ваш пример js и помещаю его поверх некоторых случайных элементов списка, он работает для меня в iOS Safari так же, как и в macOS Chrome. Но и то, и другое ужасно коренасто, потому что вы просите браузер пересчитать макет / поток почти рекурсивным способом. Когда вы обновляете высоту строки одного li, вы перекомпоновываете макет всех последующих элементов li. Это действительно дорого / неэффективно. Вместо обновления свойств, связанных с макетом / потоком, вы должны найти способ создать желаемый эффект с помощью краски или более сложных, но связанных свойств.

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

Если бы это был я, я бы попытался найти способ использовать свойство transform с уникальными значениями translateY для каждого li после первоначального размещения их с постоянной высотой строки. Это также имеет то преимущество, что вы не изменяете высоту всего списка при каждом обновлении, благодаря чему scrollHeight окна не пересчитывается в середине прокрутки снова и снова.

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>
...