Created
January 31, 2026 13:24
-
-
Save CodingBash/2da85d53b958de164b4b7c16dbe49b90 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!-- Hide if not in view or --> | |
| <div [hidden]="!(inView || overrideShow)"> | |
| <img [style.maxWidth]="img_width" [style.maxHeight]="img_height" [src]="imageSrc" style="min-width: 100px; min-height: 20px;" class="zoom loading"> | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { isPlatformBrowser } from '@angular/common'; | |
| import { ChangeDetectorRef } from '@angular/core'; | |
| import { Component, ElementRef, EventEmitter, Inject, Input, OnChanges, OnDestroy, OnInit, Output, PLATFORM_ID, Renderer2, SimpleChanges } from '@angular/core'; | |
| import { Observable } from 'rxjs'; | |
| import { map } from 'rxjs/operators'; | |
| import { ComponentBasicModelViewer } from 'src/app/models/postproc-component-classes'; | |
| import { FitDetailsService } from 'src/app/services/fit-details.service'; | |
| /** | |
| * Component from https://medium.com/allenhwkim/simple-lazy-loading-with-angular-716dd3b174a | |
| */ | |
| @Component({ | |
| selector: 'image-in-view', | |
| templateUrl: './image-in-view.component.html', | |
| styleUrls: ['./image-in-view.component.css'] | |
| }) | |
| export class ImageInViewComponent implements OnInit, OnDestroy, OnChanges { | |
| observer: IntersectionObserver; | |
| inView: boolean = false; | |
| once50PctVisible: boolean = false; | |
| imageSrc: string; | |
| imageLoadedOrLoading = false; | |
| @Input('representativeFit') representativeFit: number; | |
| @Input('img_width') img_width: string; | |
| @Input('img_height') img_height: string; | |
| @Input('override') overrideShow: boolean = false; | |
| @Input() options: any = { threshold: [.1, .2, .3, .4, .5, .6, .7, .8] }; | |
| @Output('inView') inView$: EventEmitter<any> = new EventEmitter(); | |
| @Output('notInView') notInView$: EventEmitter<any> = new EventEmitter(); | |
| constructor( | |
| public element: ElementRef, | |
| public renderer: Renderer2, | |
| private fitDetailsService: FitDetailsService, | |
| private cdRef: ChangeDetectorRef, | |
| @Inject(PLATFORM_ID) private platformId: any) { } | |
| /** | |
| * When a component is initialized, it will register an IntersectionObserver, so that when element is visible, it calls the callback handleIntersect. | |
| */ | |
| ngOnInit(): void { | |
| if (isPlatformBrowser(this.platformId)) { | |
| this.observer = new IntersectionObserver(this.handleIntersect.bind(this), this.options); | |
| this.observer.observe(this.element.nativeElement); | |
| } | |
| /* | |
| * If override is true on init, then load image | |
| */ | |
| if (this.overrideShow && !this.imageLoadedOrLoading) { | |
| console.log("Image loaded by override true at init") | |
| this.imageLoadedOrLoading = true; | |
| this.getFitLogoSrc(this.representativeFit).subscribe(src => { | |
| console.log("Image source set"); | |
| this.imageSrc = src; | |
| }); | |
| } | |
| } | |
| ngOnChanges(changes: SimpleChanges) { | |
| /* | |
| * If override becomes true and image is not loaded already loaded, then load. | |
| */ | |
| if (changes.overrideShow != undefined && changes.overrideShow.currentValue != changes.overrideShow.previousValue) { | |
| if (changes.overrideShow.currentValue && this.imageSrc == undefined && !this.imageLoadedOrLoading) { | |
| console.log("Image loaded by change in override") | |
| this.imageLoadedOrLoading = true; | |
| this.getFitLogoSrc(this.representativeFit).subscribe(src => { | |
| console.log("Image source set"); | |
| this.imageSrc = src; | |
| this.cdRef.detectChanges(); | |
| }); | |
| } | |
| } | |
| } | |
| ngOnDestroy(): void { | |
| this.observer.disconnect(); | |
| } | |
| /** | |
| * The observer callback handleIntersect sets inView to true and fires inView$ event when the element is visible and fires notInView$ event when the element is not visible. | |
| * | |
| * @param entries | |
| * @param observer | |
| */ | |
| handleIntersect(entries, observer): void { | |
| entries.forEach((entry: IntersectionObserverEntry) => { | |
| if (entry.isIntersecting) { | |
| /* | |
| * If image is in view, load image and remove hidden | |
| */ | |
| if (this.imageSrc == undefined && !this.imageLoadedOrLoading) { | |
| console.log("Image loaded by becoming in view"); | |
| this.imageLoadedOrLoading = true; | |
| this.getFitLogoSrc(this.representativeFit).subscribe(src => { | |
| console.log("Image source set"); | |
| this.imageSrc = src; | |
| }); | |
| } | |
| this.inView = true; | |
| this.inView$.emit(entry); | |
| } else { | |
| this.notInView$.emit(entry); | |
| } | |
| }); | |
| } | |
| /** | |
| * TODO: Cache the basicmodelviewer call by creating a separate web rest endpoint for image URLs specifically, the cache that instead of the whole basicModelViewer call since this may change. Alternatively, I can create a runtime object or local storage object to contain fit->image hashtable for quick lookup. | |
| * | |
| * @param fitId | |
| */ | |
| getFitLogoSrc(fitId: number): Observable<string> { | |
| return this.fitDetailsService.getFitPostproc(fitId, "basicModelViewer").pipe(map((postprocComponent) => { | |
| if (postprocComponent == null) { | |
| return null; | |
| } else { | |
| let basicModelViewerComponent: ComponentBasicModelViewer = <ComponentBasicModelViewer>postprocComponent; | |
| let mononucleotideResourceNoAxesForwardLink = basicModelViewerComponent.viewBindingModels[0].mononucleotideResourceNoAxesForwardLink; | |
| return mononucleotideResourceNoAxesForwardLink; | |
| } | |
| })); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment