Плавная прокрутка генерирует неожиданную неопределенную ошибку свойства - PullRequest
1 голос
/ 30 января 2020

Я пытался реализовать какую-то плавную прокрутку. Я следовал этой кодовой ручке , чтобы создать такой свиток: https://codepen.io/osublake/pen/QqPqbN

Я пытался перевести на TypeScript / Angular, но он все равно выдает следующую ошибку - не когда updateScroller() вызывается внутри ngAfterViewInit, но когда я пытаюсь прокрутить в первый раз - указывая на const resized = this.scroller.resizeRequest > 0:

core.js:9110 ERROR TypeError: Cannot read property 'scroller' of undefined
    at updateScroller (app.component.ts:50)
    at ZoneDelegate.invokeTask (zone-evergreen.js:391)
    at Object.onInvokeTask (core.js:34182)
    at ZoneDelegate.invokeTask (zone-evergreen.js:390)
    at Zone.runTask (zone-evergreen.js:168)
    at invokeTask (zone-evergreen.js:465)
    at ZoneTask.invoke (zone-evergreen.js:454)
    at timer (zone-evergreen.js:2650)
export class AppComponent implements OnInit, AfterViewInit {

  scroller = {
    target: document.querySelector('.scrollable-container'),
    ease: 0.05,
    endY: 0,
    y: 0,
    resizeRequest: 1,
    scrollRequest: 0,
  };

  requestId = null;

  constructor(@Inject(PLATFORM_ID) private platformId) {
  }

  ngOnInit() {
    if (isPlatformBrowser(this.platformId)) {
      console.log('Hi, this is NØREBRO!');
    }
  }

  ngAfterViewInit(): void {
    setTimeout(() => {
      this.scroller.target = document.querySelector('.scrollable-container');

      TweenLite.set(this.scroller.target, {
        rotation: 0.01,
        force3D: true
      });

      this.updateScroller();
    });
    window.focus();
  }

  updateScroller() {
    const html = document.documentElement;
    const body = document.body;

    const resized = this.scroller.resizeRequest > 0;

    if (resized) {
      const height = this.scroller.target.clientHeight;
      body.style.height = height + 'px';
      this.scroller.resizeRequest = 0;
    }

    const scrollY = window.pageYOffset || html.scrollTop || body.scrollTop || 0;

    this.scroller.endY = scrollY;
    this.scroller.y += (scrollY - this.scroller.y) * this.scroller.ease;

    if (Math.abs(scrollY - this.scroller.y) < 0.05 || resized) {
      this.scroller.y = scrollY;
      this.scroller.scrollRequest = 0;
    }

    TweenLite.set(this.scroller.target, {
      y: -this.scroller.y
    });

    this.requestId = this.scroller.scrollRequest > 0 ? requestAnimationFrame(this.updateScroller) : null;
  }

  @HostListener('window:scroll', [])
  scroll() {
    this.scroller.scrollRequest++;
    console.log(this.requestId);
    if (!this.requestId) {
      console.log('uff');
      this.requestId = requestAnimationFrame(this.updateScroller);
    }
  }

}

1 Ответ

1 голос
/ 30 января 2020

Кажется, что this - это undefined при повторных вызовах методов. Не имея возможности отладить ваше приложение, я предполагаю, что вам нужно добавить this в качестве области действия для вашего this.updateScroller метода.

Область (this) функции всегда определяется контекстом выполнения, а при requestAnimationFrame функция вызывается вне контекста вашего экземпляра класса (компонента). Есть несколько интересных статей о сферах функций, например, см. this .

. Должны быть два способа решения вашей проблемы:

a) Заменить все requestAnimationFrame(this.updateScroller) звонки с

requestAnimationFrame(this.updateScroller.bind(this))

b) Заменить все requestAnimationFrame(this.updateScroller) звонки с

requestAnimationFrame(() => {
  this.updateScroller()
})
...