与 Angular onscroll 事件一样的视差
Parallax like with Angular onscroll event
我试图用 Angular 和 OnScroll 事件创建一种视差,但是当滚动时出现的文本闪烁。你知道如何让onscroll的效果渲染更流畅吗?也许只有 CSS?
创建的脚本
https://stackblitz.com/edit/angular-b5cmf7?file=src%2Fapp%2Fapp.component.html
实现这个效果的主要函数就是这个
@HostListener('window:scroll', ['$event'])
isScrolledIntoView(){
const offsetHeight = this.testDiv.nativeElement.children[0].offsetHeight;
const rect = this.testDiv.nativeElement.getBoundingClientRect();
if( rect.bottom <= window.innerHeight){ // when the div is visible in viewport change the height (not more than the height of the content)
let height = (window.innerHeight - rect.bottom);
if(height<offsetHeight){
this.height = height;
}else{
this.height = offsetHeight
}
}
}
一看到您的闪电战,我就意识到了一个我 运行 多次遇到的问题。这与如何在 per-frame 基础上计算值有关。我不确定如何最好地用语言表达它,但它是这样的:
Don't base your calculations on values that will be modified by the result.
有点抽象,但具体到你的情况,问题出在rect.bot
和this.height
之间的关系上。每次调用 onscroll 函数时,您都会修改部分的高度。但是修改高度也会修改rect.bot的值,在下一个滚动事件中,你会得到不同的结果,所以高度从不同的基数修改,导致你观察到的振荡。
为避免这种情况,您希望所有计算仅基于不受结果影响的值。在这种情况下,我建议使用 rect.top
,它不关心该部分的高度是多少。
此外,我建议使用插值法,因为它可以让您更好地控制。这个想法是你想选择这些值:
- 显示应该在 window 高度的多少百分比处开始(实际上,
this.height = 0
)
- 该部分应在 window 高度的多少百分比处完全显示(
this.height = offsetHeight)
- 我应该如何在这两个值之间进行插值? (最简单的是线性的)
所以我分叉了你的闪电战,我继续前进并从这里彻底窃取了 clamp
和 invlerp
函数:
https://www.trysmudford.com/blog/linear-interpolation-functions/
您可以在 link.
中了解这些插值函数及其用途
你会看到我创建了两个名为“startPercentage”和“endPercentage”的变量——它们与 rect.top
的值相关,作为 window innerHeight 的百分比。您可以使用这些来获得不同的速度或视差质量,以获得您喜欢的效果。
这是叉子:
https://stackblitz.com/edit/angular-lcyc4q?file=src%2Fapp%2Fapp.component.ts
如果您愿意,可以研究其他插值函数,用 ease-in 和 ease-out 试验不同的效果。
我试图用 Angular 和 OnScroll 事件创建一种视差,但是当滚动时出现的文本闪烁。你知道如何让onscroll的效果渲染更流畅吗?也许只有 CSS?
创建的脚本 https://stackblitz.com/edit/angular-b5cmf7?file=src%2Fapp%2Fapp.component.html
实现这个效果的主要函数就是这个
@HostListener('window:scroll', ['$event'])
isScrolledIntoView(){
const offsetHeight = this.testDiv.nativeElement.children[0].offsetHeight;
const rect = this.testDiv.nativeElement.getBoundingClientRect();
if( rect.bottom <= window.innerHeight){ // when the div is visible in viewport change the height (not more than the height of the content)
let height = (window.innerHeight - rect.bottom);
if(height<offsetHeight){
this.height = height;
}else{
this.height = offsetHeight
}
}
}
一看到您的闪电战,我就意识到了一个我 运行 多次遇到的问题。这与如何在 per-frame 基础上计算值有关。我不确定如何最好地用语言表达它,但它是这样的:
Don't base your calculations on values that will be modified by the result.
有点抽象,但具体到你的情况,问题出在rect.bot
和this.height
之间的关系上。每次调用 onscroll 函数时,您都会修改部分的高度。但是修改高度也会修改rect.bot的值,在下一个滚动事件中,你会得到不同的结果,所以高度从不同的基数修改,导致你观察到的振荡。
为避免这种情况,您希望所有计算仅基于不受结果影响的值。在这种情况下,我建议使用 rect.top
,它不关心该部分的高度是多少。
此外,我建议使用插值法,因为它可以让您更好地控制。这个想法是你想选择这些值:
- 显示应该在 window 高度的多少百分比处开始(实际上,
this.height = 0
) - 该部分应在 window 高度的多少百分比处完全显示(
this.height = offsetHeight)
- 我应该如何在这两个值之间进行插值? (最简单的是线性的)
所以我分叉了你的闪电战,我继续前进并从这里彻底窃取了 clamp
和 invlerp
函数:
https://www.trysmudford.com/blog/linear-interpolation-functions/
您可以在 link.
中了解这些插值函数及其用途你会看到我创建了两个名为“startPercentage”和“endPercentage”的变量——它们与 rect.top
的值相关,作为 window innerHeight 的百分比。您可以使用这些来获得不同的速度或视差质量,以获得您喜欢的效果。
这是叉子:
https://stackblitz.com/edit/angular-lcyc4q?file=src%2Fapp%2Fapp.component.ts
如果您愿意,可以研究其他插值函数,用 ease-in 和 ease-out 试验不同的效果。