1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2024-12-23 01:27:14 +02:00

Adding circular progress bar to slideshow

This commit is contained in:
Patrik J. Braun 2023-01-08 11:09:31 +01:00
parent 3df1f43031
commit 64432799d5
3 changed files with 68 additions and 29 deletions

View File

@ -286,3 +286,9 @@ input[type="range"].zoom-progress::-moz-range-track {
.dropdown-menu { .dropdown-menu {
min-width: auto; min-width: auto;
} }
canvas{
right: 12px;
position: relative;
top: -34px;
}

View File

@ -181,8 +181,13 @@
class="oi oi-chevron-left"></span></div> class="oi oi-chevron-left"></span></div>
<div [class.dim-controls]="controllersDimmed" class="navigation-arrow highlight" <div [class.dim-controls]="controllersDimmed" class="navigation-arrow highlight"
*ngIf="navigation.hasNext && zoom == 1" title="key: right arrow" id="rightArrow" i18n-title *ngIf="navigation.hasNext && zoom == 1" title="key: right arrow" id="rightArrow" i18n-title
(click)="nextPhoto.emit()"><span (click)="nextMediaManuallyTriggered()">
class="oi oi-chevron-right"></span></div> <span class="oi oi-chevron-right"></span>
<canvas
*ngIf="playBackState == PlayBackStates.Play"
#canvas width="55px" height="55px"></canvas>
</div>
<div [class.dim-controls]="controllersDimmed" class="controls controls-zoom row" *ngIf="Zoom > 1"> <div [class.dim-controls]="controllersDimmed" class="controls controls-zoom row" *ngIf="Zoom > 1">
<div class="col-1 col-md-4"> <div class="col-1 col-md-4">

View File

@ -1,32 +1,15 @@
import { import {Component, ElementRef, EventEmitter, HostListener, Input, OnChanges, OnDestroy, OnInit, Output, ViewChild,} from '@angular/core';
Component,
ElementRef,
EventEmitter,
HostListener,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
ViewChild,
} from '@angular/core';
import {MediaDTOUtils} from '../../../../../../common/entities/MediaDTO'; import {MediaDTOUtils} from '../../../../../../common/entities/MediaDTO';
import {CookieNames} from '../../../../../../common/CookieNames';
import {FullScreenService} from '../../fullscreen.service'; import {FullScreenService} from '../../fullscreen.service';
import {GalleryPhotoComponent} from '../../grid/photo/photo.grid.gallery.component'; import {GalleryPhotoComponent} from '../../grid/photo/photo.grid.gallery.component';
import {Observable, Subscription, timer} from 'rxjs'; import {interval, Subscription} from 'rxjs';
import {filter} from 'rxjs/operators'; import {filter, skip} from 'rxjs/operators';
import {PhotoDTO} from '../../../../../../common/entities/PhotoDTO'; import {PhotoDTO} from '../../../../../../common/entities/PhotoDTO';
import {GalleryLightboxMediaComponent} from '../media/media.lightbox.gallery.component'; import {GalleryLightboxMediaComponent} from '../media/media.lightbox.gallery.component';
import {Config} from '../../../../../../common/config/public/Config'; import {Config} from '../../../../../../common/config/public/Config';
import { import {SearchQueryTypes, TextSearch, TextSearchQueryMatchTypes,} from '../../../../../../common/entities/SearchQueryDTO';
SearchQueryTypes,
TextSearch,
TextSearchQueryMatchTypes,
} from '../../../../../../common/entities/SearchQueryDTO';
import {AuthenticationService} from '../../../../model/network/authentication.service'; import {AuthenticationService} from '../../../../model/network/authentication.service';
import {LightboxService} from '../lightbox.service'; import {LightboxService} from '../lightbox.service';
import {CookieService} from 'ngx-cookie-service';
import {GalleryCacheService} from '../../cache.gallery.service'; import {GalleryCacheService} from '../../cache.gallery.service';
export enum PlayBackStates { export enum PlayBackStates {
@ -41,6 +24,9 @@ export enum PlayBackStates {
}) })
export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges { export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
readonly MAX_ZOOM = 10; readonly MAX_ZOOM = 10;
@ViewChild('canvas')
canvas: ElementRef<HTMLCanvasElement>;
private ctx: CanvasRenderingContext2D;
@ViewChild('root', {static: false}) root: ElementRef; @ViewChild('root', {static: false}) root: ElementRef;
@Output() closed = new EventEmitter(); @Output() closed = new EventEmitter();
@ -70,7 +56,6 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
public searchEnabled: boolean; public searchEnabled: boolean;
private visibilityTimer: number = null; private visibilityTimer: number = null;
private timer: Observable<number>;
private timerSub: Subscription; private timerSub: Subscription;
private prevDrag = {x: 0, y: 0}; private prevDrag = {x: 0, y: 0};
private prevZoom = 1; private prevZoom = 1;
@ -125,7 +110,6 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
} }
ngOnInit(): void { ngOnInit(): void {
this.timer = timer(1000, 1000);
if (this.cacheService.getSlideshowSpeed()) { if (this.cacheService.getSlideshowSpeed()) {
this.selectedSlideshowSpeed = this.cacheService.getSlideshowSpeed(); this.selectedSlideshowSpeed = this.cacheService.getSlideshowSpeed();
} else { } else {
@ -234,7 +218,7 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
break; break;
case 'ArrowRight': case 'ArrowRight':
if (this.navigation.hasNext) { if (this.navigation.hasNext) {
this.nextPhoto.emit(); this.nextMediaManuallyTriggered();
} }
break; break;
case 'i': case 'i':
@ -302,10 +286,47 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
this.nextPhoto.emit(); this.nextPhoto.emit();
}; };
private drawSliderProgress(t: number) {
let p = 0;
// Video is a special snowflake. It won't go to next media if a video is playing
if (!(this.activePhoto &&
this.activePhoto.gridMedia.isVideo() &&
!this.mediaElement.Paused)) {
p = (t % (this.selectedSlideshowSpeed * 10)) / this.selectedSlideshowSpeed / 10; // ticks every 100 ms
}
if (!this.canvas) {
return;
}
if (!this.ctx) {
this.ctx = this.canvas.nativeElement.getContext('2d');
}
this.ctx.lineWidth = 5;
this.ctx.strokeStyle = 'white';
this.ctx.clearRect(0, 0, this.canvas.nativeElement.width, this.canvas.nativeElement.height);
this.ctx.beginPath();
this.ctx.arc(this.canvas.nativeElement.width / 2, this.canvas.nativeElement.height / 2, this.canvas.nativeElement.width / 2 - this.ctx.lineWidth, 0, p * 2 * Math.PI);
this.ctx.stroke();
}
resetSlideshowTimer(): void {
if (this.playBackState == PlayBackStates.Play) {
this.play();
}
}
public play(): void { public play(): void {
this.pause(); this.pause();
this.timerSub = this.timer this.drawSliderProgress(0);
.pipe(filter((t) => t % this.selectedSlideshowSpeed === 0)) this.timerSub = interval(100)
.pipe(filter((t) => {
this.drawSliderProgress(t);
return t % (this.selectedSlideshowSpeed * 10) === 0; // ticks every 100 ms
}))
.pipe(skip(1)) // do not skip to next photo right away
.subscribe(this.showNextMedia); .subscribe(this.showNextMedia);
this.playBackState = PlayBackStates.Play; this.playBackState = PlayBackStates.Play;
} }
@ -323,6 +344,7 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
if (this.timerSub != null) { if (this.timerSub != null) {
this.timerSub.unsubscribe(); this.timerSub.unsubscribe();
} }
this.ctx = null;
this.playBackState = PlayBackStates.Paused; this.playBackState = PlayBackStates.Paused;
} }
@ -411,7 +433,7 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
} }
private hideControls = () => { private hideControls = () => {
this.controllersDimmed = true; // this.controllersDimmed = true;
}; };
private updateFaceContainerDim(): void { private updateFaceContainerDim(): void {
@ -431,5 +453,11 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges {
this.faceContainerDim.width = this.photoFrameDim.width; this.faceContainerDim.width = this.photoFrameDim.width;
} }
} }
nextMediaManuallyTriggered() {
this.resetSlideshowTimer();
this.nextPhoto.emit();
}
} }