From 1d880e49d92b80965fd1b00c5601371d75f814c8 Mon Sep 17 00:00:00 2001 From: Sheik Althaf Date: Thu, 24 Aug 2023 04:16:21 +0000 Subject: [PATCH] feat: improve performace --- .../ngu/magnify/src/lib/magnify.directive.ts | 56 ++++++++++++++++--- .../ngu/magnify/src/lib/magnify.service.ts | 45 +++++++++++---- src/app/app.component.html | 2 +- 3 files changed, 84 insertions(+), 19 deletions(-) diff --git a/projects/ngu/magnify/src/lib/magnify.directive.ts b/projects/ngu/magnify/src/lib/magnify.directive.ts index af597a3..c0c1df5 100644 --- a/projects/ngu/magnify/src/lib/magnify.directive.ts +++ b/projects/ngu/magnify/src/lib/magnify.directive.ts @@ -8,7 +8,7 @@ import { OnInit, OnDestroy, } from '@angular/core'; -import { Subscription } from 'rxjs'; +import { Subject, Subscription } from 'rxjs'; import { MagnifyService } from './magnify.service'; @Directive({ @@ -28,23 +28,36 @@ export class Magnify implements OnInit, OnDestroy { private scaleYValue = 1; subscription: Subscription; zSubscription: Subscription; + z$ = new Subject(); + isZoomed = false; + id = Date.now().toString(); constructor( private el: ElementRef, private renderer: Renderer2, private ngZone: NgZone - ) {} + ) { + this.magnifyService.add(this.id); + } ngOnInit() { this.ngZone.runOutsideAngular(() => { this.el.nativeElement.addEventListener('load', this.updateSizes, { once: true, }); - this.init(); + // this.initClick(); + this.zInit(); + }); + } + + private initClick() { + this.el.nativeElement.addEventListener('click', (ev) => { + this.isZoomed = !this.isZoomed; + this.z$.next(this.isZoomed); }); } - private init() { + private zInit() { this.zSubscription = this.magnifyService.z$.subscribe((res) => { if (res) { this.el.nativeElement.addEventListener('mouseenter', this.onMouseEnter); @@ -58,6 +71,7 @@ export class Magnify implements OnInit, OnDestroy { 'mouseenter', this.onMouseEnter ); + // this.onMouseEnter(); this.onMouseLeave(); } }); @@ -73,6 +87,7 @@ export class Magnify implements OnInit, OnDestroy { this.zSubscription?.unsubscribe(); this.subscription?.unsubscribe(); this.div?.remove(); + this.magnifyService.remove(this.id); } updateSizes = () => { @@ -96,20 +111,46 @@ export class Magnify implements OnInit, OnDestroy { private getValues(rect: DOMRect, parent: DOMRect) { let left = rect.left - parent.left; - const top = rect.top - parent.top; + let top = rect.top - parent.top; let cWidth = rect.width; let cHeight = rect.height; + if (!this.inline) { - left += rect.width + 40; cWidth = 400; cHeight = 400; } + const width = rect.width * this.scale; const localScale = width / rect.width; const height = rect.height * localScale; + this.scaleXValue = (width - cWidth) / rect.width; this.scaleYValue = (height - cHeight) / rect.height; - return { cWidth, cHeight, left, top, width, height }; + + if (!this.inline) { + // Determine whether to show magnified image on the left or right + const screenWidth = window.innerWidth; + const showOnLeft = left > screenWidth / 2; + + left = showOnLeft ? left - cWidth - 10 : left + rect.width + 10 + + // Determine whether to position magnified image above or below original image + const screenHeight = window.innerHeight; + const showAbove = (top + cHeight) > screenHeight; + + if (showAbove) { + top -= (cHeight - rect.height); + } + } + + return { + cWidth, + cHeight, + left, + top, + width, + height + }; } private get parentElement() { @@ -177,6 +218,7 @@ export class Magnify implements OnInit, OnDestroy { onMouseLeave = () => { // this.el.nativeElement.removeEventListener('mousemove', this.onMouseMove); this.subscription?.unsubscribe(); + this.isZoomed = false; this.el.nativeElement.removeEventListener('mouseleave', this.onMouseLeave); if (this.div) this.renderer.setStyle(this.div, 'display', 'none'); }; diff --git a/projects/ngu/magnify/src/lib/magnify.service.ts b/projects/ngu/magnify/src/lib/magnify.service.ts index 3041c8c..7d00dd4 100644 --- a/projects/ngu/magnify/src/lib/magnify.service.ts +++ b/projects/ngu/magnify/src/lib/magnify.service.ts @@ -1,25 +1,48 @@ -import { Injectable, NgZone } from '@angular/core'; -import { Subject } from 'rxjs'; +import { Injectable, NgZone, inject } from '@angular/core'; +import { Subject, Subscription } from 'rxjs'; import { KeysEvent } from './keysEvent'; @Injectable({ providedIn: 'root' }) export class MagnifyService { - keyEvents = new KeysEvent(); + private keyEvents = new KeysEvent(); currentMousePosition: MouseEvent; currentMouse$ = new Subject(); z$ = new Subject(); + private ngZone = inject(NgZone); + private zSubscription: Subscription; + private observersIds = new Set(); + private isConnected = false; - constructor(private ngZone: NgZone) { + constructor() {} + + private onMouseMove = (ev: MouseEvent) => { + this.currentMousePosition = ev; + this.currentMouse$.next(ev); + }; + + add(id: string) { + this.observersIds.add(id); + if (!this.isConnected) this.connect(); + } + + remove(id: string) { + this.observersIds.delete(id); + if (this.observersIds.size === 0) this.disconnect(); + } + + private disconnect() { + document.removeEventListener('mousemove', this.onMouseMove); + this.zSubscription?.unsubscribe(); + this.isConnected = false; + } + + private connect() { this.ngZone.runOutsideAngular(() => { - document.addEventListener('mousemove', (ev) => this.onMouseMove(ev)); - this.keyEvents.event('z').subscribe(([res, ev]) => { + this.isConnected = true; + document.addEventListener('mousemove', ev => this.onMouseMove(ev)); + this.zSubscription = this.keyEvents.event('z').subscribe(([res, ev]) => { this.z$.next(res); }); }); } - - onMouseMove = (ev: MouseEvent) => { - this.currentMousePosition = ev; - this.currentMouse$.next(ev); - }; } diff --git a/src/app/app.component.html b/src/app/app.component.html index fd7ec0b..1653d61 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -4,7 +4,7 @@ -
+