Skip to content

Commit

Permalink
perf(virtualScroll): improve UIWebView virtual scroll
Browse files Browse the repository at this point in the history
Related #6104
  • Loading branch information
adamdbradley committed Jun 10, 2016
1 parent 99fdcc0 commit ff1daa6
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 120 deletions.
11 changes: 9 additions & 2 deletions src/components/img/img.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@

ion-img {
position: relative;
display: block;
display: flex;
overflow: hidden;

align-items: center;
justify-content: center;
}

ion-img img {
display: block;
flex-shrink: 0;

min-width: 100%;
min-height: 100%;
}

ion-img .img-placeholder {
Expand Down
63 changes: 52 additions & 11 deletions src/components/img/img.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Component, Input, ElementRef, ChangeDetectionStrategy, ViewEncapsulation, NgZone} from '@angular/core';
import {Component, Input, HostBinding, ElementRef, ChangeDetectionStrategy, ViewEncapsulation, NgZone} from '@angular/core';

import {nativeRaf} from '../../util/dom';
import {isPresent} from '../../util/util';
Expand All @@ -19,6 +19,7 @@ export class Img {
private _w: string;
private _h: string;
private _enabled: boolean = true;
private _init: boolean;

constructor(private _elementRef: ElementRef, private _platform: Platform, private _zone: NgZone) {}

Expand All @@ -30,11 +31,18 @@ export class Img {
this._src = isPresent(val) ? val : '';
this._normalizeSrc = tmpImg.src;

if (this._init) {
this._update();
}
}

ngOnInit() {
this._init = true;
this._update();
}

private _update() {
if (this._enabled && this._src !== '' && this.isVisible()) {
if (this._enabled && this._src !== '') {
// actively update the image

for (var i = this._imgs.length - 1; i >= 0; i--) {
Expand All @@ -56,8 +64,15 @@ export class Img {
if (!this._imgs.length) {
this._zone.runOutsideAngular(() => {
let img = new Image();
img.style.width = this._w;
img.style.height = this._h;
img.style.width = this._width;
img.style.height = this._height;

if (isPresent(this.alt)) {
img.alt = this.alt;
}
if (isPresent(this.title)) {
img.title = this.title;
}

img.addEventListener('load', () => {
if (img.src === this._normalizeSrc) {
Expand Down Expand Up @@ -92,19 +107,45 @@ export class Img {
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;
this._w = getUnitValue(val);
}

@Input()
set height(val: string | number) {
this._h = (typeof val === 'number') ? val + 'px' : val;
this._h = getUnitValue(val);
}

@Input() alt: string;

@Input() title: string;

@HostBinding('style.width')
get _width(): string {
return isPresent(this._w) ? this._w : '';
}

@HostBinding('style.height')
get _height(): string {
return isPresent(this._h) ? this._h : '';
}

}

function getUnitValue(val: any): string {
if (isPresent(val)) {
if (typeof val === 'string') {
if (val.indexOf('%') > -1 || val.indexOf('px') > -1) {
return val;
}
if (val.length) {
return val + 'px';
}

} else if (typeof val === 'number') {
return val + 'px';
}
}
return '';
}
4 changes: 3 additions & 1 deletion src/components/virtual-scroll/test/basic/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,6 @@ class E2EApp {
root = E2EPage;
}

ionicBootstrap(E2EApp);
ionicBootstrap(E2EApp, null, {
prodMode: true
});
20 changes: 15 additions & 5 deletions src/components/virtual-scroll/test/cards/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import {ionicBootstrap} from '../../../../../src';
encapsulation: ViewEncapsulation.None
})
class E2EPage {
items = [];
items: any[] = [];

constructor() {
for (var i = 0; i < 500; i++) {
for (var i = 0; i < 1000; i++) {
this.items.push({
imgSrc: `../../img/img/${images[rotateImg]}.jpg?${Math.random()}`,
imgHeight: Math.floor((Math.random() * 50) + 150),
name: i + ' - ' + images[rotateImg],
imgSrc: getImgSrc(),
avatarSrc: getImgSrc(),
imgHeight: Math.floor((Math.random() * 50) + 150),
content: lorem.substring(0, (Math.random() * (lorem.length - 100)) + 100)
});

Expand All @@ -33,7 +34,9 @@ class E2EApp {
root = E2EPage;
}

ionicBootstrap(E2EApp);
ionicBootstrap(E2EApp, null, {
prodMode: true
});

const lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';

Expand All @@ -50,4 +53,11 @@ const images = [
'mirth-mobile',
];

function getImgSrc() {
let src = `../../img/img/${images[rotateImg]}.jpg?${Math.round(Math.random() * 10000000)}`;
rotateImg++;
if (rotateImg === images.length) rotateImg = 0;
return src;
}

let rotateImg = 0;
4 changes: 2 additions & 2 deletions src/components/virtual-scroll/test/cards/main.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
<ion-card *virtualItem="let item">

<div>
<ion-img [src]="item.imgSrc" [height]="item.imgHeight"></ion-img>
<ion-img [src]="item.imgSrc" [height]="item.imgHeight" [alt]="item.name"></ion-img>
</div>

<ion-item>
<ion-avatar item-left>
<ion-img [src]="item.imgSrc"></ion-img>
<ion-img [src]="item.avatarSrc" height="40" width="40"></ion-img>
</ion-avatar>
<h2>{{ item.name }}</h2>
</ion-item>
Expand Down
4 changes: 3 additions & 1 deletion src/components/virtual-scroll/test/image-gallery/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ class E2EApp {
root = E2EPage;
}

ionicBootstrap(E2EApp);
ionicBootstrap(E2EApp, null, {
prodMode: true
});

var monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

Expand Down
8 changes: 5 additions & 3 deletions src/components/virtual-scroll/test/variable-size/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {ionicBootstrap} from '../../../../../src';
templateUrl: 'main.html'
})
class E2EPage {
items = [];
items: any[] = [];

constructor() {

Expand All @@ -21,7 +21,7 @@ class E2EPage {
}
}

headerFn(record, recordIndex) {
headerFn(record: any, recordIndex: number) {
if (recordIndex > 0 && recordIndex % 100 === 0) {
return recordIndex;
}
Expand All @@ -38,4 +38,6 @@ class E2EApp {
root = E2EPage;
}

ionicBootstrap(E2EApp);
ionicBootstrap(E2EApp, null, {
prodMode: true
});
18 changes: 9 additions & 9 deletions src/components/virtual-scroll/test/virtual-scroll.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ describe('VirtualScroll', () => {
data.hdrWidth = data.viewWidth; // 100%, 1 per row
data.ftrWidth = data.viewWidth; // 100%, 1 per row

headerFn = function(record) {
headerFn = function(record: any) {
return (record === 0) ? 'Header' : null;
};

footerFn = function(record) {
footerFn = function(record: any) {
return (record === 4) ? 'Footer' : null;
};

Expand Down Expand Up @@ -159,7 +159,7 @@ describe('VirtualScroll', () => {
data.itmWidth = 90; // 2 per row
data.hdrWidth = data.viewWidth; // 100%, 1 per row

headerFn = function(record) {
headerFn = function(record: any) {
return (record === 0) ? 'Header' : null;
};

Expand Down Expand Up @@ -267,10 +267,10 @@ describe('VirtualScroll', () => {
let endCellIndex = 4;

populateNodeData(startCellIndex, endCellIndex, data.viewWidth, true,
cells, records, nodes, viewContainer,
itmTmp, hdrTmp, ftrTmp, true);
cells, records, nodes, viewContainer,
itmTmp, hdrTmp, ftrTmp, true);

expect(nodes.length).toBe(3);
expect(nodes.length).toBe(6);

expect(nodes[0].cell).toBe(2);
expect(nodes[1].cell).toBe(3);
Expand Down Expand Up @@ -522,9 +522,9 @@ describe('VirtualScroll', () => {
let headerFn: Function;
let footerFn: Function;
let data: VirtualData;
let itmTmp = null;
let hdrTmp = null;
let ftrTmp = null;
let itmTmp: any = {};
let hdrTmp: any = {};
let ftrTmp: any = {};
let viewContainer: any = {
createEmbeddedView: function() {
return getView();
Expand Down
Loading

0 comments on commit ff1daa6

Please sign in to comment.