From aa67f45f78e6f725c58c2a2e87b8291a58f7a0cc Mon Sep 17 00:00:00 2001 From: jojohoch <joachim.hoch@iqb.hu-berlin.de> Date: Mon, 8 Nov 2021 08:28:01 +0100 Subject: [PATCH] Enable and extend magnifier for images * Add magnifier properties to `ImageElement` * Set used value at `UnitStateService` * Bypass parsing error of distpacker --- .../element-components/image.component.ts | 21 ++++--- .../element-components/magnifier.component.ts | 56 ++++++++++++------- projects/common/models/image-element.ts | 4 ++ .../element-container.component.ts | 14 +++++ 4 files changed, 67 insertions(+), 28 deletions(-) diff --git a/projects/common/element-components/image.component.ts b/projects/common/element-components/image.component.ts index cf57db12c..d3ba88932 100644 --- a/projects/common/element-components/image.component.ts +++ b/projects/common/element-components/image.component.ts @@ -1,6 +1,7 @@ -import { Component } from '@angular/core'; +import { Component, EventEmitter, Output } from '@angular/core'; import { ElementComponent } from '../element-component.directive'; import { ImageElement } from '../models/image-element'; +import { ValueChangeElement } from '../models/uI-element'; @Component({ selector: 'app-image', @@ -13,18 +14,24 @@ import { ImageElement } from '../models/image-element'; [src]="elementModel.src | safeResourceUrl" [alt]="'imageNotFound' | translate" [class]="elementModel.dynamicPositioning? 'dynamic-image' : 'static-image'"> -<!-- <app-magnifier--> -<!-- [image]=image>--> -<!-- </app-magnifier>--> + <app-magnifier *ngIf="elementModel.magnifier" + [imageId]="elementModel.id" + [size]="elementModel.magnifierSize" + [zoom]="elementModel.magnifierZoom" + [used]="elementModel.magnifierUsed" + [image]=image + (magnifierUsed)="magnifierUsed.emit($event)"> + </app-magnifier> </div> </div> `, styles: [ - '.image-container{ width: fit-content; height: fit-content; margin: auto; position: relative}', - '.dynamic-image{width: 100%; height: fit-content}', - '.static-image{ width: 100%; height: 100%; object-fit: contain}' + '.image-container{ width: fit-content; height: fit-content; margin: auto; position: relative }', + '.dynamic-image{ width: 100%; height: fit-content }', + '.static-image{ width: 100%; height: 100%; object-fit: contain }' ] }) export class ImageComponent extends ElementComponent { + @Output() magnifierUsed = new EventEmitter<ValueChangeElement>(); elementModel!: ImageElement; } diff --git a/projects/common/element-components/magnifier.component.ts b/projects/common/element-components/magnifier.component.ts index f319cd0ce..43910aade 100644 --- a/projects/common/element-components/magnifier.component.ts +++ b/projects/common/element-components/magnifier.component.ts @@ -1,50 +1,64 @@ -import { Component, HostListener, Input } from '@angular/core'; +import { + Component, EventEmitter, HostListener, Input, Output +} from '@angular/core'; +import { ValueChangeElement } from '../models/uI-element'; @Component({ selector: 'app-magnifier', template: ` - <div *ngIf="image && image.width && image.height" - class="hide-cursor"> -<!-- <div class="magnifier-glass"--> -<!-- [style.backgroundImage] = "'url('+ (image.src) + ')'"--> -<!-- [style.backgroundPosition] = "backgroundPosition"--> -<!-- [style.left.px]="left"--> -<!-- [style.top.px]="top"--> -<!-- [style.width.px]="glassRadius * 2"--> -<!-- [style.height.px]="glassRadius * 2"--> -<!-- [style.backgroundSize] = "(image.width * zoom) + 'px ' + (image.height * zoom) + 'px'"--> -<!-- [style.backgroundRepeat] = "'no-repeat'">--> -<!-- </div>--> + <div class="hide-cursor"> + <div class="magnifier-glass" + [style.backgroundImage]="url + '(' + image.src + ')'" + [style.backgroundPosition]="backgroundPosition" + [style.left.px]="left" + [style.top.px]="top" + [style.width.px]="size" + [style.height.px]="size" + [style.backgroundSize]="(image.width * zoom) + 'px ' + (image.height * zoom) + 'px'" + [style.backgroundRepeat]="'no-repeat'"> + </div> </div> `, styles: [ ':host { position: absolute; top: 0; bottom: 0; right: 0; left: 0; }', - '.magnifier-glass{ position: absolute; outline: 1px solid #000; pointer-events: none;}', + '.magnifier-glass{ position: absolute; border: 1px solid #000; pointer-events: none;}', '.hide-cursor{ width: 100%; height: 100%; cursor: none }' ] }) export class Magnifier { @Input() image!: HTMLImageElement; + @Input() imageId!: string; + @Input() zoom!: number; + @Input() size!: number; + @Input() used!: boolean; + @Output() magnifierUsed = new EventEmitter<ValueChangeElement>(); - glassRadius = 50; - zoom: number = 2; left!: number; - top!:number; + top!: number; backgroundPosition!: string; + url: string = 'url'; @HostListener('mousemove', ['$event']) onMousemove(event: MouseEvent): void { + if (!this.used) { + this.used = true; + this.magnifierUsed.emit({ id: this.imageId, values: [false, true] }); + } this.left = this.calculateGlassPosition(this.image.width, event.offsetX); this.top = this.calculateGlassPosition(this.image.height, event.offsetY); this.backgroundPosition = - `-${this.calculateBackgroundPosition(event.offsetX)}px -${this.calculateBackgroundPosition(event.offsetY)}px`; + `-${ + this.calculateBackgroundPosition(this.image.width, event.offsetX) + }px -${ + this.calculateBackgroundPosition(this.image.height, event.offsetY) + }px`; } private calculateGlassPosition(max: number, value: number): number { - return ((max - 2 * this.glassRadius) / (max)) * value; + return ((max - this.size) / (max)) * value; } - private calculateBackgroundPosition(value: number): number { - return (value * this.zoom) < this.glassRadius ? 0 : (value * this.zoom - this.glassRadius); + private calculateBackgroundPosition(max: number, value: number): number { + return value * this.zoom - (value / max) * this.size; } } diff --git a/projects/common/models/image-element.ts b/projects/common/models/image-element.ts index 06e8fb9fa..2c6ee045a 100644 --- a/projects/common/models/image-element.ts +++ b/projects/common/models/image-element.ts @@ -2,6 +2,10 @@ import { UIElement } from './uI-element'; export class ImageElement extends UIElement { src: string = ''; + magnifier: boolean = false; + magnifierSize: number = 100; + magnifierZoom: number = 1.5; + magnifierUsed: boolean = false; constructor(serializedElement: UIElement) { super(serializedElement); Object.assign(this, serializedElement); diff --git a/projects/player/src/app/components/element-container/element-container.component.ts b/projects/player/src/app/components/element-container/element-container.component.ts index ef013bd0f..b72132b7c 100644 --- a/projects/player/src/app/components/element-container/element-container.component.ts +++ b/projects/player/src/app/components/element-container/element-container.component.ts @@ -26,6 +26,7 @@ import { CompoundElementComponent } import { TextElement } from '../../../../../common/models/text-element'; import { VideoElement } from '../../../../../common/models/video-element'; import { AudioElement } from '../../../../../common/models/audio-element'; +import { ImageElement } from '../../../../../common/models/image-element'; @Component({ selector: 'app-element-container', @@ -105,6 +106,14 @@ export class ElementContainerComponent implements OnInit { }); } + if (elementComponent.magnifierUsed) { + elementComponent.magnifierUsed + .pipe(takeUntil(this.ngUnsubscribe)) + .subscribe((magnifierUsed: ValueChangeElement) => { + this.unitStateService.changeElementValue(magnifierUsed); + }); + } + if (elementComponent.formValueChanged) { elementComponent.formValueChanged .pipe(takeUntil(this.ngUnsubscribe)) @@ -165,6 +174,9 @@ export class ElementContainerComponent implements OnInit { case 'text': elementModel.text = unitStateElementCode.value; break; + case 'image': + elementModel.magnifierUsed = unitStateElementCode.value; + break; case 'video': case 'audio': elementModel.playbackTime = unitStateElementCode.value; @@ -180,6 +192,8 @@ export class ElementContainerComponent implements OnInit { switch (elementModel.type) { case 'text': return { id: elementModel.id, value: (elementModel as TextElement).text }; + case 'image': + return { id: elementModel.id, value: (elementModel as ImageElement).magnifierUsed }; case 'video': return { id: elementModel.id, value: (elementModel as VideoElement).playbackTime }; case 'audio': -- GitLab