ScrollIntoView在移动设备(角度)上不平滑

时间:2019-08-27 13:35:54

标签: javascript angular scroll

我在Angular项目中创建了一个示例scrollIntoView。它在网络浏览器上效果很好。但是,当您在移动设备(Chrome或Safari)上查看时,该行为是不稳定的。它会跳到没有“平稳”行为的位置。

app.component.html

<button (click)="scroll('one')">One</button>
<button (click)="scroll('two')">Two</button>
<button (click)="scroll('three')">Three</button>
<button (click)="scroll('four')">Four</button>
<div id="one"></div>
<div id="two"></div>
<div id="three"></div>
<div id="four"></div>

app.component.ts

export class AppComponent  {
  name = 'Mobile scrollIntoView';

  scroll(id: string) {
    console.log(`scrolling to ${id}`);
    const el = document.getElementById(id);
    el.scrollIntoView({behavior: 'smooth', block: 'start', inline: 'nearest'});
  }
}

您可以通过stackblitz查看它-用手机打开:https://angular-nbpxk7.stackblitz.io

编辑模式:https://stackblitz.com/edit/angular-nbpxk7

我错过了什么吗?如何在移动设备上存档“流畅”的行为?谢谢,

1 个答案:

答案 0 :(得分:1)

角度似乎不是问题,而是cross-browser compatibility issue。 smooth属性不适用于几乎所有移动设备(Chrome和Firefox安卓系统除外)。

here中,您有另一种选择,但是您需要构建自定义实现的smooth scrollIntoView。

为此,我准备了一个自定义函数,您可以根据自己的代码在here中找到完整的工作示例。对于那些想要在有角度的基础应用程序上使用它的人,您只需要将以下函数添加到您的组件中,并通过传递desire dom元素来调用它:

scrollCustomImplementation(element: HTMLElement) {
    let start = null;
    let target = element && element ? element.getBoundingClientRect().top : 0;
    let firstPos = window.pageYOffset || document.documentElement.scrollTop;
    let pos = 0;

    (function () {
      var browser = ['ms', 'moz', 'webkit', 'o'];

      for (var x = 0, length = browser.length; x < length && !window.requestAnimationFrame; x++) {
        window.requestAnimationFrame = window[browser[x] + 'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[browser[x] + 'CancelAnimationFrame'] || window[browser[x] + 'CancelRequestAnimationFrame'];
      }
    })();

    function showAnimation(timestamp) {
      if (!start) {
        start = timestamp || new Date().getTime();
      } //get id of animation


      var elapsed = timestamp - start;
      var progress = elapsed / 600; // animation duration 600ms
      //ease in function from https://github.com/component/ease/blob/master/index.js

      var outQuad = function outQuad(n) {
        return n * (2 - n);
      };

      var easeInPercentage = +outQuad(progress).toFixed(2); // if target is 0 (back to top), the position is: current pos + (current pos * percentage of duration)
      // if target > 0 (not back to top), the positon is current pos + (target pos * percentage of duration)

      pos = target === 0 ? firstPos - firstPos * easeInPercentage : firstPos + target * easeInPercentage;
      window.scrollTo(0, pos);
      console.log(pos, target, firstPos, progress);

      if (target !== 0 && pos >= firstPos + target || target === 0 && pos <= 0) {
        cancelAnimationFrame(start);

        if (element) {
          element.setAttribute("tabindex", -1);
          element.focus();
        }

        pos = 0;
      } else {
        window.requestAnimationFrame(showAnimation);
      }
    }

    window.requestAnimationFrame(showAnimation);
  }