1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2024-12-31 02:29:51 +02:00

improving thumbnail loading

This commit is contained in:
Braun Patrik 2016-06-17 11:25:15 +02:00
parent 08d6dc994e
commit cc43db58ac
8 changed files with 242 additions and 145 deletions

View File

@ -18,6 +18,7 @@ interface SearchConfig {
interface ClientConfig {
thumbnailSizes:Array<number>;
Search:SearchConfig;
concurrentThumbnailGenerations:number;
}
export class ConfigClass {
@ -29,7 +30,8 @@ export class ConfigClass {
searchEnabled: true,
instantSearchEnabled: true,
autocompleteEnabled: true
}
},
concurrentThumbnailGenerations: 1
};
public setDatabaseType(type:DatabaseType) {

View File

@ -0,0 +1,97 @@
.static {
width: 100%;
height: 100%;
background-color: #bbbbbb;
color: #7f7f7f;
font-size: 50px;
}
.static span {
top: calc(50% - 25px);
left: calc(50% - 25px);
}
.sk-cube-grid {
width: 100%;
height: 100%;
}
.sk-cube-grid .sk-cube {
width: 33%;
height: 33%;
background-color: #bbbbbb;
float: left;
}
.sk-cube-grid.animate .sk-cube {
-webkit-animation: sk-cubeGridScaleDelay 4.6s infinite ease-in-out;
animation: sk-cubeGridScaleDelay 4.6s infinite ease-in-out;
}
.sk-cube-grid.animate .sk-cube1 {
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s;
}
.sk-cube-grid.animate .sk-cube2 {
-webkit-animation-delay: 0.6s;
animation-delay: 0.6s;
}
.sk-cube-grid.animate .sk-cube3 {
-webkit-animation-delay: 0.8s;
animation-delay: 0.8s;
}
.sk-cube-grid.animate .sk-cube4 {
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s;
}
.sk-cube-grid.animate .sk-cube5 {
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s;
}
.sk-cube-grid.animate .sk-cube6 {
-webkit-animation-delay: 0.6s;
animation-delay: 0.6s;
}
.sk-cube-grid.animate .sk-cube7 {
-webkit-animation-delay: 0s;
animation-delay: 0s;
}
.sk-cube-grid.animate .sk-cube8 {
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s;
}
.sk-cube-grid.animate .sk-cube9 {
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s;
}
@-webkit-keyframes sk-cubeGridScaleDelay {
0%, 70%, 100% {
-webkit-transform: scale3D(1, 1, 1);
transform: scale3D(1, 1, 1);
}
35% {
-webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1);
}
}
@keyframes sk-cubeGridScaleDelay {
0%, 70%, 100% {
-webkit-transform: scale3D(1, 1, 1);
transform: scale3D(1, 1, 1);
}
35% {
-webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1);
}
}

View File

@ -0,0 +1,12 @@
<div class="static" *ngIf="!animate"><span class="glyphicon glyphicon-picture" aria-hidden="true"></span></div>
<div class="sk-cube-grid animate" *ngIf="animate">
<div class="sk-cube sk-cube1"></div>
<div class="sk-cube sk-cube2"></div>
<div class="sk-cube sk-cube3"></div>
<div class="sk-cube sk-cube4"></div>
<div class="sk-cube sk-cube5"></div>
<div class="sk-cube sk-cube6"></div>
<div class="sk-cube sk-cube7"></div>
<div class="sk-cube sk-cube8"></div>
<div class="sk-cube sk-cube9"></div>
</div>

View File

@ -0,0 +1,19 @@
///<reference path="../../../../../browser.d.ts"/>
import {Component} from "@angular/core";
@Component({
selector: 'gallery-grid-photo-loading',
templateUrl: 'app/gallery/grid/photo/loading/loading.photo.grid.gallery.component.html',
styleUrls: ['app/gallery/grid/photo/loading/loading.photo.grid.gallery.component.css'],
})
export class GalleryPhotoLoadingComponent {
animate = false;
startAnimation() {
console.log("animate");
this.animate = true;
}
}

View File

@ -1,6 +1,51 @@
img {
width: inherit;
height: inherit;
-webkit-animation: fadein 2s; /* Safari, Chrome and Opera > 12.1 */
-moz-animation: fadein 2s; /* Firefox < 16 */
-ms-animation: fadein 2s; /* Internet Explorer */
-o-animation: fadein 2s; /* Opera < 12.1 */
animation: fadein 2s;
}
@keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Firefox < 16 */
@-moz-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Safari, Chrome and Opera > 12.1 */
@-webkit-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Internet Explorer */
@-ms-keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.info {
@ -44,85 +89,3 @@ a {
display: inline-block;
width: 100%;
}
.sk-cube-grid {
width: 100%;
height: 100%;
}
.sk-cube-grid .sk-cube {
width: 33%;
height: 33%;
background-color: rgba(0, 0, 0, 0.1);
float: left;
-webkit-animation: sk-cubeGridScaleDelay 4.6s infinite ease-in-out;
animation: sk-cubeGridScaleDelay 4.6s infinite ease-in-out;
}
.sk-cube-grid .sk-cube1 {
-webkit-animation-delay: 2.4s;
animation-delay: 2.4s;
}
.sk-cube-grid .sk-cube2 {
-webkit-animation-delay: 2.6s;
animation-delay: 2.6s;
}
.sk-cube-grid .sk-cube3 {
-webkit-animation-delay: 2.8s;
animation-delay: 2.8s;
}
.sk-cube-grid .sk-cube4 {
-webkit-animation-delay: 2.2s;
animation-delay: 2.2s;
}
.sk-cube-grid .sk-cube5 {
-webkit-animation-delay: 2.4s;
animation-delay: 2.4s;
}
.sk-cube-grid .sk-cube6 {
-webkit-animation-delay: 2.6s;
animation-delay: 2.6s;
}
.sk-cube-grid .sk-cube7 {
-webkit-animation-delay: 2s;
animation-delay: 2s;
}
.sk-cube-grid .sk-cube8 {
-webkit-animation-delay: 2.2s;
animation-delay: 2.2s;
}
.sk-cube-grid .sk-cube9 {
-webkit-animation-delay: 2.4s;
animation-delay: 2.4s;
}
@-webkit-keyframes sk-cubeGridScaleDelay {
0%, 70%, 100% {
-webkit-transform: scale3D(1, 1, 1);
transform: scale3D(1, 1, 1);
}
35% {
-webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1);
}
}
@keyframes sk-cubeGridScaleDelay {
0%, 70%, 100% {
-webkit-transform: scale3D(1, 1, 1);
transform: scale3D(1, 1, 1);
}
35% {
-webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1);
}
}

View File

@ -1,16 +1,8 @@
<div class="photo-container" (mouseover)="hover()" (mouseout)="mouseOut()">
<img #image [src]="imageSrc" [hidden]="!showImage">
<div class="sk-cube-grid" *ngIf="!showImage">
<div class="sk-cube sk-cube1"></div>
<div class="sk-cube sk-cube2"></div>
<div class="sk-cube sk-cube3"></div>
<div class="sk-cube sk-cube4"></div>
<div class="sk-cube sk-cube5"></div>
<div class="sk-cube sk-cube6"></div>
<div class="sk-cube sk-cube7"></div>
<div class="sk-cube sk-cube8"></div>
<div class="sk-cube sk-cube9"></div>
</div>
<gallery-grid-photo-loading #loading *ngIf="!showImage">
</gallery-grid-photo-loading>
<!--Info box -->
<div #info [hidden]="!showImage" class="info" [style.margin-top.px]="-infoStyle.height"

View File

@ -1,23 +1,25 @@
///<reference path="../../../../browser.d.ts"/>
import {Component, Input, ElementRef, ViewChild, OnChanges} from "@angular/core";
import {Component, Input, ElementRef, ViewChild, AfterViewInit} from "@angular/core";
import {IRenderable, Dimension} from "../../../model/IRenderable";
import {GridPhoto} from "../GridPhoto";
import {SearchTypes} from "../../../../../common/entities/AutoCompleteItem";
import {RouterLink} from "@angular/router-deprecated";
import {Config} from "../../../config/Config";
import {ThumbnailLoaderService} from "../thumnailLoader.service";
import {GalleryPhotoLoadingComponent} from "./loading/loading.photo.grid.gallery.component";
@Component({
selector: 'gallery-grid-photo',
templateUrl: 'app/gallery/grid/photo/photo.grid.gallery.component.html',
styleUrls: ['app/gallery/grid/photo/photo.grid.gallery.component.css'],
directives: [RouterLink],
directives: [RouterLink, GalleryPhotoLoadingComponent],
})
export class GalleryPhotoComponent implements IRenderable, OnChanges {
export class GalleryPhotoComponent implements IRenderable, AfterViewInit {
@Input() gridPhoto:GridPhoto;
@ViewChild("image") imageRef:ElementRef;
@ViewChild("info") infoDiv:ElementRef;
@ViewChild(GalleryPhotoLoadingComponent) loading:GalleryPhotoLoadingComponent;
imageSrc = "#";
showImage = false;
@ -34,21 +36,28 @@ export class GalleryPhotoComponent implements IRenderable, OnChanges {
this.searchEnabled = Config.Client.Search.searchEnabled;
}
ngOnChanges() {
if (this.gridPhoto.isThumbnailAvailable()) {
this.imageSrc = this.gridPhoto.getThumbnailPath();
// this.showImage = true;
} else {
this.thumbnailService.loadImage(this.gridPhoto).then(()=> {
ngAfterViewInit() {
//schedule change after Angular checks the model
setImmediate(() => {
if (this.gridPhoto.isThumbnailAvailable()) {
this.imageSrc = this.gridPhoto.getThumbnailPath();
// this.showImage = true;
this.gridPhoto.thumbnailLoaded();
}).catch((error)=> {
console.error("something bad happened");
});
}
this.showImage = true;
} else {
this.thumbnailService.loadImage(this.gridPhoto,
()=> { //onLoadStarted
this.loading.startAnimation();
},
()=> {//onLoaded
this.imageSrc = this.gridPhoto.getThumbnailPath();
this.showImage = true;
},
()=> {//onError
console.error("something bad happened");
});
}
});
}
getPositionText():string {
if (!this.gridPhoto) {

View File

@ -2,64 +2,66 @@
import {Injectable} from "@angular/core";
import {GridPhoto} from "./GridPhoto";
import {Config} from "../../config/Config";
@Injectable()
export class ThumbnailLoaderService {
que:Array<ThumbnailTask> = [];
runningRequests:number = 0;
constructor() {
}
loadImage(gridPhoto:GridPhoto):Promise<void> {
loadImage(gridPhoto:GridPhoto, onStartedLoading, onLoad, onError):void {
console.log("[LOAD IMG]" + gridPhoto.photo.name);
return new Promise<void>((resolve:Function, reject:Function)=> {
let tmp:ThumbnailTask = null;
for (let i = 0; i < this.que.length; i++) {
if (this.que[i].src == gridPhoto.getThumbnailPath()) {
tmp = this.que[i];
break;
}
let tmp:ThumbnailTask = null;
for (let i = 0; i < this.que.length; i++) {
if (this.que[i].gridPhoto.getThumbnailPath() == gridPhoto.getThumbnailPath()) {
tmp = this.que[i];
break;
}
if (tmp != null) {
tmp.resolve.push(resolve);
tmp.reject.push(reject);
} else {
this.que.push({src: gridPhoto.getThumbnailPath(), resolve: [resolve], reject: [reject]});
}
this.run();
});
}
if (tmp != null) {
tmp.onStartedLoading.push(onStartedLoading);
tmp.onLoad.push(onLoad);
tmp.onError.push(onError);
} else {
this.que.push({
gridPhoto: gridPhoto,
onStartedLoading: [onStartedLoading],
onLoad: [onLoad],
onError: [onError]
});
}
this.run();
}
isRunning:boolean = false;
run() {
if (this.que.length === 0 || this.isRunning === true) {
if (this.que.length === 0 || this.runningRequests >= Config.Client.concurrentThumbnailGenerations) {
return;
}
this.isRunning = true;
this.runningRequests++;
let task = this.que.shift();
console.log("loadingstarted: " + task.src);
task.onStartedLoading.forEach(cb=>cb());
console.log("loadingstarted: " + task.gridPhoto.getThumbnailPath());
let curImg = new Image();
curImg.src = task.src;
curImg.src = task.gridPhoto.getThumbnailPath();
curImg.onload = () => {
console.log(task.src + "done");
task.resolve.forEach((resolve:()=>{}) => {
resolve();
});
this.isRunning = false;
console.log(task.gridPhoto.getThumbnailPath() + "done");
task.gridPhoto.thumbnailLoaded();
task.onLoad.forEach(cb=>cb());
this.runningRequests--;
this.run();
};
curImg.onerror = (error) => {
console.error(task.src + "error");
task.reject.forEach((reject:(error)=>{}) => {
reject(error);
});
this.isRunning = false;
console.error(task.gridPhoto.getThumbnailPath() + "error");
task.onLoad.forEach(cb=>cb(error));
this.runningRequests--;
this.run();
};
}
@ -67,7 +69,8 @@ export class ThumbnailLoaderService {
}
interface ThumbnailTask {
src:string;
resolve:Array<Function>;
reject:Array<Function>;
gridPhoto:GridPhoto;
onStartedLoading:Array<Function>;
onLoad:Array<Function>;
onError:Array<Function>;
}