Виявлення змін розміру вікна в реальному часі в куті 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? Це про Іоніка?
Günter Zöchbauer

@ Günter Zöchbauer Платформа кутова, просто хотілося згадати коди, які я намагався.
Роніт Ооммен

1
Platformє іонічною службою. Тож я здогадуюсь, що це іонічний проект?
robbannn


@BlackBeard Я не думаю, що це дублікат через те, наскільки кутовий 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; ... можливо, більш ефективний, дає такий же результат
понеділок74,

2
Також рекомендуйте це в конструкторі, якщо ви використовуєте lodash ... this.onResize = debounce (this.onResize, 150, {Lead: false, trailing: true}) ..., щоб запобігти виклику методу onResize занадто часто .. Вам потрібно буде ... імпортувати {debounce} з 'lodash'
понеділок74

Я думаю, що вважав за краще використовувати метод " ngAfterViewInitngOnInit
спасання життєвих обстрілів"

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: Так, звичайно. Я відредагував свою відповідь, щоб зробити це зрозумілим. Дякую.
Джеремі Бенкс

Здається, що це cdkмає рівну залежність від конкретної версії кутового. Як 7 для останніх. У будь-якому випадку я можу використовувати це для старішої версії (кутовий 4, як у питанні)?
LeOn - Хань Лі

@Leon li: Я фактично використовую кутовий 7, це правильно. Однак: Наскільки я знаю, ви також можете використовувати cdk у кутовій 4. Відповідно до цієї публікації в блозі, вам потрібен cdk 2.x. Наскільки я знаю, це потрібно встановити вручну та з вказаною версією: npm @ angular / cdk @ 4
Джеремі Бенкс

@JeremyBenks Y, ми спеціально використовуємо ng 4.2.6. На цьому не можна знайти версію cdk 2.x, лише 4.1.x та 4.3.x. У будь-якому випадку, дякую!
LeOn - Хан Лі

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.
Родріго

1
По-перше, DI - це кутовий спосіб, і чіткіші залежності компонентів / директив. Але головний момент, про який йдеться, - спростити тестування коду, який використовує послугу. Використовуючи такий підхід, WindowService може бути знущається з будь-якого тесту, написаного для компонентів, які використовують сервіс.
Кілдарефларе

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? Логічно, це не повинно залежати від того, як виглядає дерево купола.
Шахряр Саляфій

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 () у конструктор, щоб він працював.
Бен


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

Для цього сценарію ви можете використати метод отримання машинопису. Подобається це

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

І використовуйте це в такому шаблоні:

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

Вам не знадобиться жоден обробник подій для перевірки зміни розміру / вікна, цей метод буде перевіряти розмір кожного разу автоматично.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.