平滑滚动抛出意外的未定义 属性 错误
Smooth scroll throws unexpected undefined property error
我一直在尝试实现某种平滑滚动。我关注了 this codepen to create such scroll: https://codepen.io/osublake/pen/QqPqbN
我试图翻译成 TypeScript/Angular,但它仍然以某种方式抛出以下错误 - 不是在 ngAfterViewInit
内部调用 updateScroller()
时,而是当我第一次尝试滚动 - 指向 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
函数在 class 实例(组件)的上下文之外调用。有几篇关于函数作用域的有趣文章,例如参见 this。
应该有两种方法可以解决您的问题:
a) 将所有 requestAnimationFrame(this.updateScroller)
调用替换为
requestAnimationFrame(this.updateScroller.bind(this))
b) 将所有 requestAnimationFrame(this.updateScroller)
调用替换为
requestAnimationFrame(() => {
this.updateScroller()
})
我一直在尝试实现某种平滑滚动。我关注了 this codepen to create such scroll: https://codepen.io/osublake/pen/QqPqbN
我试图翻译成 TypeScript/Angular,但它仍然以某种方式抛出以下错误 - 不是在 ngAfterViewInit
内部调用 updateScroller()
时,而是当我第一次尝试滚动 - 指向 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
函数在 class 实例(组件)的上下文之外调用。有几篇关于函数作用域的有趣文章,例如参见 this。
应该有两种方法可以解决您的问题:
a) 将所有 requestAnimationFrame(this.updateScroller)
调用替换为
requestAnimationFrame(this.updateScroller.bind(this))
b) 将所有 requestAnimationFrame(this.updateScroller)
调用替换为
requestAnimationFrame(() => {
this.updateScroller()
})