mirror of
https://github.com/xuthus83/pigallery2.git
synced 2025-01-14 14:43:17 +08:00
implementing advanced grid rendering (on scroll render more images)
fixing slow image load
This commit is contained in:
parent
54636ac290
commit
a874c7d70f
@ -8,7 +8,8 @@ import {
|
|||||||
ViewChild,
|
ViewChild,
|
||||||
ViewChildren,
|
ViewChildren,
|
||||||
QueryList,
|
QueryList,
|
||||||
AfterViewInit
|
AfterViewInit,
|
||||||
|
HostListener
|
||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import {Photo} from "../../../../common/entities/Photo";
|
import {Photo} from "../../../../common/entities/Photo";
|
||||||
import {GridRowBuilder} from "./GridRowBuilder";
|
import {GridRowBuilder} from "./GridRowBuilder";
|
||||||
@ -41,56 +42,24 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges() {
|
ngOnChanges() {
|
||||||
this.renderPhotos();
|
this.onPhotosChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
onResize() {
|
onResize() {
|
||||||
this.renderPhotos();
|
this.onPhotosChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
this.lightbox.gridPhotoQL = this.gridPhotoQL;
|
this.lightbox.gridPhotoQL = this.gridPhotoQL;
|
||||||
|
|
||||||
//TODO: implement scroll detection
|
//TODO: implement scroll detection
|
||||||
/* this.gridPhotoQL.changes.subscribe(
|
|
||||||
(x)=> {
|
|
||||||
console.log("changed");
|
|
||||||
if (!this.directory || this.gridPhotoQL.length < this.directory.photos.length) {
|
|
||||||
console.log("bad");
|
|
||||||
console.log(this.directory ? this.gridPhotoQL.length + " < "+this.directory.photos.length : "no dir");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.renderedContainerWidth != this.getContainerWidth()) {
|
|
||||||
this.renderPhotos();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(err) => {
|
|
||||||
console.log('Error: %s', err);
|
|
||||||
},
|
|
||||||
() =>{
|
|
||||||
console.log('Completed');
|
|
||||||
}
|
|
||||||
|
|
||||||
); */
|
|
||||||
|
|
||||||
|
|
||||||
setImmediate(() => {
|
this.onPhotosChanged();
|
||||||
this.renderPhotos();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private renderedContainerWidth = 0;
|
private onPhotosChanged() {
|
||||||
|
|
||||||
private renderPhotos() {
|
|
||||||
if (this.getContainerWidth() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let maxRowHeight = window.innerHeight / this.MIN_ROW_COUNT;
|
|
||||||
let minRowHeight = window.innerHeight / this.MAX_ROW_COUNT;
|
|
||||||
let containerWidth = this.getContainerWidth();
|
|
||||||
this.renderedContainerWidth = containerWidth;
|
|
||||||
|
|
||||||
this.photos.sort((a:Photo, b:Photo) => {
|
this.photos.sort((a:Photo, b:Photo) => {
|
||||||
if (a.metadata.creationDate > b.metadata.creationDate) {
|
if (a.metadata.creationDate > b.metadata.creationDate) {
|
||||||
return 1;
|
return 1;
|
||||||
@ -101,13 +70,28 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
|||||||
// a must be equal to b
|
// a must be equal to b
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.photosToRender = [];
|
this.photosToRender = [];
|
||||||
let i = 0;
|
this.renderedPhotoIndex = 0;
|
||||||
|
setImmediate(() => {
|
||||||
|
this.renderPhotos();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
while (i < this.photos.length) {
|
private renderedPhotoIndex:number = 0;
|
||||||
|
|
||||||
let photoRowBuilder = new GridRowBuilder(this.photos, i, this.IMAGE_MARGIN, containerWidth);
|
private renderPhotos() {
|
||||||
|
if (this.getContainerWidth() == 0 || this.renderedPhotoIndex >= this.photos.length || !this.shouldRenderMore()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let maxRowHeight = window.innerHeight / this.MIN_ROW_COUNT;
|
||||||
|
let minRowHeight = window.innerHeight / this.MAX_ROW_COUNT;
|
||||||
|
|
||||||
|
let renderedContentHeight = 0;
|
||||||
|
|
||||||
|
while (this.renderedPhotoIndex < this.photos.length && this.shouldRenderMore(renderedContentHeight)) {
|
||||||
|
|
||||||
|
let photoRowBuilder = new GridRowBuilder(this.photos, this.renderedPhotoIndex, this.IMAGE_MARGIN, this.getContainerWidth());
|
||||||
photoRowBuilder.addPhotos(this.TARGET_COL_COUNT);
|
photoRowBuilder.addPhotos(this.TARGET_COL_COUNT);
|
||||||
photoRowBuilder.adjustRowHeightBetween(minRowHeight, maxRowHeight);
|
photoRowBuilder.adjustRowHeightBetween(minRowHeight, maxRowHeight);
|
||||||
|
|
||||||
@ -119,11 +103,24 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
|||||||
this.photosToRender.push(new GridPhoto(photo, imageWidth, imageHeight));
|
this.photosToRender.push(new GridPhoto(photo, imageWidth, imageHeight));
|
||||||
});
|
});
|
||||||
|
|
||||||
i += photoRowBuilder.getPhotoRow().length;
|
renderedContentHeight += rowHeight;
|
||||||
|
this.renderedPhotoIndex += photoRowBuilder.getPhotoRow().length;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private shouldRenderMore(offset:number = 0):boolean {
|
||||||
|
return document.body.scrollTop >= (document.body.clientHeight + offset - window.innerHeight) * 0.7
|
||||||
|
|| document.body.clientHeight + offset < window.innerHeight;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('window:scroll')
|
||||||
|
onScroll() {
|
||||||
|
this.renderPhotos();
|
||||||
|
}
|
||||||
|
|
||||||
private getContainerWidth():number {
|
private getContainerWidth():number {
|
||||||
if (!this.gridContainer) {
|
if (!this.gridContainer) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div #photoContainer class="photo-container" (mouseover)="hover()" (mouseout)="mouseOut()">
|
<div #photoContainer class="photo-container" (mouseover)="hover()" (mouseout)="mouseOut()">
|
||||||
<img #img [src]="image.src" [hidden]="!image.show">
|
<img #img [src]="image.src" [hidden]="!image.show || loading.show" (load)="onImageLoad()">
|
||||||
|
|
||||||
<gallery-grid-photo-loading [animate]="loading.animate" *ngIf="loading.show">
|
<gallery-grid-photo-loading [animate]="loading.animate" *ngIf="loading.show">
|
||||||
</gallery-grid-photo-loading>
|
</gallery-grid-photo-loading>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
///<reference path="../../../../browser.d.ts"/>
|
///<reference path="../../../../browser.d.ts"/>
|
||||||
|
|
||||||
import {Component, Input, ElementRef, ViewChild, OnInit, AfterViewInit, OnDestroy, HostListener} from "@angular/core";
|
import {Component, Input, ElementRef, ViewChild, OnInit, AfterViewInit, OnDestroy, Renderer} from "@angular/core";
|
||||||
import {IRenderable, Dimension} from "../../../model/IRenderable";
|
import {IRenderable, Dimension} from "../../../model/IRenderable";
|
||||||
import {GridPhoto} from "../GridPhoto";
|
import {GridPhoto} from "../GridPhoto";
|
||||||
import {SearchTypes} from "../../../../../common/entities/AutoCompleteItem";
|
import {SearchTypes} from "../../../../../common/entities/AutoCompleteItem";
|
||||||
@ -34,7 +34,7 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, AfterViewInit
|
|||||||
|
|
||||||
loading = {
|
loading = {
|
||||||
animate: false,
|
animate: false,
|
||||||
show: false
|
show: true
|
||||||
};
|
};
|
||||||
|
|
||||||
thumbnailTask:ThumbnailTaskEntity = null;
|
thumbnailTask:ThumbnailTaskEntity = null;
|
||||||
@ -47,9 +47,13 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, AfterViewInit
|
|||||||
SearchTypes:any = [];
|
SearchTypes:any = [];
|
||||||
searchEnabled:boolean = true;
|
searchEnabled:boolean = true;
|
||||||
|
|
||||||
constructor(private thumbnailService:ThumbnailLoaderService) {
|
scrollListener = null;
|
||||||
|
|
||||||
|
constructor(private thumbnailService:ThumbnailLoaderService, private renderer:Renderer) {
|
||||||
this.SearchTypes = SearchTypes;
|
this.SearchTypes = SearchTypes;
|
||||||
this.searchEnabled = Config.Client.Search.searchEnabled;
|
this.searchEnabled = Config.Client.Search.searchEnabled;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@ -57,7 +61,7 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, AfterViewInit
|
|||||||
if (this.gridPhoto.isThumbnailAvailable()) {
|
if (this.gridPhoto.isThumbnailAvailable()) {
|
||||||
this.image.src = this.gridPhoto.getThumbnailPath();
|
this.image.src = this.gridPhoto.getThumbnailPath();
|
||||||
this.image.show = true;
|
this.image.show = true;
|
||||||
this.loading.show = false;
|
// this.loading.show = false;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (this.gridPhoto.isReplacementThumbnailAvailable()) {
|
if (this.gridPhoto.isReplacementThumbnailAvailable()) {
|
||||||
@ -84,15 +88,23 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, AfterViewInit
|
|||||||
this.image.show = true;
|
this.image.show = true;
|
||||||
this.loading.show = false;
|
this.loading.show = false;
|
||||||
this.thumbnailTask = null;
|
this.thumbnailTask = null;
|
||||||
|
if (this.scrollListener) {
|
||||||
|
this.scrollListener();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onError: (error)=> {//onError
|
onError: (error)=> {//onError
|
||||||
this.thumbnailTask = null;
|
this.thumbnailTask = null;
|
||||||
|
if (this.scrollListener) {
|
||||||
|
this.scrollListener();
|
||||||
|
}
|
||||||
//TODO: handle error
|
//TODO: handle error
|
||||||
console.error("something bad happened");
|
console.error("something bad happened");
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
this.scrollListener = this.renderer.listenGlobal('window', 'scroll', () => {
|
||||||
|
this.onScroll();
|
||||||
|
});
|
||||||
if (this.gridPhoto.isReplacementThumbnailAvailable()) {
|
if (this.gridPhoto.isReplacementThumbnailAvailable()) {
|
||||||
this.thumbnailTask = this.thumbnailService.loadImage(this.gridPhoto, ThumbnailLoadingPriority.medium, listener);
|
this.thumbnailTask = this.thumbnailService.loadImage(this.gridPhoto, ThumbnailLoadingPriority.medium, listener);
|
||||||
} else {
|
} else {
|
||||||
@ -117,7 +129,6 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, AfterViewInit
|
|||||||
&& document.body.scrollTop + window.innerHeight > this.container.nativeElement.offsetTop;
|
&& document.body.scrollTop + window.innerHeight > this.container.nativeElement.offsetTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('window:scroll')
|
|
||||||
onScroll() {
|
onScroll() {
|
||||||
if (this.thumbnailTask != null) {
|
if (this.thumbnailTask != null) {
|
||||||
if (this.isInView() == true) {
|
if (this.isInView() == true) {
|
||||||
@ -157,6 +168,10 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, AfterViewInit
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onImageLoad() {
|
||||||
|
this.loading.show = false;
|
||||||
|
}
|
||||||
|
|
||||||
public getDimension():Dimension {
|
public getDimension():Dimension {
|
||||||
return new Dimension(this.imageRef.nativeElement.offsetTop,
|
return new Dimension(this.imageRef.nativeElement.offsetTop,
|
||||||
this.imageRef.nativeElement.offsetLeft,
|
this.imageRef.nativeElement.offsetLeft,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user