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:
parent
d0b609b416
commit
c06620a795
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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}"
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user