master
MrPlatnum 2025-09-15 10:01:23 +02:00
parent 4b4759b29e
commit d97640ee63
2 changed files with 34 additions and 10 deletions

View File

@ -3,22 +3,28 @@
src="https://modelviewer.dev/shared-assets/models/Astronaut.glb" ar ar-modes="webxr" ar-placement="ceiling" src="https://modelviewer.dev/shared-assets/models/Astronaut.glb" ar ar-modes="webxr" ar-placement="ceiling"
reveal="manual" camera-orbit="0deg 75deg 2m"> reveal="manual" camera-orbit="0deg 75deg 2m">
<button slot="ar-button" id="ar-button-legibility" (click)="logInteraction($event)" <button slot="ar-button" id="ar-button-legibility" (click)="logInteraction($event)"
class="text-xl absolute top-4 left-1/2 -translate-x-1/2 bg-blue-500 text-white py-2 px-4 rounded-lg z-10"> class="text-xl absolute top-4 left-1/2 -translate-x-1/2 bg-blue-500 text-white py-2 px-4 rounded-lg z-10">
WebXR Umgebung laden WebXR Umgebung laden
</button> </button>
<button slot="hotspot-text" class="hotspot ar-hotspot" data-position="-0.1 0.93 0.1" data-normal="0 1 0"> <button slot="hotspot-text" class="hotspot ar-hotspot" data-position="-0.1 0.93 0.1" data-normal="0 1 0">
<div class="annotation" [ngStyle]="{'font-size.px': currentSize}" <div class="annotation" [ngStyle]="{'font-size.px': currentSize}"
style="background:rgba(255,255,255,0.9);padding:8px;border-radius:4px;color:black;"> style="background:rgba(255,255,255,0.9);padding:8px;border-radius:4px;color:black;">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet labore et
dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
Stet
clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. </div> clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. </div>
</button> </button>
<div <div
class="ar-controls absolute bottom-24 left-1/2 -translate-x-1/2 bg-black bg-opacity-70 p-4 rounded-xl space-y-4 text-white z-10"> class="ar-controls absolute bottom-24 left-1/2 -translate-x-1/2 bg-black bg-opacity-70 p-4 rounded-xl space-y-4 text-white z-10">
<!-- Phase: Min --> <!-- Phase: Min -->
<ng-container *ngIf="phase==='min'"> <ng-container *ngIf="phase==='min'">
<div>Minimum setzen</div> <div>Minimum setzen</div>
@ -33,6 +39,7 @@
class="bg-green-600 py-2 px-6 rounded-lg">Minimum bestätigen</button> class="bg-green-600 py-2 px-6 rounded-lg">Minimum bestätigen</button>
</ng-container> </ng-container>
<!-- Phase: Confirmed Min --> <!-- Phase: Confirmed Min -->
<ng-container *ngIf="phase==='confirmedMin'"> <ng-container *ngIf="phase==='confirmedMin'">
<div>Minimum bestätigt: {{ minSizeResult }}px</div> <div>Minimum bestätigt: {{ minSizeResult }}px</div>
@ -42,6 +49,7 @@
class="bg-blue-600 py-2 px-6 rounded-lg">Weiter zu Maximum</button> class="bg-blue-600 py-2 px-6 rounded-lg">Weiter zu Maximum</button>
</ng-container> </ng-container>
<!-- Phase: Max --> <!-- Phase: Max -->
<ng-container *ngIf="phase==='max'"> <ng-container *ngIf="phase==='max'">
<div>Maximum setzen</div> <div>Maximum setzen</div>
@ -56,6 +64,7 @@
class="bg-green-600 py-2 px-6 rounded-lg">Maximum bestätigen</button> class="bg-green-600 py-2 px-6 rounded-lg">Maximum bestätigen</button>
</ng-container> </ng-container>
<!-- Phase: Confirmed Max --> <!-- Phase: Confirmed Max -->
<ng-container *ngIf="phase==='confirmedMax'"> <ng-container *ngIf="phase==='confirmedMax'">
<div>Maximum bestätigt: {{ maxSizeResult }}px</div> <div>Maximum bestätigt: {{ maxSizeResult }}px</div>
@ -63,6 +72,7 @@
class="bg-blue-600 py-2 px-6 rounded-lg">Weiter zu optiomal</button> class="bg-blue-600 py-2 px-6 rounded-lg">Weiter zu optiomal</button>
</ng-container> </ng-container>
<!-- Phase: Comfortable --> <!-- Phase: Comfortable -->
<ng-container *ngIf="phase==='comfortable'"> <ng-container *ngIf="phase==='comfortable'">
<div>Optimale Größe setzen</div> <div>Optimale Größe setzen</div>
@ -77,6 +87,7 @@
class="bg-green-600 py-2 px-6 rounded-lg">Optimale Größe setzen</button> class="bg-green-600 py-2 px-6 rounded-lg">Optimale Größe setzen</button>
</ng-container> </ng-container>
<!-- Phase: Confirmed Comfortable --> <!-- Phase: Confirmed Comfortable -->
<ng-container *ngIf="phase==='confirmedComfort'"> <ng-container *ngIf="phase==='confirmedComfort'">
<div>Optimale Größe bestätigt: {{ comfortableSizeResult }}px</div> <div>Optimale Größe bestätigt: {{ comfortableSizeResult }}px</div>
@ -84,11 +95,6 @@
class="bg-blue-600 py-2 px-6 rounded-lg">Test beenden</button> class="bg-blue-600 py-2 px-6 rounded-lg">Test beenden</button>
</ng-container> </ng-container>
<!-- Phase: Finished -->
<ng-container *ngIf="phase==='finished'">
<div class="font-semibold text-lg">Vielen Dank!</div>
<p>Ergebnisse werden für die finale Übermittlung gespeichert...</p>
</ng-container>
</div> </div>
</model-viewer> </model-viewer>

View File

@ -15,6 +15,7 @@ import { FormsModule } from '@angular/forms';
import { MetricsTrackerService } from '../../../../services/metrics-tracker.service'; import { MetricsTrackerService } from '../../../../services/metrics-tracker.service';
import '../../../../../assets/scripts/model-viewer'; import '../../../../../assets/scripts/model-viewer';
@Component({ @Component({
selector: 'app-text-legibility-assessment', selector: 'app-text-legibility-assessment',
standalone: true, standalone: true,
@ -28,24 +29,31 @@ export class TextLegibilityAssessmentComponent implements AfterViewInit, OnDestr
@Output() testComplete = new EventEmitter<void>(); @Output() testComplete = new EventEmitter<void>();
@Output() redoTest = new EventEmitter<number>(); @Output() redoTest = new EventEmitter<number>();
private metricsService = inject(MetricsTrackerService); private metricsService = inject(MetricsTrackerService);
minSize = 2; minSize = 2;
maxSize = 64; maxSize = 64;
currentSize = 16; currentSize = 16;
minSizeResult: number | null = null; minSizeResult: number | null = null;
maxSizeResult: number | null = null; maxSizeResult: number | null = null;
comfortableSizeResult: number | null = null; comfortableSizeResult: number | null = null;
phase: 'min' | 'confirmedMin' | 'max' | 'confirmedMax' | 'comfortable' | 'confirmedComfort' | 'finished' = 'min';
phase: 'min' | 'confirmedMin' | 'max' | 'confirmedMax' | 'comfortable' | 'confirmedComfort' = 'min';
private offsetApplied = false; private offsetApplied = false;
constructor(private cdr: ChangeDetectorRef) { constructor(private cdr: ChangeDetectorRef) {
this.logInteraction = this.logInteraction.bind(this); this.logInteraction = this.logInteraction.bind(this);
} }
ngAfterViewInit() { ngAfterViewInit() {
const mv = this.modelViewerRef.nativeElement; const mv = this.modelViewerRef.nativeElement;
mv.addEventListener('ar-status', (event: any) => { mv.addEventListener('ar-status', (event: any) => {
@ -55,18 +63,22 @@ export class TextLegibilityAssessmentComponent implements AfterViewInit, OnDestr
}); });
} }
public logInteraction(event: Event) { public logInteraction(event: Event) {
this.metricsService.logInteraction(event); this.metricsService.logInteraction(event);
} }
decrease() { decrease() {
if (this.currentSize > this.minSize) this.currentSize--; if (this.currentSize > this.minSize) this.currentSize--;
} }
increase() { increase() {
if (this.currentSize < this.maxSize) this.currentSize++; if (this.currentSize < this.maxSize) this.currentSize++;
} }
nextPhase() { nextPhase() {
switch (this.phase) { switch (this.phase) {
case 'min': case 'min':
@ -102,19 +114,20 @@ export class TextLegibilityAssessmentComponent implements AfterViewInit, OnDestr
this.comfortableSizeResult = null; this.comfortableSizeResult = null;
} }
retry() { retry() {
this.redoTest.emit(1); this.redoTest.emit(1);
} }
finishAssessment() {
this.phase = 'finished';
finishAssessment() {
const finalResults = { const finalResults = {
minReadableSize: this.minSizeResult, minReadableSize: this.minSizeResult,
maxReadableSize: this.maxSizeResult, maxReadableSize: this.maxSizeResult,
comfortableReadableSize: this.comfortableSizeResult comfortableReadableSize: this.comfortableSizeResult
}; };
this.metricsService.logInteraction(new CustomEvent('test-results', { this.metricsService.logInteraction(new CustomEvent('test-results', {
detail: { detail: {
testName: 'TextLegibility', testName: 'TextLegibility',
@ -122,15 +135,20 @@ export class TextLegibilityAssessmentComponent implements AfterViewInit, OnDestr
} }
})); }));
console.log(finalResults); console.log(finalResults);
this.testComplete.emit(); this.testComplete.emit();
} }
ngOnDestroy() { ngOnDestroy() {
this.metricsService.stopTracking(); this.metricsService.stopTracking();
} }
} }