Как аккуратно изменить img src в Angular2 + - PullRequest
0 голосов
/ 22 января 2019

Когда я динамически изменяю атрибут img src, старое изображение отображается при загрузке нового.

У меня есть компонент, который отображает некоторые данные: текст и изображение. При щелчке базовые данные изменяются (то есть новые данные с сервера). После щелчка текст изменяется немедленно, но компонент отображает старое изображение, а новое загружается. Когда загружается новое изображение, оно отображается визуально, что может занять значительное время.

В реальном приложении можно получить информацию о продукте и изменить продукт по нажатию кнопки. Все данные заменяются сразу, но не изображение.

Проблема существует, если компонент не уничтожен (повторно использован).

Я уже пробовал очистить изображение src после щелчка, но оно не сработало.

У меня есть простая привязка в шаблоне

img [src]="img.url" style="width: 300px; height: 300px">
<p>{{ img.text }}</p>

и изменение изображения при клике

this.img = this.images[1];

Пример приложения можно посмотреть здесь https://stackblitz.com/edit/angular-cojqnf

Возможно ли получить больше контроля над процессом смены изображения? Было бы здорово очистить изображение при клике и ждать нового с пустым фоном, например.

Ответы [ 2 ]

0 голосов
/ 22 января 2019

Я немного поэкспериментировал с вашей демонстрацией stackblitz, я в основном обернул ваш код в ImageGhostDirective, чтобы сделать его многократно используемым.Директива прослушивает любые изменения атрибута src, используя MutationObserver для изменения стиля.Используя HostListener в событии load, он возвращает стили обратно к нормальному состоянию.Я начинаю с непрозрачности 0 для первой загрузки, за которой следует непрозрачность 0,2 между последовательными изменениями изображения, но это совершенно произвольно и может быть заменено вращателем или любым другим заполнителем ...

Здесьэто ссылка на стек стека: https://stackblitz.com/edit/angular-image-ghost-directive

<img [src]="'https://loremflickr.com/300/300?random=' + index"
     style="width: 300px; height: 300px" imgGhost>
@Directive({
  selector: 'img[imgGhost]'
})
export class ImageGhostDirective implements OnDestroy {
  private changes: MutationObserver;

  constructor(private elementRef: ElementRef) {
    this.changes = new MutationObserver((mutations: MutationRecord[]) =>
      mutations.filter(m => m.attributeName === 'src').forEach(() => this.opacity = 0.2)
    );

    this.changes.observe(this.elementRef.nativeElement, {
      attributes: true,
      childList: false,
      characterData: false
    });
  }

  ngOnDestroy(): void {
    this.changes.disconnect();
  }

  @HostBinding('style.display') display = 'block';
  @HostBinding('style.opacity') opacity = 0;

  @HostListener('load')
  onLoad(): void {
    this.opacity = 1;
  }
}

Также можно указать Angular автоматически присоединять эту директиву к каждому элементу img, используя селектор img:not([imgGhost]) в директиведекоратор.Таким образом, вам не нужно вручную помещать директиву на каждое изображение в вашем приложении.

Надеюсь, это полезно.

0 голосов
/ 22 января 2019

Наконец я достиг того, что хочу, используя (load) событие на img и [ngStyle].

В шаблоне я добавил обработчик загрузки и стиль:

<img [src]="img.url" style="width: 300px; height: 300px" (load)="loaded()"
 [ngStyle]="{'display': imgVisible ? 'block' : 'none'}">

В ответ-end:

imgVisible = true;

и при изменении данных также скрыть изображение:

this.imgVisible = false;

далее, когда изображение загружено, показать изображение (будьте осторожны! когда старые и новые изображения имеюттот же URL, это событие не вызывается; если это так, нужно условно скрыть изображение)

loaded(): void {
  this.imgVisible = true;
}

Полный код для решения: https://stackblitz.com/edit/angular-ewptj7

Я небольшой поклонник такого рода решений.Это может быть трудно применить, когда у вас есть больше изображений.

Все лучшее решение приветствуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...