wake-up-neo.com

Ereignis zur Winkeländerung des Fensters

Ich möchte einige Aufgaben basierend auf dem Fenstergrößenänderungsereignis ausführen (beim Laden und dynamisch).

Derzeit habe ich mein DOM wie folgt:

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

Das Ereignis wird richtig ausgelöst

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

Wie rufe ich die Breite und Höhe von diesem Ereignisobjekt ab?

Vielen Dank.

147
DanAbdn
<div (window:resize)="onResize($event)"
onResize(event) {
  event.target.innerWidth;
}

oder

@HostListener('window:resize', ['$event'])
onResize(event) {
  event.target.innerWidth;
}

Unterstützte globale Ziele sind window, document und body.

Bis zur Implementierung von https://github.com/angular/angular/issues/13248 in Angular ist es für die Leistung besser, DOM-Ereignisse unbedingt zu abonnieren und RXJS zu verwenden, um die Anzahl der Ereignisse zu reduzieren, wie in einigen der Andere Antwort.

364

@ Günters Antwort ist richtig. Ich wollte nur eine andere Methode vorschlagen. 

Sie können die Host-Bindung auch in den @Component()- Decorator einfügen. Sie können das Ereignis und den gewünschten Funktionsaufruf wie folgt in die Host-Metadaten-Eigenschaft einfügen:

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  Host: {
    '(window:resize)': 'onResize($event)'
  }
})
export class AppComponent{
   onResize(event){
     event.target.innerWidth; // window width
   }
}
50
John

Der richtige Weg, dies zu tun, ist die Verwendung der EventManager Klasse, um das Ereignis zu binden. Dadurch kann Ihr Code auf alternativen Plattformen arbeiten, z. B. serverseitiges Rendern mit Angular Universal.

import { EventManager } from '@angular/platform-browser';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { Injectable } from '@angular/core';

@Injectable()
export class ResizeService {

  get onResize$(): Observable<Window> {
    return this.resizeSubject.asObservable();
  }

  private resizeSubject: Subject<Window>;

  constructor(private eventManager: EventManager) {
    this.resizeSubject = new Subject();
    this.eventManager.addGlobalEventListener('window', 'resize', this.onResize.bind(this));
  }

  private onResize(event: UIEvent) {
    this.resizeSubject.next(<Window>event.target);
  }
}

Die Verwendung in einer Komponente ist so einfach wie das Hinzufügen dieses Dienstes als Anbieter zu app.module und das Importieren in den Konstruktor einer Komponente.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'my-component',
  template: ``,
  styles: [``]
})
export class MyComponent implements OnInit {

  private resizeSubscription: Subscription;

  constructor(private resizeService: ResizeService) { }

  ngOnInit() {
    this.resizeSubscription = this.resizeService.onResize$
      .subscribe(size => console.log(size));
  }

  ngOnDestroy() {
    if (this.resizeSubscription) {
      this.resizeSubscription.unsubscribe();
    }
  }
}
28
cgatian

Hier ist ein besserer Weg, dies zu tun. Basierend auf Birowskys Antwort.

Schritt 1: Erstellen Sie einen angular service mit RxJS Observables .

import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs';

@Injectable()
export class WindowService {
    height$: Observable<number>;
    //create more Observables as and when needed for various properties
    hello: string = "Hello";
    constructor() {
        let windowSize$ = new BehaviorSubject(getWindowSize());

        this.height$ = (windowSize$.pluck('height') as Observable<number>).distinctUntilChanged();

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

}

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

Schritt 2: Fügen Sie die obige service ein und abonnieren Sie eine der innerhalb des Dienstes erstellten Observables, wo immer Sie das Fenster zur Größenänderung des Fensters erhalten möchten.

import { Component } from '@angular/core';
//import service
import { WindowService } from '../Services/window.service';

@Component({
    selector: 'pm-app',
    templateUrl: './componentTemplates/app.component.html',
    providers: [WindowService]
})
export class AppComponent { 

    constructor(private windowService: WindowService) {

        //subscribe to the window resize event
        windowService.height$.subscribe((value:any) => {
            //Do whatever you want with the value.
            //You can also subscribe to other observables of the service
        });
    }

}

Ein fundiertes Verständnis der reaktiven Programmierung hilft immer, schwierige Probleme zu überwinden. Hoffe das hilft jemandem.

24
Giridhar Karnik

Ich weiß, dass dies vor langer Zeit gefragt wurde, aber es gibt einen besseren Weg, dies jetzt zu tun! Ich bin mir nicht sicher, ob jemand diese Antwort sehen wird. Offensichtlich Ihre Importe:

import { fromEvent } from "rxjs/observable/fromEvent";
import { Observable } from "rxjs/Observable";
import { Subscription } from "rxjs/Subscription";

Dann in Ihrer Komponente:

resizeObservable$: Observable<Event>
resizeSubscription$: Subscription

ngOnInit() {
    this.resizeObservable$ = fromEvent(window, 'resize')
    this.resizeSubscription$ = this.resizeObservable$.subscribe( evt => {
      console.log('event: ', evt)
    })
}

Dann sollten Sie sich unbedingt abmelden um zu zerstören!

ngOnDestroy() {
    this.resizeSubscription$.unsubscribe()
}
15
Chris Stanley

Ich habe noch niemanden gesehen, der über MediaMatcher von angular/cdk Gesprochen hat.

Sie können eine MediaQuery definieren und einen Listener an sie anhängen. Anschließend können Sie an einer beliebigen Stelle in Ihrer Vorlage (oder Ihren Vorlagen) Inhalte aufrufen, wenn der Matcher übereinstimmt. 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;
}

quelle: https://material.angular.io/components/sidenav/overview

8
Stavm

Angenommen, <600px bedeutet für Sie mobil, können Sie dieses Observable verwenden und es abonnieren:

Zuerst benötigen wir die aktuelle Fenstergröße. Wir erstellen also ein Observable, das nur einen einzigen Wert ausgibt: die aktuelle Fenstergröße.

initial$ = Observable.of(window.innerWidth > 599 ? false : true);

Dann müssen wir ein weiteres Observable erstellen, damit wir wissen, wann die Fenstergröße geändert wurde. Dafür können wir den Operator "fromEvent" verwenden. Um mehr über die Betreiber von rxjs zu erfahren, besuchen Sie bitte: rxjs

resize$ = Observable.fromEvent(window, 'resize').map((event: any) => {
  return event.target.innerWidth > 599 ? false : true;
 });

Fassen Sie diese beiden Ströme zusammen, um unser Beobachtbares zu erhalten:

mobile$ = Observable.merge(this.resize$, this.initial$).distinctUntilChanged();

Jetzt können Sie es so abonnieren:

mobile$.subscribe((event) => { console.log(event); });

Denken Sie daran, sich abzumelden :)

6
Flosut Mözil

Basierend auf der Lösung von @cgatian würde ich folgende Vereinfachung vorschlagen:

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
      }));
  }
}

Verwendungszweck:

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) { }
}
3
Johannes Hoppe

Dies ist keine exakte Antwort auf die Frage, aber es kann jemandem helfen, der Größenänderungen an jedem Element erkennen muss.

Ich habe eine Bibliothek erstellt, die jedem Element - Angular Resize Event ein resized -Ereignis hinzufügt.

Es verwendet intern ResizeSensor aus CSS Element Queries .

Verwendungsbeispiel

HTML

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

Typoskript

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

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

Ich habe diese lib geschrieben, um zu finden, wenn sich die Größe der Komponentengrenzen in Angular geändert hat, kann dies anderen Menschen helfen. Sie können es in der Wurzelkomponente ablegen, wird das gleiche tun wie die Fenstergröße.

Schritt 1: Importieren Sie das Modul

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

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

Schritt 2: Fügen Sie die Anweisung wie folgt hinzu

<simple-component boundSensor></simple-component>

Schritt 3: Erhalte die Details zur Grenzgröße

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

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

Auf Angular2 (2.1.0) verwende ich ngZone, um das Bildschirmänderungsereignis zu erfassen.

Schauen Sie sich das Beispiel an:

import { Component, NgZone } from '@angular/core';//import ngZone library
...
//capture screen changed inside constructor
constructor(private ngZone: NgZone) {
    window.onresize = (e) =>
    {
        ngZone.run(() => {
            console.log(window.innerWidth);
            console.log(window.innerHeight);
        });
    };
}

Ich hoffe diese Hilfe!

1
Anh Hoang

Es gibt einen ViewportRuler Dienst in angular CDK. Es wird außerhalb der Zone ausgeführt und funktioniert auch beim serverseitigen Rendern.

0
Totati

Mit dem folgenden Code können Sie die Größenänderung für ein beliebiges div in Angular beobachten.

<div #observed-div>
</div>

dann in der Komponente:

oldWidth = 0;
oldHeight = 0;

@ViewChild('observed-div') myDiv: ElementRef;
ngAfterViewChecked() {
  const newWidth = this.myDiv.nativeElement.offsetWidth;
  const newHeight = this.myDiv.nativeElement.offsetHeight;
  if (this.oldWidth !== newWidth || this.oldHeight !== newHeight)
    console.log('resized!');

  this.oldWidth = newWidth;
  this.oldHeight = newHeight;
}
0
abedfar