From d6ad18e80bd2134d3140323b7bb539faa987a864 Mon Sep 17 00:00:00 2001 From: Xiao Gui <xgui3783@gmail.com> Date: Wed, 12 Sep 2018 11:29:22 +0200 Subject: [PATCH] feat: loading indicators --- src/index.html | 4 + src/res/css/extra_styles.css | 72 ++++++++++++++++++ .../nehubaContainer.component.ts | 75 ++++++++++++++++--- .../nehubaContainer/nehubaContainer.style.css | 29 +++++++ .../nehubaContainer.template.html | 22 ++++++ .../nehubaViewer/nehubaViewer.component.ts | 9 +-- 6 files changed, 197 insertions(+), 14 deletions(-) diff --git a/src/index.html b/src/index.html index 33f639768..ef550de05 100644 --- a/src/index.html +++ b/src/index.html @@ -11,6 +11,10 @@ </head> <body> <atlas-viewer> + Loading the atlas viewer + <span class = "homeAnimationDots loadingAnimationDots">•</span> + <span class = "homeAnimationDots loadingAnimationDots">•</span> + <span class = "homeAnimationDots loadingAnimationDots">•</span> </atlas-viewer> </body> </html> \ No newline at end of file diff --git a/src/res/css/extra_styles.css b/src/res/css/extra_styles.css index 82f035c9b..ae82ca6de 100644 --- a/src/res/css/extra_styles.css +++ b/src/res/css/extra_styles.css @@ -145,3 +145,75 @@ markdown-dom pre code { width:1em; } + +@keyframes explode +{ + 0% { + opacity: 0.0; + } + 30% { + opacity: 1.0 + } + 100% { + opacity: 0.0; + } +} + +.loadingAnimationDots:nth-child(1) +{ + animation: explode 1s ease infinite running; +} +.loadingAnimationDots:nth-child(2) +{ + animation: explode 1s ease 0.2s infinite running; +} +.loadingAnimationDots:nth-child(3) +{ + animation: explode 1s ease 0.4s infinite running; +} +.loadingAnimationDots:nth-child(4) +{ + animation: explode 1s ease 0.6s infinite running; +} +.loadingAnimationDots:nth-child(5) +{ + animation: explode 1s ease 0.8s infinite running; +} + +.homeAnimationDots:nth-child(1) +{ + color: red; +} +.homeAnimationDots:nth-child(2) +{ + color: blue; +} +.homeAnimationDots:nth-child(3) +{ + color: green; +} + +@keyframes spinning +{ + from { + transform: rotate(0deg); + } + to{ + transform: rotate(359deg); + } +} + +#homeSpinning +{ + font-size: 200%; +} + +.spinnerAnimationCircle +{ + width: 1em; + height:1em; + border-radius: 50%; + border: 0.2em rgba(128,128,128,0.2) solid; + border-top: 0.2em rgba(128,128,128,0.99) solid; + animation: spinning 700ms linear infinite running; +} \ No newline at end of file diff --git a/src/ui/nehubaContainer/nehubaContainer.component.ts b/src/ui/nehubaContainer/nehubaContainer.component.ts index 594637892..71b944c9f 100644 --- a/src/ui/nehubaContainer/nehubaContainer.component.ts +++ b/src/ui/nehubaContainer/nehubaContainer.component.ts @@ -27,6 +27,11 @@ export class NehubaContainer implements OnInit, OnDestroy{ public viewerLoaded : boolean = false + public sliceViewLoading0$: Observable<boolean> + public sliceViewLoading1$: Observable<boolean> + public sliceViewLoading2$: Observable<boolean> + public perspectiveViewLoading$: Observable<string|null> + private newViewer$ : Observable<any> private selectedParcellation$ : Observable<any> private selectedRegions$ : Observable<any[]> @@ -47,7 +52,7 @@ export class NehubaContainer implements OnInit, OnDestroy{ private ngLayersRegister : NgViewerStateInterface = {layers : [], forceShowSegment: null} private ngLayers$ : Observable<NgViewerStateInterface> - private selectedParcellationNgId : string + public selectedParcellation : any | null private cr : ComponentRef<NehubaViewerUnit> @@ -161,6 +166,12 @@ export class NehubaContainer implements OnInit, OnDestroy{ .pipe( scan((acc:Event[],event:Event)=>{ const target = (event as Event).target as HTMLElement + /** + * 0 | 1 + * 2 | 3 + * + * 4 ??? + */ const key = target.offsetLeft < 5 && target.offsetTop < 5 ? 0 : target.offsetLeft > 5 && target.offsetTop < 5 ? @@ -186,6 +197,60 @@ export class NehubaContainer implements OnInit, OnDestroy{ [0,1,2].forEach(idx=>this.nanometersToOffsetPixelsFn[idx] = (events[idx] as any).detail.nanometersToOffsetPixels) }) + this.sliceViewLoading0$ = fromEvent(this.elementRef.nativeElement, 'sliceRenderEvent') + .pipe( + filter((event:Event) => (event.target as HTMLElement).offsetLeft < 5 && (event.target as HTMLElement).offsetTop < 5), + map(event => { + const e = (event as any); + const num1 = typeof e.detail.missingChunks === 'number' ? e.detail.missingChunks : 0 + const num2 = typeof e.detail.missingImageChunks === 'number' ? e.detail.missingImageChunks : 0 + return Math.max(num1, num2) > 0 + }) + ) + + this.sliceViewLoading1$ = fromEvent(this.elementRef.nativeElement, 'sliceRenderEvent') + .pipe( + filter((event:Event) => (event.target as HTMLElement).offsetLeft > 5 && (event.target as HTMLElement).offsetTop < 5), + map(event => { + const e = (event as any); + const num1 = typeof e.detail.missingChunks === 'number' ? e.detail.missingChunks : 0 + const num2 = typeof e.detail.missingImageChunks === 'number' ? e.detail.missingImageChunks : 0 + return Math.max(num1, num2) > 0 + }) + ) + + this.sliceViewLoading2$ = fromEvent(this.elementRef.nativeElement, 'sliceRenderEvent') + .pipe( + filter((event:Event) => (event.target as HTMLElement).offsetLeft < 5 && (event.target as HTMLElement).offsetTop > 5), + map(event => { + const e = (event as any); + const num1 = typeof e.detail.missingChunks === 'number' ? e.detail.missingChunks : 0 + const num2 = typeof e.detail.missingImageChunks === 'number' ? e.detail.missingImageChunks : 0 + return Math.max(num1, num2) > 0 + }) + ) + + /* missing chunk perspective view */ + this.perspectiveViewLoading$ = fromEvent(this.elementRef.nativeElement, 'perpspectiveRenderEvent') + .pipe( + filter(event => isDefined(event) && isDefined((event as any).detail) && isDefined((event as any).detail.lastLoadedMeshId) ), + map(event => { + + const e = (event as any) + const lastLoadedIdString = e.detail.lastLoadedMeshId.split(',')[0] + const lastLoadedIdNum = Number(lastLoadedIdString) + return e.detail.meshesLoaded >= this.regionsLabelIndexMap.size + ? null + : isNaN(lastLoadedIdNum) + ? 'Loading unknown chunk' + : lastLoadedIdNum >= 65500 + ? 'Loading auxiliary chunk' + : this.regionsLabelIndexMap.get(lastLoadedIdNum) + ? `Loading ${this.regionsLabelIndexMap.get(lastLoadedIdNum).name}` + : 'Loading unknown chunk ...' + }) + ) + this.combinedSpatialData$ = combineLatest( combineLatest( this.fetchedSpatialDatasets$, @@ -397,13 +462,6 @@ export class NehubaContainer implements OnInit, OnDestroy{ return pos } - // get combinedSpatialData$(){ - // return (this.fetchedSpatialData - // .filter(() => this.spatialResultsVisible) - // .map(v => Object.assign({}, v, {type: 'spatial'})) as any[]) - // .concat(this.userLandmarks.map(v => Object.assign({}, v, {type: 'user'}))) - // } - getPositionX(quadrant:number,data:any){ return this.returnTruePos(quadrant,data)[0] } @@ -426,7 +484,6 @@ export class NehubaContainer implements OnInit, OnDestroy{ this.regionsLabelIndexMap = getLabelIndexMap(parcellation.regions) this.nehubaViewer.regionsLabelIndexMap = this.regionsLabelIndexMap this.nehubaViewer.parcellationId = parcellation.ngId - this.selectedParcellationNgId = parcellation.ngId this.selectedParcellation = parcellation } diff --git a/src/ui/nehubaContainer/nehubaContainer.style.css b/src/ui/nehubaContainer/nehubaContainer.style.css index 83626740a..ac5c9d805 100644 --- a/src/ui/nehubaContainer/nehubaContainer.style.css +++ b/src/ui/nehubaContainer/nehubaContainer.style.css @@ -107,4 +107,33 @@ div[linksContainer] { display:inline-block; margin-left:1em; +} + +div[landmarkMasterContainer] > div > [landmarkContainer] > div.loadingIndicator +{ + left: auto; + top: auto; + right: 0; + bottom: 0; + margin-right: 0.2em; + margin-bottom: 0.2em; + width: 100%; + height:2em; + display: flex; + flex-direction: row-reverse; +} + +div.loadingIndicator div.spinnerAnimationCircle +{ + font-size:150%; +} + +[perspectiveLoadingText] +{ + margin-right: 1em; +} + +:host-context([darktheme="true"]) [perspectiveLoadingText] +{ + color:rgba(255,255,255,0.8); } \ No newline at end of file diff --git a/src/ui/nehubaContainer/nehubaContainer.template.html b/src/ui/nehubaContainer/nehubaContainer.template.html index 0e22c3267..2d2c633e7 100644 --- a/src/ui/nehubaContainer/nehubaContainer.template.html +++ b/src/ui/nehubaContainer/nehubaContainer.template.html @@ -20,6 +20,12 @@ [positionY] = "getPositionY(0,spatialData)" [positionZ] = "getPositionZ(0,spatialData)"> </nehuba-2dlandmark-unit> + + <div *ngIf = "sliceViewLoading0$ | async" class = "loadingIndicator"> + <div class = "spinnerAnimationCircle"> + + </div> + </div> </layout-floating-container> </div> <div> @@ -36,6 +42,11 @@ [positionY] = "getPositionY(1,spatialData)" [positionZ] = "getPositionZ(1,spatialData)"> </nehuba-2dlandmark-unit> + <div *ngIf = "sliceViewLoading1$ | async" class = "loadingIndicator"> + <div class = "spinnerAnimationCircle"> + + </div> + </div> </layout-floating-container> </div> <div> @@ -52,12 +63,23 @@ [positionY] = "getPositionY(2,spatialData)" [positionZ] = "getPositionZ(2,spatialData)"> </nehuba-2dlandmark-unit> + <div *ngIf = "sliceViewLoading2$ | async" class = "loadingIndicator"> + <div class = "spinnerAnimationCircle"> + + </div> + </div> </layout-floating-container> </div> <div> <layout-floating-container pos11 landmarkContainer> + <div *ngIf = "perspectiveViewLoading$ | async" class = "loadingIndicator"> + <div class = "spinnerAnimationCircle"></div> + <div perspectiveLoadingText> + {{ perspectiveViewLoading$ | async }} + </div> + </div> </layout-floating-container> </div> </div> diff --git a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts b/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts index 53e26e19d..fdc89f294 100644 --- a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts +++ b/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts @@ -87,12 +87,10 @@ export class NehubaViewerUnit implements AfterViewInit,OnDestroy{ public mouseOverSegment : number | null ngAfterViewInit(){ - this.nehubaViewer = export_nehuba.createNehubaViewer(this.config,(err)=>{ + this.nehubaViewer = export_nehuba.createNehubaViewer(this.config, (err)=>{ /* print in debug mode */ + console.log('xgui3783', err) }); - - // console.log(export_nehuba) - (<any>window).quat = export_nehuba.quat if(this.regionsLabelIndexMap){ const managedLayers = this.nehubaViewer.ngviewer.layerManager.managedLayers @@ -487,7 +485,8 @@ export interface ViewerState{ } export function getAuxilliaryLabelIndices(){ - return Array.from(Array(36)).map((_,i)=>65500+i) + return [65535] + // return Array.from(Array(36)).map((_,i)=>65500+i) } export const ICOSAHEDRON = `# vtk DataFile Version 2.0 -- GitLab