diff --git a/application/frontend/src/app/core/containers/app/app.component.ts b/application/frontend/src/app/core/containers/app/app.component.ts index 2f85da7b..a588f1b1 100644 --- a/application/frontend/src/app/core/containers/app/app.component.ts +++ b/application/frontend/src/app/core/containers/app/app.component.ts @@ -79,7 +79,9 @@ export class AppComponent { 'navigate_before', 'navigate_next', 'open_in_new', + 'pause', 'pdf', + 'play', 'pickup', 'route', 'satellite', diff --git a/application/frontend/src/app/core/containers/travel-simulator/travel-simulator.component.html b/application/frontend/src/app/core/containers/travel-simulator/travel-simulator.component.html index 7d5015c7..1feef6af 100644 --- a/application/frontend/src/app/core/containers/travel-simulator/travel-simulator.component.html +++ b/application/frontend/src/app/core/containers/travel-simulator/travel-simulator.component.html @@ -1,30 +1,31 @@ -
+
Activate travel simulatorTravel simulator -
{{ formatSecondsDate(timeDisplayed$ | async) }}
- - - - Speed - - Slow - Normal - Fast - - +
+ + + +
+
Speed:
+ + 0.5x + 1x + 3x + 5x + +
+
diff --git a/application/frontend/src/app/core/containers/travel-simulator/travel-simulator.component.scss b/application/frontend/src/app/core/containers/travel-simulator/travel-simulator.component.scss index 9ce9699f..55bf1c5b 100644 --- a/application/frontend/src/app/core/containers/travel-simulator/travel-simulator.component.scss +++ b/application/frontend/src/app/core/containers/travel-simulator/travel-simulator.component.scss @@ -1,17 +1,42 @@ +@import '../../../../styles/variables.scss'; + :host { position: absolute; - top: 10px; - left: 0; - right: 0; - display: flex; - justify-content: center; + bottom: 10px; + left: 10px; + padding: 10px; +} + +.simulator-toggle { + font-size: 16px; + line-height: 24px; +} + +.simulator-contents { + margin-left: 20px; + gap: 20px; } -.container { - width: 50%; +.divider { + height: 24px; } -.time-value { - text-align: center; - padding-top: 8px; +.play-button { + box-shadow: none; + height: 24px; + width: 24px; + + .mat-button-wrapper { + position: relative; + top: -4px; + } +} + +.speed-container { + gap: 10px; + + mat-radio-group { + display: flex; + gap: 10px; + } } diff --git a/application/frontend/src/app/core/containers/travel-simulator/travel-simulator.component.ts b/application/frontend/src/app/core/containers/travel-simulator/travel-simulator.component.ts index c991ba7f..6f6c0cef 100644 --- a/application/frontend/src/app/core/containers/travel-simulator/travel-simulator.component.ts +++ b/application/frontend/src/app/core/containers/travel-simulator/travel-simulator.component.ts @@ -7,13 +7,13 @@ * https://opensource.org/licenses/MIT. */ -import { ChangeDetectionStrategy, Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { ChangeDetectionStrategy, Component, HostBinding, OnDestroy, OnInit } from '@angular/core'; import { Store, select } from '@ngrx/store'; import Long from 'long'; import { Observable, Subject, Subscription, asyncScheduler, combineLatest, interval } from 'rxjs'; import ShipmentModelSelectors from '../../selectors/shipment-model.selectors'; import { map, throttleTime } from 'rxjs/operators'; -import { MatSlider, MatSliderChange } from '@angular/material/slider'; +import { MatSliderChange } from '@angular/material/slider'; import { setActive, setTime } from '../../actions/travel-simulator.actions'; import TravelSimulatorSelectors from '../../selectors/travel-simulator.selectors'; import { MatSlideToggleChange } from '@angular/material/slide-toggle'; @@ -27,17 +27,18 @@ import { formatSecondsDate } from 'src/app/util/time-translation'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class TravelSimulatorComponent implements OnInit, OnDestroy { - @ViewChild(MatSlider) timeSlider: MatSlider; + @HostBinding('class.app-map-panel') readonly mapPanel = true; active$: Observable; - start$: Observable; - end$: Observable; - time$: Observable; timeDisplayed$: Observable; timezoneOffset: number; valueChanged = new Subject(); animationTimer$: Subscription; - animationSpeedMultiple = 3; + animationSpeedMultiple = 1; + end$: Subscription; + end: number; + time$: Subscription; + time: number; formatSecondsDate = formatSecondsDate; @@ -49,20 +50,19 @@ export class TravelSimulatorComponent implements OnInit, OnDestroy { .pipe(map((value) => (this.timezoneOffset = value))) .subscribe(); - this.start$ = this.store - .select(ShipmentModelSelectors.selectGlobalStartTime) - .pipe(map((value) => Long.fromValue(value).toNumber())); - this.end$ = this.store .select(ShipmentModelSelectors.selectGlobalEndTime) - .pipe(map((value) => Long.fromValue(value).toNumber())); + .pipe(map((value) => Long.fromValue(value).toNumber())) + .subscribe((end) => (this.end = end)); this.timeDisplayed$ = combineLatest([ this.store.select(TravelSimulatorSelectors.selectTime), this.store.select(selectTimezoneOffset), ]).pipe(map(([value, tzOffset]) => value + tzOffset)); - this.time$ = this.store.select(TravelSimulatorSelectors.selectTime); + this.time$ = this.store + .select(TravelSimulatorSelectors.selectTime) + .subscribe((time) => (this.time = time)); this.active$ = this.store.pipe(select(TravelSimulatorSelectors.selectActive)); @@ -76,13 +76,14 @@ export class TravelSimulatorComponent implements OnInit, OnDestroy { ngOnDestroy(): void { this.onEndAnimate(); + this.time$.unsubscribe(); + this.end$.unsubscribe(); } onBeginAnimate(): void { - this.timeSlider.disabled = true; - this.animationTimer$ = interval(100).subscribe((_value) => { - const newTime = this.timeSlider.value + 60 * this.animationSpeedMultiple; - if (newTime > this.timeSlider.max) { + this.animationTimer$ = interval(33).subscribe((_value) => { + const newTime = this.time + 60 * this.animationSpeedMultiple; + if (newTime > this.end) { this.onEndAnimate(); return; } @@ -92,7 +93,6 @@ export class TravelSimulatorComponent implements OnInit, OnDestroy { onEndAnimate(): void { this.animationTimer$?.unsubscribe(); - this.timeSlider.disabled = false; } onToggleActive(event: MatSlideToggleChange): void { diff --git a/application/frontend/src/assets/images/pause.svg b/application/frontend/src/assets/images/pause.svg new file mode 100644 index 00000000..d477130b --- /dev/null +++ b/application/frontend/src/assets/images/pause.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/application/frontend/src/assets/images/play.svg b/application/frontend/src/assets/images/play.svg new file mode 100644 index 00000000..5a9aa6ad --- /dev/null +++ b/application/frontend/src/assets/images/play.svg @@ -0,0 +1,41 @@ + + + + + + diff --git a/application/frontend/src/styles/main.scss b/application/frontend/src/styles/main.scss index 4b69435a..2cb58e0c 100644 --- a/application/frontend/src/styles/main.scss +++ b/application/frontend/src/styles/main.scss @@ -985,3 +985,12 @@ app-post-solve-map-legend .legend-panel mat-checkbox label .mat-checkbox-label { font-size: 16px; line-height: 24px; } + +.play-button .mat-button-wrapper { + position: relative; + top: -8px; + + mat-icon svg { + height: 22px; + } +}