平滑滚动引发意外的未定义属性错误

问题描述 投票:0回答:1

我一直在尝试实现某种平滑的滚动。我按照this codepen创建了这样的滚动条: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);
    }
  }

}
javascript html angular typescript gsap
1个回答
0
投票

[通过重复的方法调用,似乎thisundefined。在无法调试应用程序的情况下,我假设您需要将this作为作用域添加到this.updateScroller方法中。

函数的范围(this)始终由执行上下文确定,使用requestAnimationFrame时,该函数在类实例(组件)的上下文之外调用。关于功能范围有几篇有趣的文章,例如参见this

应该有两种方法可以解决您的问题:

a)将所有requestAnimationFrame(this.updateScroller)呼叫替换为

requestAnimationFrame(this.updateScroller.bind(this)

b)将所有requestAnimationFrame(this.updateScroller)呼叫替换为

requestAnimationFrame(() => {
  this.updateScroller()
})
© www.soinside.com 2019 - 2024. All rights reserved.