按“偏移”设置的Div高度是生涩/滞后的

问题描述

在我的网络应用中,我尝试设置滚动事件的div高度,以产生UI效果和视差, 当我滚动到顶部时,Div会变大;当我滚动到底部页面时,Div会变小,以获得视差效果

我使用 @HostListener('window:scroll',['$ event'])来触发滚动,但它的工作却很不稳定,带有冻结帧,并具有随机延迟。

有人想到了为什么会有那么多的越野车吗?还是角度库可以通过性能优化做到这一点?

component.html:

    <div id="header" class="header" >
      <div class="coverBackgroundGradiantUp">  </div>
        <div class="coverBackgroundGradiantDown">
        </div>
    </div>

<div id="panel" class="panel" (scroll)="scrollHandler($event)">
{...bodypage...}
</div>

component.ts:

export class ProfilComponent implements OnInit {

  constructor() {
  }

  ngOnInit(): void {

  }


  @HostListener('window:scroll',['$event'])
  scrollHandler(event) {
    console.log(window.pageYOffset)
    const offset = window.pageYOffset
    if (offset < -1) {
      document.getElementById("headerHeight").style.width = String((100 - offset/6)+ "%");
      document.getElementById("headerHeight").style.height = String( 151 - offset + "px");
    } else if (offset < 151) {
      document.getElementById("headerHeight").style.height = String( 151 - offset + "px");
    } else if (offset > 151) {
      document.getElementById("headerHeight").style.height = String(0 + "px");
    }
  }

component.scss:

.header{
  position: fixed;
  display: flex;
  flex-direction: column-reverse;

  background-image: url("../../../../../assets/exempleCover.png");
  background-size: cover;
  background-repeat: no-repeat;

  width: 100%;
  height: 151px;
  top: 59px;
  background-color: red;
}

......

.panel{
  position: relative;
  top: 0;
  width: auto;
  margin-top: 146px;
  z-index: 2;
}

the scroll laggy

解决方法

当您订阅类似事件时,每次回调执行后(每次触发DOM事件并执行回调),角度运行都会发生变化检测。您需要在角度区域外手动订阅DOM事件。

最简单的方法是:

NgZone注入您的组件:

constuctor(private readonly ngZone: NgZone) { }

通过本机浏览器api订阅ngOnInit()中的滚动事件(也可以使用Renderer2):

this.zone.runOutsideAngular(() => {
  window.addEventListener('scroll',this.scrollHandler);
});

不要忘记退订ngOnDestroy()中的事件:

window.removeEventListener('scroll',this.scrollHandler);

scrollHandler函数更改为lambda格式,以绑定上下文并将来可以退订:

scrollHandler = (event) => {
  console.log(window.pageYOffset);
  const offset = window.pageYOffset;
  ...
}

我在编辑器中编写了代码,所以可能会有一些错字。

,

非常感谢阿米尔,

不幸的是,当我尝试使用renderer2时出现错误:

我有zone-evergreen.js:171未捕获的TypeError:无法读取未定义的属性'setAttribute',因为此面板未定义。

export class ProfilComponent implements OnInit,AfterViewInit {

  ***@ViewChildren('panel') panel: ElementRef;***

  constructor(private readonly ngZone: NgZone,private renderer: Renderer2){ }

  ngOnInit(): void {
    this.ngZone.runOutsideAngular(() => {
      window.addEventListener('scroll',this.scrollHandler);
    });
  }

  ngAfterViewInit() {

    console.log(this.panel);
  }


  scrollHandler(event) {
    **console.log(this.panel)**
    const offset = window.pageYOffset

    **this.renderer.setAttribute(this.panel.nativeElement,"id","panel")**;



    // if (offset < -1) {
    //   document.getElementById("headerHeight").style.width = String((100 - offset/6)+ "%");
    //
    //   document.getElementById("headerHeight").style.height = String( 151 - offset + "px");
    // } else if (offset < 151) {
    //   document.getElementById("headerHeight").style.height = String( 151 - offset + "px");
    // } else if (offset > 151) {
    //   document.getElementById("headerHeight").style.height = String(0 + "px");
    // }
  }