Angular 4에서 실시간 창 크기 변경 감지


118

반응 형 내비게이션 바를 만들려고했지만 미디어 쿼리를 사용하고 싶지 않으므로 *ngIF창 크기를 기준으로 사용하려고합니다 . 그러나 Angular 4 창 크기 감지에 대한 방법이나 문서를 찾을 수 없기 때문에 문제가 발생했습니다. JavaScript 방법도 시도했지만 지원되지 않습니다.

또한 다음을 시도했습니다 .

constructor(platform: Platform) {
    platform.ready().then((readySource) => {
        console.log('Width: ' + platform.width());
        console.log('Height: ' + platform.height());
    });
}

... 이온 계에 사용되었습니다.

그리고 screen.availHeight, 그러나 여전히 성공하지 못했습니다.


1
무엇에 platform대해? Ionic에 관한 건가요?
Günter Zöchbauer

@ Günter Zöchbauer 플랫폼은 각도가 있으며 내가 시도한 코드를 언급하고 싶었습니다.
Ronit Oommen

1
PlatformIonic 서비스입니다. 그래서 Ionic 프로젝트라고 생각합니까?
robbannn


@BlackBeard Angular 2와 4가 얼마나 다른지로 인해 중복이라고 생각하지 않습니다.
tehlivi

답변:


260

init에서 얻으려면

public innerWidth: any;
ngOnInit() {
    this.innerWidth = window.innerWidth;
}

크기를 조정할 때 계속 업데이트하려면 다음을 수행하십시오.

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

2
this.innerWidth = event.target.innerWidth; ... 가능한 효율적 동일한 결과를 생성한다
danday74

2
또한 lodash를 사용하는 경우 생성자에서 이것을 권장합니다 ... this.onResize = debounce (this.onResize, 150, {leading : false, trailing : true}) ... onResize 메서드가 너무 자주 호출되는 것을 방지하기 위해 .. . 당신에게 ... 'lodash'에서 가져 오기 {디 바운스}이 필요합니다
danday74

내가 사용하는 것이 바람직 생각 ngAfterViewInit대신에 삶의 후크 방법 ngOnInit 생활 후크 방법
아메드 hamdy

39

특정 중단 점에 대해 반응하려면 (예 : 너비가 768px 미만인 경우 작업 수행) BreakpointObserver를 사용할 수도 있습니다.

import {BreakpointObserver, Breakpoints} from '@angular/cdk/layout';

{ ... }

const isSmallScreen = breakpointObserver.isMatched('(max-width: 599px)');

또는 중단 점의 변경 사항을 들어도됩니다.

breakpointObserver.observe([
  '(max-width: 768px)'
    ]).subscribe(result => {
      if (result.matches) {
        doSomething();
      } else {
        // if necessary:
        doSomethingElse();
      }
    });

당신은 관찰자가 기준과 일치하는 경우에만 작동 할 경우 내부에 추가이 가입있어 if (result.matches)그렇지 않으면이없는 경우에도 호출
karoluS

1
@karoluS : 물론입니다. 나는 그것을 명확하게하기 위해 내 대답을 편집했습니다. 감사합니다.
제레미 Benks

이것은 cdk특정 버전의 각도에 대한 피어 종속성 이있는 것 같습니다 . 최신의 경우 7처럼. 어쨌든 이전 버전 (질문에서와 같이 각도 4)에 이것을 사용할 수 있습니까?
LeOn-Han Li

@Leon li : 저는 실제로 각도 7을 사용합니다. 그러나 : 내가 아는 한 각도 4에서도 cdk를 사용할 수 있습니다. 이 블로그 게시물 에 따르면 cdk 2.x가 필요합니다. NPM @ 각도 / CDK @ 4 : 내가 아는 한,이 수동으로 설치하고 다음과 같이 지정된 버전으로해야한다
제레미 Benks

@JeremyBenks Y, 우리는 4.2.6특별히 ng를 사용하고 있습니다. CDK 2.x 버전을 찾을 수 없으며 4.1.x 및 4.3.x 만 있습니다. 어쨌든 감사합니다!
LeOn-Han Li

9

구성 요소를 쉽게 테스트 할 수 있도록하려면 Angular 서비스에서 전역 창 개체를 래핑해야합니다.

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

@Injectable()
export class WindowService {

  get windowRef() {
    return window;
  }

}

그런 다음 다른 서비스처럼 삽입 할 수 있습니다.

constructor(
    private windowService: WindowService
) { }

그리고 소비 ...

  ngOnInit() {
      const width= this.windowService.windowRef.innerWidth;
  }

2
나는 이미 당면한 것을 정확히하기 위해 서비스를하는 것에 대한 요점을 볼 수 없다. window.innerWidth.
Rodrigo 19

1
첫째, DI는 Angular 방식이며 구성 요소 / 지시문의 종속성을 더 명확하게 만듭니다. 그러나 여기에 언급 된 요점은 서비스를 사용하는 코드를 테스트하기 쉽게 만드는 것입니다. 이 접근 방식을 사용하면 서비스를 사용하는 구성 요소에 대해 작성된 모든 테스트에서 WindowService를 모의 할 수 있습니다.
Kildareflare

9

Platform width()height()에 대한 설명서에는 이러한 메서드가 각각 window.innerWidth및을 사용한다고 명시 되어 window.innerHeight있습니다. 그러나 차원이 캐시 된 값이기 때문에 메서드를 사용하는 것이 선호되어 여러 번의 값 비싼 DOM 읽기 기회를 줄입니다.

import { Platform } from 'ionic-angular';

...
private width:number;
private height:number;

constructor(private platform: Platform){
    platform.ready().then(() => {
        this.width = platform.width();
        this.height = platform.height();
    });
}

얻는 width것은 window어떤 관련이 DOM있습니까? 논리적으로 dom 트리가 어떻게 생겼는지에 의존해서는 안됩니다.
Shahryar Saljoughi

6

제가 사용하는 서비스의 예입니다.

을 구독하거나을 screenWidth$통해 화면 너비를 얻을 수 있습니다 screenWidth$.value.

mediaBreakpoint$(또는 mediaBreakpoint$.value)도 동일합니다.

import {
  Injectable,
  OnDestroy,
} from '@angular/core';
import {
  Subject,
  BehaviorSubject,
  fromEvent,
} from 'rxjs';
import {
  takeUntil,
  debounceTime,
} from 'rxjs/operators';

@Injectable()
export class ResponsiveService implements OnDestroy {
  private _unsubscriber$: Subject<any> = new Subject();
  public screenWidth$: BehaviorSubject<number> = new BehaviorSubject(null);
  public mediaBreakpoint$: BehaviorSubject<string> = new BehaviorSubject(null);

  constructor() {}

  init() {
    this._setScreenWidth(window.innerWidth);
    this._setMediaBreakpoint(window.innerWidth);
    fromEvent(window, 'resize')
      .pipe(
        debounceTime(1000),
        takeUntil(this._unsubscriber$)
      ).subscribe((evt: any) => {
        this._setScreenWidth(evt.target.innerWidth);
        this._setMediaBreakpoint(evt.target.innerWidth);
      });
  }

  ngOnDestroy() {
    this._unsubscriber$.next();
    this._unsubscriber$.complete();
  }

  private _setScreenWidth(width: number): void {
    this.screenWidth$.next(width);
  }

  private _setMediaBreakpoint(width: number): void {
    if (width < 576) {
      this.mediaBreakpoint$.next('xs');
    } else if (width >= 576 && width < 768) {
      this.mediaBreakpoint$.next('sm');
    } else if (width >= 768 && width < 992) {
      this.mediaBreakpoint$.next('md');
    } else if (width >= 992 && width < 1200) {
      this.mediaBreakpoint$.next('lg');
    } else if (width >= 1200 && width < 1600) {
      this.mediaBreakpoint$.next('xl');
    } else {
      this.mediaBreakpoint$.next('xxl');
    }
  }

}

이것이 누군가에게 도움이되기를 바랍니다.


내가 가장 좋아하는 대답! 이것이 작동하도록 생성자에 this.init ()를 추가했는지 확인하십시오.
Ben


3
@HostListener("window:resize", [])
public onResize() {
  this.detectScreenSize();
}

public ngAfterViewInit() {
    this.detectScreenSize();
}

private detectScreenSize() {
    const height = window.innerHeight;
    const width = window.innerWidth;
}

3
이 적합한 솔루션이 될 수있는 이유를 반드시 설명
thedp

3

대답은 매우 간단합니다. 아래 코드를 작성하십시오

import { Component, OnInit, OnDestroy, Input } from "@angular/core";
// Import this, and write at the top of your .ts file
import { HostListener } from "@angular/core";

@Component({
 selector: "app-login",
 templateUrl: './login.component.html',
 styleUrls: ['./login.component.css']
})

export class LoginComponent implements OnInit, OnDestroy {
// Declare height and width variables
scrHeight:any;
scrWidth:any;

@HostListener('window:resize', ['$event'])
getScreenSize(event?) {
      this.scrHeight = window.innerHeight;
      this.scrWidth = window.innerWidth;
      console.log(this.scrHeight, this.scrWidth);
}

// Constructor
constructor() {
    this.getScreenSize();
}
}

1

이 시나리오에서는 typescript getter 메서드를 사용할 수 있습니다. 이렇게

public get width() {
  return window.innerWidth;
}

그리고 다음과 같은 템플릿에서 사용하십시오.

<section [ngClass]="{ 'desktop-view': width >= 768, 'mobile-view': width < 768 
}"></section>

창 크기 조정 / 확인을 위해 이벤트 핸들러가 필요하지 않습니다.이 메서드는 매번 자동으로 크기를 확인합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.