diff --git a/src/ui/help/helpOnePager/helpOnePager.template.html b/src/ui/help/helpOnePager/helpOnePager.template.html index c309155ae5174ca4c62034fc8ab758913cbc71a3..5deb0814295c1c67a71fc641dd6698e47795b7cd 100644 --- a/src/ui/help/helpOnePager/helpOnePager.template.html +++ b/src/ui/help/helpOnePager/helpOnePager.template.html @@ -3,6 +3,16 @@ <div mat-dialog-actions align="center"> + + <button mat-button color="primary" mat-dialog-close quick-tour> + <span class="d-flex align-items-center"> + Take a tour + <mat-icon fontSet="far" fontIcon="fa-play-circle"> + </mat-icon> + </span> + + </button> + <a *ngIf="extQuickStarter" [href]="extQuickStarter" target="_blank"> @@ -16,4 +26,4 @@ </a> <button mat-button mat-dialog-close cdkFocusInitial>close</button> -</div> \ No newline at end of file +</div> diff --git a/src/ui/help/module.ts b/src/ui/help/module.ts index 4a34ab43a3cf9efa449eb2edcd2150921a53e744..9decffaa2985077251f945e7a55c20b1924390d7 100644 --- a/src/ui/help/module.ts +++ b/src/ui/help/module.ts @@ -5,6 +5,7 @@ import { UtilModule } from "src/util"; import { AngularMaterialModule } from "../sharedModules/angularMaterial.module"; import { AboutCmp } from './about/about.component' import { HelpOnePager } from "./helpOnePager/helpOnePager.component"; +import {QuickTourModule} from "src/ui/quickTour/module"; @NgModule({ imports: [ @@ -12,6 +13,7 @@ import { HelpOnePager } from "./helpOnePager/helpOnePager.component"; AngularMaterialModule, ComponentsModule, UtilModule, + QuickTourModule ], declarations: [ AboutCmp, @@ -23,4 +25,4 @@ import { HelpOnePager } from "./helpOnePager/helpOnePager.component"; ] }) -export class HelpModule{} \ No newline at end of file +export class HelpModule{} diff --git a/src/ui/quickTour/module.ts b/src/ui/quickTour/module.ts new file mode 100644 index 0000000000000000000000000000000000000000..b027e558fccd92fd39d2491193a96b0e8cbe52e1 --- /dev/null +++ b/src/ui/quickTour/module.ts @@ -0,0 +1,27 @@ +import { FullscreenOverlayContainer, OverlayContainer } from "@angular/cdk/overlay"; +import { CommonModule } from "@angular/common"; +import { NgModule } from "@angular/core"; +import { UtilModule } from "src/util"; +import { AngularMaterialModule } from "../sharedModules/angularMaterial.module"; +import {QuickTourComponent} from "src/ui/quickTour/quickToutCmp/quickTour.component"; +import {QuickTourDirective} from "src/ui/quickTour/quickTour.directive"; + +@NgModule({ + imports: [ + CommonModule, + AngularMaterialModule, + UtilModule, + ], + declarations:[ + QuickTourDirective, + QuickTourComponent, + ], + exports: [ + QuickTourDirective, + ], + providers:[{ + provide: OverlayContainer, + useClass: FullscreenOverlayContainer + }] +}) +export class QuickTourModule{} diff --git a/src/ui/quickTour/quickTour.directive.ts b/src/ui/quickTour/quickTour.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..2ca41054593adf91776d3ef19a572a572c6f0224 --- /dev/null +++ b/src/ui/quickTour/quickTour.directive.ts @@ -0,0 +1,68 @@ +import { Overlay, OverlayRef } from "@angular/cdk/overlay"; +import { ComponentPortal } from "@angular/cdk/portal"; +import {ComponentRef, Directive, HostListener} from "@angular/core"; +import { take } from "rxjs/operators"; +import {QuickTourComponent} from "src/ui/quickTour/quickToutCmp/quickTour.component"; + +@Directive({ + selector: '[quick-tour]' +}) + +export class QuickTourDirective { + public touring = false + + private overlayRef: OverlayRef + private cmpRef: ComponentRef<QuickTourComponent> + + @HostListener('window:keydown', ['$event']) + keyListener(ev: KeyboardEvent){ + if (ev.key === 'Escape') { + if (this.overlayRef) this.dispose() + } + } + + @HostListener('click') + onClick(){ + + this.overlayRef = this.overlay.create({ + + height: '0px', + width: '0px', + + hasBackdrop: false, + positionStrategy: this.overlay.position().global(), + // panelClass: ['w-100', 'h-100'], + }) + + this.cmpRef = this.overlayRef.attach( + new ComponentPortal(QuickTourComponent) + ) + + this.cmpRef.instance.destroy.pipe( + take(1) + ).subscribe( + () => { + this.dispose() + } + ) + + + } + + dispose(){ + this.cmpRef = null + if (this.overlayRef) this.overlayRef.dispose() + this.overlayRef = null + } + + reset(){ + this.touring = true + } + + clear(){ + this.touring = false + } + + constructor(private overlay: Overlay){} + +} diff --git a/src/ui/quickTour/quickToutCmp/quickTour.component.ts b/src/ui/quickTour/quickToutCmp/quickTour.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..6c5e051665b813fb060ab6042c48c421f041c98f --- /dev/null +++ b/src/ui/quickTour/quickToutCmp/quickTour.component.ts @@ -0,0 +1,327 @@ +import {AfterViewInit, Component, EventEmitter, HostListener, OnDestroy, Output} from "@angular/core"; + +@Component({ + selector : 'quick-tour', + templateUrl : './quickTour.temlate.html', + styleUrls : ['./quickTour.style.css',], +}) +export class QuickTourComponent implements AfterViewInit, OnDestroy { + + @Output() destroy = new EventEmitter() + public currentTip = 0 + public numberOfSteps = null + private observers: any[] = [] + + public slides: any[] = [ + { + description: 'This is the atlas selector. Click here to choose between EBRAINS reference atlases of different species.', + tooltipRight: '10px', + tooltipTop: '65px', + arrowPosition: 'top', + arrowMargin: '0 0 0 60%', + arrow: 'arrow1', + + step: 1, + }, + + { + description: 'The planar views allow you to zoom in to full resolution (mouse wheel), pan the view (click+drag), and select oblique sections (shift+click+drag). You can double-click brain regions to select them.', + tooltipLeft: 'calc(50% - 50px)', + tooltipTop: 'calc(50% - 50px)', + arrowPosition: 'top', + arrow: 'arrow5', + textMargin: '-60px 0px 0px 45px', + + step: 2, + }, + { + description: 'The 3D view gives an overview of the brain with limited resolution. It can be independently rotated. Click the „eye“ icon on the bottom left to toggle pure surface view.', + tooltipLeft: 'calc(50% - 300px)', + tooltipTop: 'calc(50% - 160px)', + arrowPosition: 'bottom', + arrow: 'arrow6', + arrowMargin: '-10 0 0 calc(100% + 10px)', + arrowTransform: 'rotate(130deg)', + step: 3, + }, + + { + description: 'Use these icons in any of the views to maximize it and zoom in/out.', + tooltipRight: '122px', + tooltipTop: 'calc(50% - 28px)', + arrowPosition: 'top', + arrowMargin: '0 100% -8px calc(100% + 5px)', + arrow: 'arrow6', + + arrowTransform: 'rotate(40deg)', + + step: 4, + }, + + { + description: 'This is the atlas layer browser. If an atlas supports multiple template spaces or parcellation maps, you will find them here.', + tooltipLeft: '18px', + tooltipTop: 'calc(100vh - 230px)', + arrow: 'arrow2', + arrowMargin: '100% 0px 0px 0px', + arrowPosition: 'left', + autoNext: 'layerSelectorOpened', + viewAttached: 'sidebarRegion', + step: 5, + }, + + { + description: 'Choose other available templates or parcellations here.', + tooltipLeft: '300px', + tooltipTop: 'calc(100vh - 550px)', + arrow: 'arrow6', + arrowMargin: '30px 14px 0px 15px', + arrowTransform: 'rotate(-120deg)', + arrowPosition: 'left', + viewAttached: 'sidebarRegion', + documentClickOnNext: true, + step: 5, + }, + + + { + description: 'These „chips“ indicate the currently selected parcellation map as well as selected region. Click the chip to see different versions, if any. Click (i) to read more about a selected item. Click (x) to clear a selection.', + tooltipLeft: '18px', + tooltipTop: 'calc(100vh - 340px)', + arrow: 'arrow1', + arrowTransform: 'scaleX(-1) rotate(170deg)', + arrowMargin: '0 0 0 100px', + arrowPosition: 'bottom', + viewAttached: 'sidebarRegion', + documentClickOnNext: true, + step: 6, + }, + { + description: 'This is the coordinate navigator. Expand it to manipulate voxel and physical coordinates, to reset the view, or to create persistent links to the current view for sharing.', + tooltipLeft: '50px', + tooltipTop: '55px', + arrowPosition: 'top', + arrow: 'arrow1', + autoNext: 'viewerStatusOpened', + viewAttached: 'sidebar', + step: 7, + }, + + { + description: 'You can to manipulate voxel and physical coordinates, to reset the view, or to create persistent links to the current view for sharing.', + tooltipLeft: '30px', + tooltipTop: '130px', + arrowPosition: 'top', + arrow: 'arrow6', + arrowMargin: '0 0 0 50%', + viewAttached: 'sidebar', + step: 7, + }, + + { + description: 'Open sidebar to find the region quick search.', + tooltipTop: '80px', + arrow: 'arrow2', + arrowMargin: '-40px 0 0 0', + arrowTransform: 'scaleX(-1) rotate(180deg)', + arrowPosition: 'arrow2', + autoNext: 'sidebarOpened', + step: 8, + }, + + { + description: 'Use the region quick search for finding, selecting and navigating brain regions in the selected parcellation map.', + tooltipTop: '65px', + arrow: 'arrow6', + arrowMargin: '-50px 10px 0 40px', + arrowTransform: 'rotate(-55deg)', + arrowPosition: 'left', + documentClickOnNext: true, + step: 8, + }, + + { + description: 'These icons provide access to plugins, pinned datasets, and user documentation. Use the profile icon to login with your EBRAINS account.', + tooltipRight: '125px', + tooltipTop: '55px', + arrowPosition: 'top', + arrowMargin: '0 0 0 50%', + arrowTransform: 'scaleX(-1)', + arrow: 'arrow1', + + step: 9, + }, + ] + + + constructor() { + this.numberOfSteps = new Array([...this.slides].filter(s => s.step).pop()['step']) + } + + ngAfterViewInit() { + const layerSelectorEl = document.querySelector('atlas-layer-selector') + + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (this.slides[this.currentTip]?.autoNext === 'layerSelectorOpened' && mutation.target['dataset']['opened'] === 'true') { + this.currentTip += 1 + } else if (this.slides[this.currentTip-1]?.autoNext === 'layerSelectorOpened' && mutation.target['dataset']['opened'] === 'false') { + this.currentTip -= 1 + } + }) + }) + + const observerConfig = { + attributes: true, + childList: true, + characterData: true + } + + observer.observe(layerSelectorEl, observerConfig) + + this.observers.push(observer) + } + + @HostListener('document:click', ['$event']) + documentClick(event) { + // Auto change view when nehuba navigation status is opened + const nehubaStatus = document.querySelector('iav-cmp-viewer-nehuba-status') + const nehubaStatusContainer = nehubaStatus? nehubaStatus.querySelector('mat-card.expandedContainer') : null + if (this.slides[this.currentTip]?.autoNext === 'viewerStatusOpened' && nehubaStatusContainer) { + this.currentTip += 1 + } else if(this.slides[this.currentTip-1]?.autoNext === 'viewerStatusOpened' && !nehubaStatusContainer) { + this.currentTip -= 1 + } + + // Auto move to region search tip when sidebar is opened + const drawerElement = document.getElementsByTagName('mat-drawer')[0] as HTMLElement + const drawerOpened = drawerElement.getAttribute('data-mat-drawer-top-open') === 'true' + if (this.slides[this.currentTip]?.autoNext === 'sidebarOpened' && drawerOpened) { + const drawerWidth = drawerElement.offsetWidth + this.currentTip += 1 + this.slides[this.currentTip].tooltipLeft = drawerWidth-100 + 'px' + } else if(this.slides[this.currentTip-1]?.autoNext === 'sidebarOpened' && !drawerOpened) { + this.currentTip -= 1 + } + + // Check sidebar status when on open/close + const clickInsideCdkOverlay = document.querySelector('.cdk-overlay-container')?.contains(event.target) + if (!clickInsideCdkOverlay) { + this.checkSidebarStatus() + } + + } + + + goBack() { + // Click document for closing menu + if (this.slides[this.currentTip]?.documentClickOnNext) { + document.body.click() + } + // Moeve to prev tip + this.currentTip = this.slides.findIndex(s => s.step === this.slides[this.currentTip].step-1) + + //Checks + //// Layer selector status + this.checkAtlasLayerSelectorState() + //// Sidebar status + if (this.slides[this.currentTip]?.viewAttached === 'sidebar' || this.slides[this.currentTip]?.viewAttached === 'sidebarRegion') { + this.checkSidebarStatus() + } + } + + goForward() { + // Click document for closing menu + if (this.slides[this.currentTip]?.documentClickOnNext) { + document.body.click() + } + // Moeve to next tip + this.currentTip = this.slides.findIndex(s => s.step === this.slides[this.currentTip].step+1) + // Checks + //// Layer selector status + this.checkAtlasLayerSelectorState() + //// Sidebar status + if (this.slides[this.currentTip]?.viewAttached === 'sidebar' || this.slides[this.currentTip]?.viewAttached === 'sidebarRegion') { + this.checkSidebarStatus() + } + } + + moveToTipByIndex(index) { + // Click document for closing menu + if (this.slides[this.currentTip]?.documentClickOnNext) { + document.body.click() + } + // Moeve to next tip + this.currentTip = this.slides.findIndex(s => s.step === index+1) + // Checks + //// Layer selector status + this.checkAtlasLayerSelectorState() + //// Sidebar status + if (this.slides[this.currentTip]?.viewAttached === 'sidebar' || this.slides[this.currentTip]?.viewAttached === 'sidebarRegion') { + this.checkSidebarStatus() + } + } + + + checkAtlasLayerSelectorState() { + const layerSelectorEl = document.querySelector('atlas-layer-selector') + + if (this.slides[this.currentTip]?.autoNext === 'layerSelectorOpened' && layerSelectorEl['dataset']['opened'] === 'true') { + this.currentTip += 1 + } + } + + private lastTipForSidebar = null + private drawerOpened = false + private drawerExpanded = false + checkSidebarStatus() { + const drawerElement = document.getElementsByTagName('mat-drawer')[0] as HTMLElement + const expandDrawer = document.getElementsByTagName('mat-drawer')[1] as HTMLElement + const drawerOpened = drawerElement.getAttribute('data-mat-drawer-top-open') === 'true' + const drawerExpanded = expandDrawer.getAttribute('data-mat-drawer-fullleft-open') === 'true' + + const drawerWidth = drawerElement.offsetWidth + + if (this.slides[this.currentTip]?.viewAttached === 'sidebar' || this.slides[this.currentTip]?.viewAttached === 'sidebarRegion' + && this.slides[this.currentTip].tooltipLeft) { + + if (this.slides[this.currentTip]?.viewAttached === 'sidebar') { + if (drawerOpened + && (!this.drawerOpened || this.lastTipForSidebar !== this.currentTip) + && !this.slides[this.currentTip].movedForSidebar) { + this.slides[this.currentTip].tooltipLeft = (parseInt(this.slides[this.currentTip].tooltipLeft) + drawerWidth) + 'px' + this.slides[this.currentTip].movedForSidebar = true + } else if (!drawerOpened + && (this.drawerOpened || this.lastTipForSidebar !== this.currentTip) + && this.slides[this.currentTip].movedForSidebar) { + this.slides[this.currentTip].tooltipLeft = (parseInt(this.slides[this.currentTip].tooltipLeft) - drawerWidth) + 'px' + this.slides[this.currentTip].movedForSidebar = false + } + } else if (this.slides[this.currentTip]?.viewAttached === 'sidebarRegion') { + if (drawerExpanded + && (!this.drawerExpanded || this.lastTipForSidebar !== this.currentTip) + && !this.slides[this.currentTip].movedForSidebar) { + this.slides[this.currentTip].tooltipLeft = (parseInt(this.slides[this.currentTip].tooltipLeft) + drawerWidth) + 'px' + this.slides[this.currentTip].movedForSidebar = true + } else if (!drawerExpanded + && (this.drawerExpanded || this.lastTipForSidebar !== this.currentTip) + && this.slides[this.currentTip].movedForSidebar) { + this.slides[this.currentTip].tooltipLeft = (parseInt(this.slides[this.currentTip].tooltipLeft) - drawerWidth) + 'px' + this.slides[this.currentTip].movedForSidebar = false + } + } + } + + + this.drawerOpened = drawerOpened + this.drawerExpanded = drawerExpanded + this.lastTipForSidebar = this.currentTip + } + + ngOnDestroy(): void { + this.observers.forEach(o => { + o.disconnect() + }) + } + +} diff --git a/src/ui/quickTour/quickToutCmp/quickTour.style.css b/src/ui/quickTour/quickToutCmp/quickTour.style.css new file mode 100644 index 0000000000000000000000000000000000000000..d3813b0c5273313fa3b1e00cfd16aa90007f3343 --- /dev/null +++ b/src/ui/quickTour/quickToutCmp/quickTour.style.css @@ -0,0 +1,90 @@ +:host { + /*z-index: 9999;*/ + display: block; + width: 100%; + height: 100%; +} + +::ng-deep .cdk-global-overlay-wrapper { + z-index: 900; +} + +::ng-deep .mat-stroked-button[disabled] { + color: rgba(128, 128, 128, 0.41) !important; +} + +::ng-deep .mat-stroked-button:not([disabled]) { + border-color: #222529 !important; +} + +.stokeColor { + stroke-width: 3px; + stroke-linecap: round; + stroke-linejoin: round; + fill: rgba(0, 0, 0, 0); +} +:host-context([darktheme="true"]) .stokeColor { + stroke: rgb(255, 255, 255); +} +:host-context([darktheme="false"]) .stokeColor { + stroke: rgb(66,66,66); +} + +/*::ng-deep .mat-stroked-button:not([disabled]) {*/ +/* color: #1a1a1a;*/ +/*}*/ + +.tour-help { + /*background-color: #efefef;*/ + z-index: 901; +} + + +.tipCard { + border-radius: 10px; + max-width: 300px; + text-align: left; +} + +:host-context([darktheme="true"]) .tipCard { + background-color: #424242; + color: white; +} +:host-context([darktheme="false"]) .tipCard { + background-color: #FFFFFF; + border: 1px solid rgba(66, 66, 66, 0.26); + color: #424242; +} + +.cover { + background-color: rgba(0,0,0, 0.5); + width: 100vw; + height: 100vh; + z-index: 899; + /*display: block;*/ + + top: 0; + left: 0; +} + +.box { + box-sizing: content-box; + width: 0; + height: 0; + transform-origin: top left; + border: 10000px solid rgba(0, 0, 0, 0.5); +} + +.inner-box { + border: 1px white solid; +} + +.stepCircle { + width: 10px; + height: 10px; + border-radius: 5px; +} + +/*.cover {*/ +/* pointer-events: none; z-index: 900;*/ +/*}*/ diff --git a/src/ui/quickTour/quickToutCmp/quickTour.temlate.html b/src/ui/quickTour/quickToutCmp/quickTour.temlate.html new file mode 100644 index 0000000000000000000000000000000000000000..27cc13ef130fcfbeb0ef8a7474e6e757df7ee004 --- /dev/null +++ b/src/ui/quickTour/quickToutCmp/quickTour.temlate.html @@ -0,0 +1,137 @@ +<div class="tour-help position-fixed pt-3 pr-3 pl-3 pb-1 d-flex" + [ngStyle]="{ + top: slides[currentTip]?.tooltipTop || null, + bottom: slides[currentTip].tooltipBottom || null, + left: slides[currentTip]?.tooltipLeft || null, + right: slides[currentTip]?.tooltipRight || null}" + [ngClass]="[slides[currentTip]?.arrowPosition === 'right'? 'flex-row-reverse' : '', + slides[currentTip]?.arrowPosition === 'left'? 'flex-row' : '', + slides[currentTip]?.arrowPosition === 'top'? 'flex-column' : '', + slides[currentTip]?.arrowPosition === 'bottom'? 'flex-column-reverse' : '']"> + + + <div *ngIf="slides[currentTip]?.arrow"> + <ng-content *ngTemplateOutlet="arrow"></ng-content> + </div> + + <div class="d-flex align-items-center justify-content-center h-100 tipCard pt-3 pr-3 pl-3" + [ngStyle]="{margin: slides[currentTip]?.textMargin? slides[currentTip].textMargin : null, + maxWidth: slides[currentTip]?.textWidth? slides[currentTip].textWidth : null}"> + <div class="iv-custom-comp d-flex flex-column"> + <h6 class="mb-2"> + {{slides[currentTip].description}} + </h6> + + <div class="text-center"> + <button mat-button iav-stop="mousedown mouseup" + (click)="goBack()" + *ngIf="currentTip"> + <i class="fas fa-angle-left"></i> + <span class="ml-1">BACK</span> + </button> + + <button mat-button iav-stop="mousedown mouseup" + (click)="goForward()" + *ngIf="currentTip < slides.length - 1"> + <span class="mr-1">NEXT</span> + <i class="fas fa-angle-right"></i> + </button> + + <button iav-stop="mousedown mouseup" + (click)="destroy.emit();" + mat-button>CLOSE</button> + </div> + + <div class="d-flex align-self-end mb-1 mt-1"> + <div *ngFor="let stepCircle of numberOfSteps; let i = index" + class="border mr-1 stepCircle" + [ngStyle]="{background: slides[currentTip]?.step === i+1? 'currentColor' : ''}" + (click)="moveToTipByIndex(i)"> + {{stepCircle}} + </div> + </div> + + </div> + </div> +</div> + +<ng-template #arrow> + <ng-content *ngTemplateOutlet="slides[currentTip]?.arrow === 'arrow1'? arrow1 : + slides[currentTip]?.arrow === 'arrow2'? arrow2: + slides[currentTip]?.arrow === 'arrow3'? arrow3: + slides[currentTip]?.arrow === 'arrow5'? arrow5: + slides[currentTip]?.arrow === 'arrow6'? arrow6: + slides[currentTip]?.arrow === 'arrow4'? arrow4: null"></ng-content> +</ng-template> + +<ng-template #arrow1> + <svg [ngStyle]="{transform: slides[currentTip]?.arrowTransform? slides[currentTip]?.arrowTransform : null, + margin: slides[currentTip]?.arrowMargin? slides[currentTip]?.arrowMargin : null}" + height="80px" class="overflow-visible" viewBox="166.586 231.427 12.015 71.497" xmlns="http://www.w3.org/2000/svg"> + <path class="stokeColor" style="fill-opacity: 0; paint-order: stroke markers; stroke-linecap: round; stroke-linejoin: round; stroke-width: 3px;" d="M 183.239 326.14 C 176.831 309.209 176.634 285.376 182.647 254.643" transform="matrix(1, 0, 0, 1, -9.368863, -23.215925)"/> + <path class="stokeColor" d="M 187.97 263.39 C 187.12 262.245 184.536 259.536 182.665 254.732" transform="matrix(1, 0, 0, 1, -9.368863, -23.215925)"/> + <path class="stokeColor" d="M 182.791 254.976 C 181.626 254.227 174.925 262.146 176.09 262.895" transform="matrix(1, 0, 0, 1, -9.368863, -23.215925)"/> + </svg> +</ng-template> + +<ng-template #arrow2> + <svg [ngStyle]="{transform: slides[currentTip]?.arrowTransform? slides[currentTip]?.arrowTransform : null, + margin: slides[currentTip]?.arrowMargin? slides[currentTip]?.arrowMargin : null}" + width="80px" height="70px" class="overflow-visible" viewBox="150.239 144.229 67.46 40.886" xmlns="http://www.w3.org/2000/svg"> + <path class="stokeColor" d="M 296.081 265.092 Q 302.545 229.649 359.476 224.337" transform="matrix(1, 0, 0, 1, -141.776566, -80.108154)"/> + <path class="stokeColor" d="M 292.065 265.677 C 294.922 265.86 297.891 264.941 300.918 262.844 C 302.986 261.411 299.162 257.842 295.976 253.078" transform="matrix(0, 1, -1, 0, 415.938782, -116.389183)"/> + </svg> +</ng-template> + + + +<ng-template #arrow3> + <svg [ngStyle]="{transform: slides[currentTip]?.arrowTransform? slides[currentTip]?.arrowTransform : null, + margin: slides[currentTip]?.arrowMargin? slides[currentTip]?.arrowMargin : null}" + width="40px" class="overflow-visible" viewBox="210.782 56.841 29.636 288.223" xmlns="http://www.w3.org/2000/svg"> + <path class="stokeColor" d="M 212.078 57.419 C 231.858 81.463 223.38 117.762 225.382 146.924 C 226.221 159.143 228.267 171.776 232.453 183.328 C 233.961 187.49 240.011 194.737 240.418 198.726 C 240.445 198.997 234.593 204.524 233.912 205.886 C 231.231 211.249 230.106 218.152 229.665 224.115 C 227.666 251.12 229.249 278.318 227.395 305.339 C 226.51 318.233 217.11 333.266 217.11 345.064" style="stroke-linecap: round; stroke-linejoin: round; stroke-width: 3px; fill: rgba(0, 0, 0, 0);"/> + <path class="stokeColor" d="M 210.782 65.415 C 210.782 51.809 212.181 58.472 220.897 58.472" /> + <path class="stokeColor" d="M 214.504 338.782 C 214.906 351.198 220.239 339.913 224.34 339.913"/> + </svg> +</ng-template> + +<ng-template #arrow4 > + <svg [ngStyle]="{transform: slides[currentTip]?.arrowTransform? slides[currentTip]?.arrowTransform : null, + margin: slides[currentTip]?.arrowMargin? slides[currentTip]?.arrowMargin : null}" + height="38px" viewBox="299.543 321.915 170.933 30.964" xmlns="http://www.w3.org/2000/svg"> + <path class="stokeColor" d="M 301.52072039541815 323.60226246501526 C 311.5831169442529 340.51562343702426 341.60560254929175 334.7982673929286 359.2985534667969 337.2043762207031 C 367.2514321396593 338.2859081635777 375.2702876816191 342.35410524702206 382.34735107421875 345.8924865722656 C 385.22763076450417 347.33256521819686 387.1320707497497 354.70600700165824 389.4359130859375 352.4560852050781 C 390.0671934950275 351.839579670018 390.40266660252774 347.9536332932388 391.1954345703125 346.7441711425781 C 396.4823015920718 338.6784245203205 410.4743617782212 338.13712391197873 418.9132385253906 336.7287292480469 C 431.7553451427824 334.5854636244975 448.4256779742033 337.9491044314972 459.5848693847656 329.5787353515625 C 461.18996850294843 328.37477069724616 468.6846923828125 325.1523246569334 468.6846923828125 323.1907043457031" style="fill: rgb(0, 0, 0, 0);"/> + <path class="stokeColor" d="M 302.9312615546566 333.07007358944463 C 302.65366244614114 329.72018099572654 297.8531401351693 325.79953737428235 300.1758117675781 323.3697204589844 C 300.7803565677791 322.73728789250043 311.83416748046875 323.5789384146184 311.83416748046875 323.81036376953125" style="fill: rgba(0, 0, 0, 0);"/> + <path class="stokeColor" d="M 463.05231850248373 323.3282565340343 C 465.30665142189343 323.3282470703125 468.0848881713475 320.89690392424393 469.7531433105469 322.41314697265625 C 470.9482381993743 323.499344326286 470.57628053827574 331.8448791503906 469.25830078125 331.8448791503906" style="fill: rgba(0, 0, 0, 0);"/> + </svg> +</ng-template> + + +<ng-template #arrow5> + <svg [ngStyle]="{transform: slides[currentTip]?.arrowTransform? slides[currentTip]?.arrowTransform : null, + margin: slides[currentTip]?.arrowMargin? slides[currentTip]?.arrowMargin : null}" + height="100px" + viewBox="23.011 51.12 86.091 84.486" xmlns="http://www.w3.org/2000/svg"> + <path class="stokeColor" d="M 42.372 135.275 C 39.099 72.198 70.666 69.778 107.477 70.17"/> + <path class="stokeColor" d="M 28.277 125.699 L 41.622 125.699" transform="matrix(0.939693, -0.34202, 0.34202, 0.939693, -40.883873, 19.534008)"/> + <path class="stokeColor" d="M 33.304 121.099 L 25.073 128.035 L 33.062 134.606" transform="matrix(0.939693, -0.34202, 0.34202, 0.939693, -41.967846, 17.693502)"/> + <path class="stokeColor" d="M 92.404 63.192 L 105.749 63.192" transform="matrix(-0.34202, 0.939693, -0.939693, -0.34202, 192.343719, -8.296521)"/> + <path class="stokeColor" d="M 105.464 50.544 L 97.233 57.48 L 105.222 64.051" transform="matrix(-0.34202, 0.939693, -0.939693, -0.34202, 189.85376, -18.342039)"/> + <path class="stokeColor" d="M 42.968 77.934 L 56.313 77.934" transform="matrix(0.743145, 0.669131, -0.669131, 0.743145, 64.89846, -13.198224)"/> + <path class="stokeColor" d="M 49.142 66.866 L 40.911 73.802 L 48.9 80.373" transform="matrix(0.743145, 0.669131, -0.669131, 0.743145, 60.826363, -11.219056)"/> + </svg> + +</ng-template> + + + +<ng-template #arrow6> + + <svg [ngStyle]="{transform: slides[currentTip]?.arrowTransform? slides[currentTip]?.arrowTransform : null, + margin: slides[currentTip]?.arrowMargin? slides[currentTip]?.arrowMargin : null}" + height="50px" class="overflow-visible" viewBox="88.429 331.463 16.292 53.247" xmlns="http://www.w3.org/2000/svg"> + <path class="stokeColor" style="fill-rule: evenodd; fill: rgba(0, 0, 0, 0); stroke-width: 3px;" d="M 96.649 384.71 L 96.649 332.904"/> + <path class="stokeColor" style="fill-rule: evenodd; fill: rgba(0, 0, 0, 0); paint-order: fill; stroke-linejoin: round; stroke-linecap: round; stroke-width: 3px;" d="M 88.708 343.497 C 86.828 341.857 94.988 329.978 96.868 331.618 C 99.945 331.127 106.222 342.826 104.392 343.118"/> + </svg> +</ng-template> + +