我想执行一些基于窗口重新大小事件(在加载和动态)的任务。

目前我的DOM如下:

<div id="Harbour">
    <div id="Port" (window:resize)="onResize($event)" >
        <router-outlet></router-outlet>
    </div>
</div>

事件正确触发

export class AppComponent {
    onResize(event) {
        console.log(event);
    }
}

我如何从这个事件对象检索宽度和高度?

谢谢。


当前回答

下面是最新版本的Rxjs对@GiridharKamik答案的更新。

import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject, fromEvent } from 'rxjs';
import { pluck, distinctUntilChanged, map } from 'rxjs/operators';

@Injectable()
export class WindowService {
    height$: Observable<number>;
    constructor() {
        const windowSize$ = new BehaviorSubject(getWindowSize());

        this.height$ = windowSize$.pipe(pluck('height'), distinctUntilChanged());

        fromEvent(window, 'resize').pipe(map(getWindowSize))
            .subscribe(windowSize$);
    }

}

function getWindowSize() {
    return {
        height: window.innerHeight
        //you can sense other parameters here
    };
};

其他回答

我写这个库是为了找到Angular中组件边界大小改变(重新调整大小)的方法,希望能帮助到其他人。你可以把它放在根组件上,会做和窗口大小调整一样的事情。

步骤1:导入模块

import { BoundSensorModule } from 'angular-bound-sensor';

@NgModule({
  (...)
  imports: [
    BoundSensorModule,
  ],
})
export class AppModule { }

步骤2:添加如下指令

<简单的组件boundSensor > < /简单的组件>

步骤3:接收边界大小的详细信息

import { HostListener } from '@angular/core';

@Component({
  selector: 'simple-component'
  (...)
})
class SimpleComponent {
  @HostListener('resize', ['$event'])
  onResize(event) {
    console.log(event.detail);
  }
}

在angular CDK中有一个ViewportRuler服务。它在区域外运行,支持方向改变和大小调整。它也适用于服务器端渲染。

@Component({
  selector: 'my-app',
  template: `
    <p>Viewport size: {{ width }} x {{ height }}</p>
  `
})
export class AppComponent implements OnDestroy {
  width: number;
  height: number;
  private readonly viewportChange = this.viewportRuler
    .change(200)
    .subscribe(() => this.ngZone.run(() => this.setSize()));
  constructor(
    private readonly viewportRuler: ViewportRuler,
    private readonly ngZone: NgZone
  ) {
    // Change happens well, on change. The first load is not a change, so we init the values here. (You can use `startWith` operator too.)
    this.setSize();
  }
  // Never forget to unsubscribe!
  ngOnDestroy() {
    this.viewportChange.unsubscribe();
  }

  private setSize() {
    const { width, height } = this.viewportRuler.getViewportSize();
    this.width = width;
    this.height = height;
  }
}

ViewportRuler的Stackblitz示例

好处是,它限制了更改检测周期(它只会在区域中运行回调时触发),而(window:resize)将在每次调用时触发更改检测。

基于@cgatian的解决方案,我建议简化如下:

import { EventManager } from '@angular/platform-browser';
import { Injectable, EventEmitter } from '@angular/core';

@Injectable()
export class ResizeService {

  public onResize$ = new EventEmitter<{ width: number; height: number; }>();

  constructor(eventManager: EventManager) {
    eventManager.addGlobalEventListener('window', 'resize',
      e => this.onResize$.emit({
        width: e.target.innerWidth,
        height: e.target.innerHeight
      }));
  }
}

用法:

import { Component } from '@angular/core';
import { ResizeService } from './resize-service';

@Component({
  selector: 'my-component',
  template: `{{ rs.onResize$ | async | json }}`
})
export class MyComponent {
  constructor(private rs: ResizeService) { }
}

这是我创建的一个简单而干净的解决方案,这样我就可以将它注入到多个组件中。

ResizeService.ts

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ResizeService {

  constructor() {

    window.addEventListener('resize', (e) => {
      this.onResize.next();
    });

  }

  public onResize = new Subject();

}

在使用:

constructor(
  private resizeService: ResizeService
) { 

  this.subscriptions.push(this.resizeService.onResize.subscribe(() => {
    // Do stuff
  }));

}

private subscriptions: Subscription[] = [];

这并不是问题的确切答案,但它可以帮助那些需要检测任何元素的大小变化的人。

我已经创建了一个库,可以将调整大小的事件添加到任何元素中——Angular Resize event。

它内部使用resizsensor从CSS元素查询。

示例使用

HTML

<div (resized)="onResized($event)"></div>

打印稿

@Component({...})
class MyComponent {
  width: number;
  height: number;

  onResized(event: ResizedEvent): void {
    this.width = event.newWidth;
    this.height = event.newHeight;
  }
}