Add zoom to gallery view

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/4/head
trivernis 3 years ago
parent d3c94bc1ec
commit 3f90e9d1db

@ -42,6 +42,7 @@ import {BlockUIModule} from "primeng/blockui";
import {PanelModule} from "primeng/panel";
import {DragDropModule} from "@angular/cdk/drag-drop";
import { ContentAwareImageComponent } from './components/content-aware-image/content-aware-image.component';
import {MatSliderModule} from "@angular/material/slider";
@NgModule({
declarations: [
@ -90,6 +91,7 @@ import { ContentAwareImageComponent } from './components/content-aware-image/con
BlockUIModule,
PanelModule,
DragDropModule,
MatSliderModule,
],
providers: [],
bootstrap: [AppComponent]

@ -22,10 +22,8 @@ export class ContentAwareImageComponent {
public adjustSize(image: HTMLImageElement, imageContainer: HTMLDivElement): void {
const containerHeight = Math.abs(imageContainer.clientHeight);
const containerWidth = Math.abs(imageContainer.clientWidth);
console.log(containerHeight, ',', containerWidth);
const imageRelativeHeight = image.height / containerHeight;
const imageRelativeWidth = image.width / containerWidth;
console.log(imageRelativeHeight, ',', imageRelativeWidth);
this.scaleWidth = imageRelativeWidth > imageRelativeHeight;
}
}

@ -4,11 +4,22 @@
</button>
<div class="file-full-view" fxFlex="80%"
(dblclick)="this.selectedFile? this.fileDblClickEvent.emit(this.selectedFile.data) : null">
<div class="file-full-view-inner" #imageContainer>
<div class="file-full-view-inner">
<div *ngIf="!this.fileContentUrl" class="url-loading-backdrop">
<mat-progress-spinner mode="indeterminate" color="primary"></mat-progress-spinner>
</div>
<app-content-aware-image *ngIf="this.fileContentUrl" [imageSrc]="this.fileContentUrl"></app-content-aware-image>
<div class="zoom-slider">
<mat-slider min="0.5" max="4" [value]="this.imageZoom"
(input)="this.imageZoom=$event.value ?? 1" vertical step="0.1"></mat-slider>
<button mat-icon-button (click)="this.resetImage()">
<mat-icon>refresh</mat-icon>
</button>
</div>
<div #imageDragContainer [cdkDragFreeDragPosition]="this.imagePosition" (cdkDragMoved)="this.onDragMoved($event)" *ngIf="this.fileContentUrl" cdkDrag class="image-drag-container">
<div #scaledImage class="image-scale-container" [style]="{scale: this.imageZoom}">
<app-content-aware-image [imageSrc]="this.fileContentUrl"></app-content-aware-image>
</div>
</div>
</div>
</div>
<mat-divider fxFlex></mat-divider>

@ -13,6 +13,7 @@
height: 100%;
width: 100%;
position: relative;
user-select: none;
}
app-file-gallery-entry, .file-item {
@ -28,6 +29,7 @@ app-file-gallery-entry {
.file-full-view {
width: 100%;
height: 100%;
overflow: hidden;
}
.file-full-view-inner {
@ -63,3 +65,30 @@ app-content-aware-image {
margin: auto;
}
}
.image-drag-container, .image-scale-container {
height: 100%;
width: 100%;
}
.image-scale-container {
display: block;
}
.zoom-slider {
position: absolute;
display: flex;
flex-direction: column;
right: 1em;
bottom: 1em;
z-index: 10;
opacity: 0.5;
padding: 1em 0.5em;
transition-duration: 0.2s;
}
.zoom-slider:hover {
opacity: 1;
background-color: rgba(0, 0, 0, 0.3);
border-radius: 1em;
}

@ -11,6 +11,7 @@ import {FileService} from "../../services/file/file.service";
import {SafeResourceUrl} from "@angular/platform-browser";
import {Selectable} from "../../models/Selectable";
import {CdkVirtualScrollViewport} from "@angular/cdk/scrolling";
import {CdkDrag, CdkDragMove, DragRef, Point} from "@angular/cdk/drag-drop";
@Component({
selector: 'app-file-gallery',
@ -27,10 +28,13 @@ export class FileGalleryComponent implements OnChanges, OnInit {
entries: Selectable<File>[] = [];
@ViewChild("virtualScroll") virtualScroll!: CdkVirtualScrollViewport;
@ViewChild("scaledImage") scaledImage: ElementRef<HTMLDivElement> | undefined;
@ViewChild("imageDragContainer") imageDragContainer: ElementRef<HTMLDivElement> | undefined;
public selectedFile: Selectable<File> | undefined;
fileContentUrl: SafeResourceUrl | undefined;
scaleWidth = false;
public imageZoom = 1;
public imagePosition = {x: 0, y: 0};
constructor(private fileService: FileService) {
}
@ -42,6 +46,7 @@ export class FileGalleryComponent implements OnChanges, OnInit {
*/
async onEntrySelect(entry: Selectable<File>) {
if (entry) {
this.resetImage();
this.selectedFile?.unselect();
entry.select();
this.selectedFile = entry;
@ -58,7 +63,8 @@ export class FileGalleryComponent implements OnChanges, OnInit {
async loadSelectedFile() {
if (this.selectedFile) {
this.fileContentUrl = undefined;
this.fileContentUrl = await this.fileService.readFile(this.selectedFile.data);
this.fileContentUrl = await this.fileService.readFile(
this.selectedFile.data);
}
}
@ -69,8 +75,10 @@ export class FileGalleryComponent implements OnChanges, OnInit {
}
public async ngOnChanges(changes: SimpleChanges): Promise<void> {
this.entries = this.files.map(f => new Selectable(f, f.hash == this.selectedFile?.data.hash));
const selectedIndex = this.files.findIndex(f => f.hash === this.selectedFile?.data.hash);
this.entries = this.files.map(
f => new Selectable(f, f.hash == this.selectedFile?.data.hash));
const selectedIndex = this.files.findIndex(
f => f.hash === this.selectedFile?.data.hash);
if (!this.selectedFile || selectedIndex < 0) {
await this.onEntrySelect(this.getPreselectedEntry() ?? this.entries[0])
@ -111,6 +119,11 @@ export class FileGalleryComponent implements OnChanges, OnInit {
}
}
public resetImage() {
this.imageZoom = 1;
this.imagePosition = {x: 0, y: 0};
}
@HostListener("window:keydown", ["$event"])
private async handleKeydownEvent(event: KeyboardEvent) {
switch (event.key) {
@ -120,12 +133,33 @@ export class FileGalleryComponent implements OnChanges, OnInit {
case "ArrowLeft":
await this.previousItem();
break;
case "Escape":
this.resetImage();
break;
}
}
@HostListener("mousewheel", ["$event"])
private handleScroll(event: any) {
const delta = event.wheelDelta ?? event.detail
if (delta > 0) {
this.imageZoom += 0.2
if (this.imageZoom > 4) {
this.imageZoom = 4;
}
} else if (delta < 0) {
this.imageZoom -= 0.2
if (this.imageZoom < 0.5) {
this.imageZoom = 0.5;
}
}
}
private getPreselectedEntry(): Selectable<File> | undefined {
if (this.preselectedFile) {
const entry = this.entries.find(e => e.data.hash == this.preselectedFile?.hash);
const entry = this.entries.find(
e => e.data.hash == this.preselectedFile?.hash);
if (entry) {
return entry;
}
@ -133,10 +167,8 @@ export class FileGalleryComponent implements OnChanges, OnInit {
return undefined;
}
public adjustImageSize(fullImage: HTMLImageElement, imageContainer: HTMLDivElement): void {
const containerRatio = imageContainer.clientHeight / imageContainer.clientWidth;
const imageAdjHeight = fullImage.height / containerRatio;
const imageAdjWidth = fullImage.width * containerRatio;
this.scaleWidth = imageAdjWidth > imageAdjHeight;
public onDragMoved($event: CdkDragMove<HTMLDivElement>): void {
this.imagePosition.x += $event.delta.x;
this.imagePosition.y += $event.delta.y;
}
}

@ -26,7 +26,7 @@
(fileMultiselectEvent)="onFileMultiSelect($event)"
></app-file-grid>
<app-file-gallery *ngIf="this.showGallery" [files]="files" (fileSelectEvent)="onFileSelect($event)"
(fileDblClickEvent)="openFile($event)" [preselectedFile]="this.preselectedFile"
[preselectedFile]="this.preselectedFile"
(closeEvent)="this.closeGallery($event.selectedFile?.data)"></app-file-gallery>
</mat-drawer-content>
</mat-drawer-container>

@ -86,19 +86,6 @@ export class SearchPageComponent implements OnInit {
event.source.deselectAll();
}
async openFile(file: File) {
if (this.openingLightbox) {
return;
}
this.openingLightbox = true;
try {
await this.openLightbox(file);
} catch (err) {
this.errorBroker.showError(err);
}
this.openingLightbox = false;
}
async openGallery(preselectedFile: File) {
this.preselectedFile = preselectedFile;
this.showGallery = true;
@ -108,29 +95,4 @@ export class SearchPageComponent implements OnInit {
this.preselectedFile = preselectedFile;
this.showGallery = false;
}
private async openLightbox(file: File): Promise<void> {
let url = await this.fileService.readFile(file);
let albums = [
{
src: url as string,
caption: file.name ?? file.comment,
thumb: url as string,
}
];
this.lightbox.open(albums, 0, {
disableScrolling: true,
showImageNumberLabel: false,
showDownloadButton: true,
centerVertically: true,
});
const lighboxSubscription = this.lightboxEvent.lightboxEvent$.subscribe(
(event: any) => {
if (event?.id == LIGHTBOX_EVENT.CLOSE) {
lighboxSubscription.unsubscribe();
URL?.revokeObjectURL(url as string);
}
})
}
}

Loading…
Cancel
Save