Files
Adam Bradley b744275936 perf(img): do not reuse img elements
Safari UIWebView has troubles dropping image requests when the src
changes, and when there are hundreds going in and out this causes
issues. Instead, do not reuse img elements. Closes #6112
2016-04-11 12:21:59 -05:00

111 lines
2.9 KiB
TypeScript

import {Component, Input, ElementRef, ChangeDetectionStrategy, ViewEncapsulation, NgZone} from 'angular2/core';
import {raf} from '../../util/dom';
import {isPresent} from '../../util/util';
import {Platform} from '../../platform/platform';
@Component({
selector: 'ion-img',
template:
'<div class="img-placeholder" [style.height]="_h" [style.width]="_w"></div>',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class Img {
private _src: string = '';
private _normalizeSrc: string = '';
private _imgs: HTMLImageElement[] = [];
private _w: string;
private _h: string;
private _enabled: boolean = true;
constructor(private _elementRef: ElementRef, private _platform: Platform, private _zone: NgZone) {}
@Input()
set src(val: string) {
let tmpImg = new Image();
tmpImg.src = isPresent(val) ? val : '';
this._src = isPresent(val) ? val : '';
this._normalizeSrc = tmpImg.src;
this._update();
}
private _update() {
if (this._enabled && this._src !== '' && this.isVisible()) {
// actively update the image
for (var i = this._imgs.length - 1; i >= 0; i--) {
if (this._imgs[i].src === this._normalizeSrc) {
// this is the active image
if (this._imgs[i].complete) {
this._loaded(true);
}
} else {
// no longer the active image
if (this._imgs[i].parentElement) {
this._imgs[i].parentElement.removeChild(this._imgs[i]);
}
this._imgs.splice(i, 1);
}
}
if (!this._imgs.length) {
this._zone.runOutsideAngular(() => {
let img = new Image();
img.style.width = this._w;
img.style.height = this._h;
img.addEventListener('load', () => {
if (img.src === this._normalizeSrc) {
this._elementRef.nativeElement.appendChild(img);
raf(() => {
this._update();
});
}
});
img.src = this._src;
this._imgs.push(img);
this._loaded(false);
});
}
} else {
// do not actively update the image
if (!this._imgs.some(img => img.src === this._normalizeSrc)) {
this._loaded(false);
}
}
}
private _loaded(isLoaded: boolean) {
this._elementRef.nativeElement.classList[isLoaded ? 'add': 'remove']('img-loaded');
}
enable(shouldEnable: boolean) {
this._enabled = shouldEnable;
this._update();
}
isVisible() {
let bounds = this._elementRef.nativeElement.getBoundingClientRect();
return bounds.bottom > 0 && bounds.top < this._platform.height();
}
@Input()
set width(val: string | number) {
this._w = (typeof val === 'number') ? val + 'px' : val;
}
@Input()
set height(val: string | number) {
this._h = (typeof val === 'number') ? val + 'px' : val;
}
}