我一直在尝试实现某种平滑的滚动。我按照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);
}
}
}
[通过重复的方法调用,似乎this
是undefined
。在无法调试应用程序的情况下,我假设您需要将this
作为作用域添加到this.updateScroller
方法中。
函数的范围(this
)始终由执行上下文确定,使用requestAnimationFrame
时,该函数在类实例(组件)的上下文之外调用。关于功能范围有几篇有趣的文章,例如参见this。
应该有两种方法可以解决您的问题:
a)将所有requestAnimationFrame(this.updateScroller)
呼叫替换为
requestAnimationFrame(this.updateScroller.bind(this)
b)将所有requestAnimationFrame(this.updateScroller)
呼叫替换为
requestAnimationFrame(() => {
this.updateScroller()
})