【问题标题】:Smooth scroll throws unexpected undefined property error平滑滚动抛出意外的未定义属性错误
【发布时间】:2020-01-31 03:40:56
【问题描述】:

我一直在尝试实现某种平滑滚动。我跟着this codepen创建了这样的卷轴:https://codepen.io/osublake/pen/QqPqbN

我试图翻译成 TypeScript/Angular,但不知何故仍会引发以下错误 - 不是在 ngAfterViewInit 内部调用 updateScroller() 时,而是在我第一次尝试滚动时 strong> - 指向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】:

    通过重复的方法调用,this 似乎是undefined。由于无法调试您的应用程序,我假设您需要将 this 作为范围添加到您的 this.updateScroller 方法中。

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

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

    a) 将所有 requestAnimationFrame(this.updateScroller) 调用替换为

    requestAnimationFrame(this.updateScroller.bind(this))
    

    b) 将所有requestAnimationFrame(this.updateScroller) 调用替换为

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      • 2012-10-01
      • 2020-04-26
      • 1970-01-01
      • 2015-10-04
      相关资源
      最近更新 更多