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:
parent
08d6dc994e
commit
cc43db58ac
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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) {
|
||||
|
@ -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>;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user