1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2025-01-14 14:43:17 +08:00

Implementing next photo preloading

#134

Also fixing play button animation.
This commit is contained in:
Patrik J. Braun 2022-06-26 09:56:13 +02:00
parent d0b609b416
commit c06620a795
6 changed files with 124 additions and 74 deletions

View File

@ -154,6 +154,21 @@
opacity: 1.0; opacity: 1.0;
} }
@keyframes blink {
0% {
opacity: 0.5;
}
25% {
opacity: 1.0;
}
75% {
opacity: 1.0;
}
100% {
opacity: 0.5;
}
}
@-webkit-keyframes blink { @-webkit-keyframes blink {
0% { 0% {
opacity: 0.5; opacity: 0.5;

View File

@ -257,12 +257,9 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
} }
} }
public play(): void { private showNextMedia = () => {
this.pause(); if (this.mediaElement.imageLoadFinished.this === false ||
this.timerSub = this.timer this.mediaElement.imageLoadFinished.next === false) {
.pipe(filter((t) => t % 2 === 0))
.subscribe(() => {
if (this.mediaElement.imageLoadFinished === false) {
return; return;
} }
// do not skip video if its playing // do not skip video if its playing
@ -274,25 +271,19 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
return; return;
} }
this.nextPhoto.emit(); this.nextPhoto.emit();
}); };
public play(): void {
this.pause();
this.timerSub = this.timer
.pipe(filter((t) => t % 2 === 0))
.subscribe(this.showNextMedia);
this.playBackState = PlayBackStates.Play; this.playBackState = PlayBackStates.Play;
} }
public fastForward(): void { public fastForward(): void {
this.pause(); this.pause();
this.timerSub = this.timer.subscribe(() => { this.timerSub = this.timer.subscribe(this.showNextMedia);
if (this.mediaElement.imageLoadFinished === false) {
return;
}
if (
this.activePhoto &&
this.activePhoto.gridMedia.isVideo() &&
!this.mediaElement.Paused
) {
return;
}
this.nextPhoto.emit();
});
this.playBackState = PlayBackStates.FastForward; this.playBackState = PlayBackStates.FastForward;
} }

View File

@ -6,6 +6,7 @@
<div class="lightbox" #lightbox> <div class="lightbox" #lightbox>
<app-gallery-lightbox-media [gridMedia]="activePhoto ? activePhoto.gridMedia : null" <app-gallery-lightbox-media [gridMedia]="activePhoto ? activePhoto.gridMedia : null"
[nextGridMedia]="NexGridMedia"
[loadMedia]="!animating" [loadMedia]="!animating"
[zoom]="controls ? controls.Zoom : 1" [zoom]="controls ? controls.Zoom : 1"
[drag]="controls ? controls.drag : {x:0,y:0}" [drag]="controls ? controls.drag : {x:0,y:0}"

View File

@ -15,6 +15,7 @@ import {ContentService} from '../content.service';
import {PhotoDTO} from '../../../../../common/entities/PhotoDTO'; import {PhotoDTO} from '../../../../../common/entities/PhotoDTO';
import {ControlsLightboxComponent} from './controls/controls.lightbox.gallery.component'; import {ControlsLightboxComponent} from './controls/controls.lightbox.gallery.component';
import {SupportedFormats} from '../../../../../common/SupportedFormats'; import {SupportedFormats} from '../../../../../common/SupportedFormats';
import {GridMedia} from '../grid/GridMedia';
export enum LightboxStates { export enum LightboxStates {
Open = 1, Open = 1,
@ -389,7 +390,7 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
this.router this.router
.navigate([], { .navigate([], {
queryParams: this.queryService.getParams( queryParams: this.queryService.getParams(
this.gridPhotoQL.toArray()[photoIndex].gridMedia.media this.gridPhotoQL.get(photoIndex).gridMedia.media
), ),
}) })
.catch(console.error); .catch(console.error);
@ -440,14 +441,12 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
} }
private updateActivePhoto(photoIndex: number, resize = true): void { private updateActivePhoto(photoIndex: number, resize = true): void {
const pcList = this.gridPhotoQL.toArray();
if (photoIndex < 0 || photoIndex > this.gridPhotoQL.length) { if (photoIndex < 0 || photoIndex > this.gridPhotoQL.length) {
throw new Error('Can\'t find the media'); throw new Error('Can\'t find the media');
} }
this.videoSourceError = false; this.videoSourceError = false;
this.activePhotoId = photoIndex; this.activePhotoId = photoIndex;
this.activePhoto = pcList[photoIndex]; this.activePhoto = this.gridPhotoQL.get(photoIndex);
if (resize) { if (resize) {
this.animatePhoto( this.animatePhoto(
@ -455,7 +454,7 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
); );
} }
this.navigation.hasPrev = photoIndex > 0; this.navigation.hasPrev = photoIndex > 0;
this.navigation.hasNext = photoIndex + 1 < pcList.length; this.navigation.hasNext = photoIndex + 1 < this.gridPhotoQL.length;
const to = this.activePhoto.getDimension(); const to = this.activePhoto.getDimension();
@ -501,5 +500,12 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit {
return {top, left, width, height} as Dimension; return {top, left, width, height} as Dimension;
} }
get NexGridMedia(): GridMedia {
if (this.activePhotoId + 1 < this.gridPhotoQL?.length) {
return this.gridPhotoQL.get(this.activePhotoId + 1)?.gridMedia;
}
return null;
}
} }

View File

@ -22,7 +22,7 @@
(error)="onImageError()" (error)="onImageError()"
(timeupdate)="onVideoProgress()" (timeupdate)="onVideoProgress()"
#video> #video>
<source [src]="gridMedia.getBestFitMediaPath()" (error)="onSourceError($event)"> <source [src]="gridMedia.getBestFitMediaPath()" (error)="onSourceError()">
Something went wrong. Something went wrong.
</video> </video>

View File

@ -20,7 +20,8 @@ import { Config } from '../../../../../../common/config/public/Config';
}) })
export class GalleryLightboxMediaComponent implements OnChanges { export class GalleryLightboxMediaComponent implements OnChanges {
@Input() gridMedia: GridMedia; @Input() gridMedia: GridMedia;
@Input() loadMedia = false; @Input() nextGridMedia: GridMedia;
@Input() loadMedia = false; // prevents loading media
@Input() windowAspect = 1; @Input() windowAspect = 1;
@Input() zoom = 1; @Input() zoom = 1;
@Input() drag = {x: 0, y: 0}; @Input() drag = {x: 0, y: 0};
@ -31,17 +32,24 @@ export class GalleryLightboxMediaComponent implements OnChanges {
prevGirdPhoto: GridMedia = null; prevGirdPhoto: GridMedia = null;
public imageSize = {width: 'auto', height: '100'}; public imageSize = {width: 'auto', height: '100'};
public imageLoadFinished = false; private nextImage = new Image();
// do not skip to the next photo if not both are loaded (or resulted in an error)
public imageLoadFinished = {
this: false,
next: false
};
thumbnailSrc: string = null; thumbnailSrc: string = null;
photo = { photo = {
src: null as string, src: null as string,
isBestFit: null as boolean, isBestFit: null as boolean,
}; };
public transcodeNeedVideos = SupportedFormats.TranscodeNeed.Videos; public transcodeNeedVideos = SupportedFormats.TranscodeNeed.Videos;
// if media not loaded, show thumbnail
private mediaLoaded = false; private mediaLoaded = false;
private videoProgress = 0; private videoProgress = 0;
constructor(public elementRef: ElementRef, private sanitizer: DomSanitizer) {} constructor(public elementRef: ElementRef, private sanitizer: DomSanitizer) {
}
get ImageTransform(): SafeStyle { get ImageTransform(): SafeStyle {
return this.sanitizer.bypassSecurityTrustStyle( return this.sanitizer.bypassSecurityTrustStyle(
@ -120,8 +128,12 @@ export class GalleryLightboxMediaComponent implements OnChanges {
this.prevGirdPhoto = this.gridMedia; this.prevGirdPhoto = this.gridMedia;
this.thumbnailSrc = null; this.thumbnailSrc = null;
this.photo.src = null; this.photo.src = null;
this.nextImage.src = "";
this.mediaLoaded = false; this.mediaLoaded = false;
this.imageLoadFinished = false; this.imageLoadFinished = {
this: false,
next: false
};
} }
this.setImageSize(); this.setImageSize();
if ( if (
@ -156,16 +168,18 @@ export class GalleryLightboxMediaComponent implements OnChanges {
onImageError(): void { onImageError(): void {
// TODO:handle error // TODO:handle error
this.imageLoadFinished = true; this.imageLoadFinished.this = true;
console.error( console.error(
'Error: cannot load media for lightbox url: ' + 'Error: cannot load media for lightbox url: ' +
this.gridMedia.getBestFitMediaPath() this.gridMedia.getBestFitMediaPath()
); );
this.loadNextPhoto();
} }
onImageLoad(): void { onImageLoad(): void {
this.imageLoadFinished = true; this.imageLoadFinished.this = true;
this.mediaLoaded = true; this.mediaLoaded = true;
this.loadNextPhoto();
} }
public showThumbnail(): boolean { public showThumbnail(): boolean {
@ -178,11 +192,34 @@ export class GalleryLightboxMediaComponent implements OnChanges {
); );
} }
onSourceError($event: any): void { onSourceError(): void {
this.mediaLoaded = false; this.mediaLoaded = false;
this.videoSourceError.emit(); this.videoSourceError.emit();
} }
/**
* Loads next photo to faster show it on navigation.
* Called after the current photo is loaded
* @private
*/
private loadNextPhoto(): void {
if (!this.nextGridMedia || !this.loadMedia) {
return;
}
// Videos do not support preloading
if (!this.nextGridMedia.isPhoto()) {
this.imageLoadFinished.next = true;
return;
}
if (Config.Client.Media.Photo.Converting.enabled === true) {
this.nextImage.src = this.nextGridMedia.getBestFitMediaPath();
} else {
this.nextImage.src = this.nextGridMedia.getMediaPath();
}
this.nextImage.onload = () => this.imageLoadFinished.next = true;
}
private loadPhoto(): void { private loadPhoto(): void {
if (!this.gridMedia || !this.loadMedia || !this.gridMedia.isPhoto()) { if (!this.gridMedia || !this.loadMedia || !this.gridMedia.isPhoto()) {
return; return;