我想执行一些基于窗口重新大小事件(在加载和动态)的任务。
目前我的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);
}
}
我如何从这个事件对象检索宽度和高度?
谢谢。
我还没看到有人在谈论angular/cdk的MediaMatcher。
您可以定义一个MediaQuery并将一个侦听器附加到它-然后在模板(或ts)上的任何地方,如果匹配了Matcher,就可以调用东西。
LiveExample
App.Component.ts
import {Component, ChangeDetectorRef} from '@angular/core';
import {MediaMatcher} from '@angular/cdk/layout';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
mobileQuery: MediaQueryList;
constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher) {
this.mobileQuery = media.matchMedia('(max-width: 600px)');
this._mobileQueryListener = () => changeDetectorRef.detectChanges();
this.mobileQuery.addListener(this._mobileQueryListener);
}
private _mobileQueryListener: () => void;
ngOnDestroy() {
this.mobileQuery.removeListener(this._mobileQueryListener);
}
}
App.Component.Html
<div [class]="mobileQuery.matches ? 'text-red' : 'text-blue'"> I turn red on mobile mode
</div>
App.Component.css
.text-red {
color: red;
}
.text-blue {
color: blue;
}
来源:https://material.angular.io/components/sidenav/overview
在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)将在每次调用时触发更改检测。
如果你想在调整大小完成后只发生一个事件,最好使用RxJS和debounceTime:
debounceTime:丢弃输出间隔时间少于指定时间的发出值。
在运行代码之前,他在两个事件之间等待> 0.5s。
简单地说,它在执行下一个代码之前等待大小调整完成。
// RxJS v6+
import { fromEvent } from 'rxjs';
import { debounceTime, map } from 'rxjs/operators';
...
const resize$ = fromEvent(window, 'resize');
resize$
.pipe(
map((i: any) => i),
debounceTime(500) // He waits > 0.5s between 2 events emitted before running the next.
)
.subscribe((event) => {
console.log('resize is finished');
});
堆栈闪电战
下面是最新版本的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
};
};