Commit 5535c33d0eabd9e0b3c10e8094c584126e5f8b1d

Authored by Artem Halushko
1 parent b9db41bd

WIP on history control and route interpolation

@@ -1900,7 +1900,8 @@ @@ -1900,7 +1900,8 @@
1900 "@types/lodash": { 1900 "@types/lodash": {
1901 "version": "4.14.149", 1901 "version": "4.14.149",
1902 "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", 1902 "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz",
1903 - "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==" 1903 + "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==",
  1904 + "dev": true
1904 }, 1905 },
1905 "@types/minimatch": { 1906 "@types/minimatch": {
1906 "version": "3.0.3", 1907 "version": "3.0.3",
@@ -8263,6 +8264,14 @@ @@ -8263,6 +8264,14 @@
8263 "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.6.0.tgz", 8264 "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.6.0.tgz",
8264 "integrity": "sha512-CPkhyqWUKZKFJ6K8umN5/D2wrJ2+/8UIpXppY7QDnUZW5bZL5+SEI2J7GBpwh4LIupOKqbNSQXgqmrEJopHVNQ==" 8265 "integrity": "sha512-CPkhyqWUKZKFJ6K8umN5/D2wrJ2+/8UIpXppY7QDnUZW5bZL5+SEI2J7GBpwh4LIupOKqbNSQXgqmrEJopHVNQ=="
8265 }, 8266 },
  8267 + "leaflet-geometryutil": {
  8268 + "version": "0.9.3",
  8269 + "resolved": "https://registry.npmjs.org/leaflet-geometryutil/-/leaflet-geometryutil-0.9.3.tgz",
  8270 + "integrity": "sha512-Wi6YvfNx/Xu9q35AEfXpsUXmIFLen/MO+C2qimxHRnjyeyOxBhdcZa6kSiReaOX0cGK7yQInqrzz0dkIqZ8Dpg==",
  8271 + "requires": {
  8272 + "leaflet": "1.6.0"
  8273 + }
  8274 + },
8266 "leaflet-providers": { 8275 "leaflet-providers": {
8267 "version": "1.9.1", 8276 "version": "1.9.1",
8268 "resolved": "https://registry.npmjs.org/leaflet-providers/-/leaflet-providers-1.9.1.tgz", 8277 "resolved": "https://registry.npmjs.org/leaflet-providers/-/leaflet-providers-1.9.1.tgz",
@@ -57,6 +57,7 @@ @@ -57,6 +57,7 @@
57 "jstree": "^3.3.9", 57 "jstree": "^3.3.9",
58 "jstree-bootstrap-theme": "^1.0.1", 58 "jstree-bootstrap-theme": "^1.0.1",
59 "leaflet": "^1.6.0", 59 "leaflet": "^1.6.0",
  60 + "leaflet-geometryutil": "^0.9.3",
60 "leaflet-providers": "^1.9.1", 61 "leaflet-providers": "^1.9.1",
61 "leaflet.gridlayer.googlemutant": "^0.8.0", 62 "leaflet.gridlayer.googlemutant": "^0.8.0",
62 "leaflet.markercluster": "^1.4.1", 63 "leaflet.markercluster": "^1.4.1",
@@ -451,13 +451,13 @@ export function aspectCache(imageUrl: string): Observable<number> { @@ -451,13 +451,13 @@ export function aspectCache(imageUrl: string): Observable<number> {
451 451
452 export function parseArray(input: any[]): any[] { 452 export function parseArray(input: any[]): any[] {
453 let alliases: any = _(input).groupBy(el => el?.datasource?.aliasName).values().value(); 453 let alliases: any = _(input).groupBy(el => el?.datasource?.aliasName).values().value();
454 - console.log("alliases", alliases)  
455 return alliases.map((alliasArray, dsIndex) => 454 return alliases.map((alliasArray, dsIndex) =>
456 alliasArray[0].data.map((el, i) => { 455 alliasArray[0].data.map((el, i) => {
457 const obj = { 456 const obj = {
458 aliasName: alliasArray[0]?.datasource?.aliasName, 457 aliasName: alliasArray[0]?.datasource?.aliasName,
459 $datasource: alliasArray[0]?.datasource, 458 $datasource: alliasArray[0]?.datasource,
460 - dsIndex: dsIndex 459 + dsIndex: dsIndex,
  460 + time: el[0]
461 }; 461 };
462 alliasArray.forEach(el => { 462 alliasArray.forEach(el => {
463 obj[el?.dataKey?.label] = el?.data[i][1]; 463 obj[el?.dataKey?.label] = el?.data[i][1];
@@ -73,6 +73,10 @@ export class MapWidgetController implements MapWidgetInterface { @@ -73,6 +73,10 @@ export class MapWidgetController implements MapWidgetInterface {
73 this.map.updateMarkers(parseData(this.data)); 73 this.map.updateMarkers(parseData(this.data));
74 } 74 }
75 75
  76 + public updateHistoryData(dataSources){
  77 + dataSources.map()
  78 + }
  79 +
76 onDataUpdated() { 80 onDataUpdated() {
77 } 81 }
78 82
1 import L from 'leaflet'; 1 import L from 'leaflet';
  2 +import { interpolateOnPointSegment } from 'leaflet-geometryutil';
2 import _ from 'lodash'; 3 import _ from 'lodash';
3 4
4 export function createTooltip(target, settings, targetArgs?) { 5 export function createTooltip(target, settings, targetArgs?) {
5 - var popup = L.popup(); 6 + const popup = L.popup();
6 popup.setContent(''); 7 popup.setContent('');
7 target.bindPopup(popup, { autoClose: settings.autocloseTooltip, closeOnClick: false }); 8 target.bindPopup(popup, { autoClose: settings.autocloseTooltip, closeOnClick: false });
8 if (settings.displayTooltipAction == 'hover') { 9 if (settings.displayTooltipAction == 'hover') {
@@ -21,3 +22,27 @@ export function createTooltip(target, settings, targetArgs?) { @@ -21,3 +22,27 @@ export function createTooltip(target, settings, targetArgs?) {
21 dsIndex: settings.dsIndex 22 dsIndex: settings.dsIndex
22 }; 23 };
23 } 24 }
  25 +
  26 +
  27 +export function interpolateArray(originData, interpolatedIntervals) {
  28 +
  29 + const getRatio = (firsMoment, secondMoment, intermediateMoment) => {
  30 + return (intermediateMoment - firsMoment) / (secondMoment - firsMoment);
  31 + };
  32 +
  33 + const result = {};
  34 +
  35 + for (let i = 1, j = 0; i < originData.length, j < interpolatedIntervals.length;) {
  36 + const currentTime = interpolatedIntervals[j];
  37 + while (originData[i].time < currentTime) i++;
  38 + const before = originData[i - 1];
  39 + const after = originData[i];
  40 + result[currentTime] = (interpolateOnPointSegment(
  41 + new L.Point(before.latitude, before.longitude),
  42 + new L.Point(after.latitude, after.longitude),
  43 + getRatio(before.time, after.time, currentTime)));
  44 + j++;
  45 + }
  46 +
  47 + return result;
  48 +};
1 <div class="map" #map ></div> 1 <div class="map" #map ></div>
2 -<tb-history-selector [settings]="ctx.settings"></tb-history-selector>  
  2 +<div>{{historicalData?.lenth}}</div>
  3 +<tb-history-selector *ngIf="historicalData" [settings]="ctx.settings" [intervals]="intervals"
  4 + (onTimeUpdated)="timeUpdated($event)"></tb-history-selector>
1 -import { Component, OnInit, Input, ViewChild, AfterViewInit } from '@angular/core'; 1 +import { Component, OnInit, Input, ViewChild, AfterViewInit, ChangeDetectorRef } from '@angular/core';
2 import { MapWidgetController } from '../lib/maps/map-widget2'; 2 import { MapWidgetController } from '../lib/maps/map-widget2';
3 import { MapProviders } from '../lib/maps/map-models'; 3 import { MapProviders } from '../lib/maps/map-models';
4 import { parseArray } from '@app/core/utils'; 4 import { parseArray } from '@app/core/utils';
  5 +import { interpolateArray } from '../lib/maps/maps-utils';
5 6
6 @Component({ 7 @Component({
7 selector: 'trip-animation', 8 selector: 'trip-animation',
@@ -15,18 +16,50 @@ export class TripAnimationComponent implements OnInit, AfterViewInit { @@ -15,18 +16,50 @@ export class TripAnimationComponent implements OnInit, AfterViewInit {
15 @ViewChild('map') mapContainer; 16 @ViewChild('map') mapContainer;
16 17
17 mapWidget: MapWidgetController; 18 mapWidget: MapWidgetController;
18 - historicalData 19 + historicalData;
  20 + intervals;
  21 + normalizationStep = 500;
  22 + interpolatedData = [];
19 23
20 - constructor() { } 24 +
  25 + constructor(private cd: ChangeDetectorRef) { }
21 26
22 ngOnInit(): void { 27 ngOnInit(): void {
23 - console.log(this.ctx);  
24 - this.historicalData = parseArray(this.ctx.data);  
25 - console.log("TripAnimationComponent -> ngOnInit -> this.historicalData",this.ctx.data, this.historicalData) 28 + let subscription = this.ctx.subscriptions[Object.keys(this.ctx.subscriptions)[0]];
  29 + if (subscription) subscription.callbacks.onDataUpdated = (updated) => {
  30 + this.historicalData = parseArray(this.ctx.data);
  31 + this.historicalData.forEach(el => {
  32 + console.log("TripAnimationComponent -> if -> el", el)
  33 + el.longitude += (Math.random() - 0.5)
  34 + el.latitude += (Math.random() - 0.5)
  35 + });
  36 + this.calculateIntervals();
  37 + this.cd.detectChanges();
  38 + }
26 } 39 }
27 40
28 ngAfterViewInit() { 41 ngAfterViewInit() {
29 this.mapWidget = new MapWidgetController(MapProviders.openstreet, false, this.ctx, this.mapContainer.nativeElement); 42 this.mapWidget = new MapWidgetController(MapProviders.openstreet, false, this.ctx, this.mapContainer.nativeElement);
30 this.mapWidget.data 43 this.mapWidget.data
31 } 44 }
  45 +
  46 + timeUpdated(time) {
  47 + //this.mapWidget.ma
  48 + const currentPosition = this.interpolatedData.map(dataSource=>dataSource[time]);
  49 + console.log("TripAnimationComponent -> timeUpdated -> currentPosition", currentPosition)
  50 + }
  51 +
  52 + calculateIntervals() {
  53 + this.historicalData.forEach((dataSource, index) => {
  54 + this.intervals = [];
  55 + for (let time = dataSource[0]?.time; time < dataSource[dataSource.length - 1]?.time; time += this.normalizationStep) {
  56 + this.intervals.push(time);
  57 + }
  58 + this.intervals.push(dataSource[dataSource.length - 1]?.time);
  59 + this.interpolatedData[index] = interpolateArray(dataSource, this.intervals);
  60 + console.log("TripAnimationComponent -> calculateIntervals -> this.intervals", this.intervals)
  61 +
  62 + });
  63 + }
  64 +
32 } 65 }
@@ -6,34 +6,41 @@ @@ -6,34 +6,41 @@
6 <button mat-icon-button class="mat-icon-button" aria-label="Previous" ng-click="movePrev()"> 6 <button mat-icon-button class="mat-icon-button" aria-label="Previous" ng-click="movePrev()">
7 <mat-icon class="material-icons" ng-style="{'color': staticSettings.buttonColor}">skip_previous</mat-icon> 7 <mat-icon class="material-icons" ng-style="{'color': staticSettings.buttonColor}">skip_previous</mat-icon>
8 </button> 8 </button>
9 - <!-- <mat-slider ng-model="index" [min]="minTimeIndex" [max]="maxTimeIndex" (change)="recalculateTrips()">  
10 - </mat-slider>--> 9 + <mat-slider [(ngModel)]="index" [min]="minTimeIndex" [max]="maxTimeIndex" (change)="recalculateTrips()">
  10 + </mat-slider>
11 <button mat-icon-button class="mat-icon-button" aria-label="Next" ng-click="moveNext()"> 11 <button mat-icon-button class="mat-icon-button" aria-label="Next" ng-click="moveNext()">
12 <mat-icon class="material-icons" ng-style="{'color': staticSettings.buttonColor}">skip_next</mat-icon> 12 <mat-icon class="material-icons" ng-style="{'color': staticSettings.buttonColor}">skip_next</mat-icon>
13 </button> 13 </button>
14 <button mat-icon-button class="mat-icon-button" aria-label="End" ng-click="moveEnd()"> 14 <button mat-icon-button class="mat-icon-button" aria-label="End" ng-click="moveEnd()">
15 <mat-icon class="material-icons" ng-style="{'color': staticSettings.buttonColor}">fast_forward</mat-icon> 15 <mat-icon class="material-icons" ng-style="{'color': staticSettings.buttonColor}">fast_forward</mat-icon>
16 </button> 16 </button>
17 - <button mat-icon-button class="mat-icon-button" aria-label="Play" ng-click="playMove(true)"  
18 - ng-disabled="isPlaying">  
19 - <mat-icon class="material-icons"  
20 - ng-style="{'color': isPlaying ? staticSettings.disabledButtonColor : staticSettings.buttonColor}"> 17 + <!--<div class="play-pause">
  18 + <input type="checkbox" [(ngModel)]="play" value="" id="playPauseCheckbox" name="playPauseCheckbox" />
  19 + <label for="playPauseCheckbox"></label>
  20 + </div>-->
  21 + <button mat-icon-button class="mat-icon-button" aria-label="Play" >
  22 + <mat-icon (click)="play()" *ngIf="!playing" class="material-icons" ng-style="{'color': settings.buttonColor}">
21 play_circle_outline 23 play_circle_outline
22 </mat-icon> 24 </mat-icon>
  25 + <mat-icon (click)="pause()" *ngIf="playing" class="material-icons" ng-style="{'color': settings.buttonColor}">
  26 + pause_circle_outline
  27 + </mat-icon>
23 </button> 28 </button>
24 - <!-- <mat-select ng-model="speed" aria-label="Speed selector"> 29 + <!-- <mat-select [(ngModel)]="speed" aria-label="Speed selector">
25 <mat-option ng-value="speed" flex="1" ng-repeat="speed in speeds track by $index">{{ speed}} 30 <mat-option ng-value="speed" flex="1" ng-repeat="speed in speeds track by $index">{{ speed}}
26 </mat-option> 31 </mat-option>
27 </mat-select>--> 32 </mat-select>-->
28 - <button mat-icon-button class="mat-icon-button" aria-label="Stop playing" ng-click="stopPlay()" 33 + <!-- <button mat-icon-button class="mat-icon-button" aria-label="Stop playing" ng-click="stopPlay()"
29 ng-disabled="!isPlaying"> 34 ng-disabled="!isPlaying">
30 <mat-icon class="material-icons" 35 <mat-icon class="material-icons"
31 ng-style="{'color': isPlaying ? staticSettings.buttonColor : staticSettings.disabledButtonColor}"> 36 ng-style="{'color': isPlaying ? staticSettings.buttonColor : staticSettings.disabledButtonColor}">
32 pause_circle_outline 37 pause_circle_outline
33 </mat-icon> 38 </mat-icon>
34 - </button> 39 + </button>-->
35 </div> 40 </div>
36 <div class="panel-timer"> 41 <div class="panel-timer">
37 <span *ngIf="animationTime">{{ animationTime | date:'medium'}}</span> 42 <span *ngIf="animationTime">{{ animationTime | date:'medium'}}</span>
38 <span *ngIf="!animationTime">{{ "widget.no-data-found" | translate}}</span> 43 <span *ngIf="!animationTime">{{ "widget.no-data-found" | translate}}</span>
39 - </div>  
  44 + </div>
  45 +
  46 + <div>{{index}}</div>
@@ -13,125 +13,152 @@ @@ -13,125 +13,152 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 - .trip-animation-widget { 16 +.trip-animation-widget {
  17 + position: relative;
  18 + width: 100%;
  19 + height: 100%;
  20 + font-size: 16px;
  21 + line-height: 24px;
17 22
  23 + .trip-animation-label-container {
  24 + height: 24px;
  25 + }
  26 +
  27 + .trip-animation-container {
18 position: relative; 28 position: relative;
  29 + z-index: 1;
  30 + flex: 1;
19 width: 100%; 31 width: 100%;
20 - height: 100%;  
21 - font-size: 16px;  
22 - line-height: 24px;  
23 -  
24 - .trip-animation-label-container {  
25 - height: 24px;  
26 - }  
27 -  
28 - .trip-animation-container {  
29 - position: relative; 32 +
  33 + #trip-animation-map {
30 z-index: 1; 34 z-index: 1;
31 - flex: 1;  
32 width: 100%; 35 width: 100%;
33 -  
34 - #trip-animation-map {  
35 - z-index: 1;  
36 - width: 100%;  
37 - height: 100%;  
38 -  
39 - .pointsLayerMarkerIcon {  
40 - border-radius: 50%;  
41 - } 36 + height: 100%;
  37 +
  38 + .pointsLayerMarkerIcon {
  39 + border-radius: 50%;
42 } 40 }
43 -  
44 - .trip-animation-info-panel {  
45 - position: absolute; 41 + }
  42 +
  43 + .trip-animation-info-panel {
  44 + position: absolute;
  45 + top: 0;
  46 + right: 0;
  47 + z-index: 2;
  48 + pointer-events: none;
  49 +
  50 + .md-button {
46 top: 0; 51 top: 0;
47 - right: 0;  
48 - z-index: 2;  
49 - pointer-events: none;  
50 -  
51 - .md-button {  
52 - top: 0;  
53 - left: 0;  
54 - width: 32px;  
55 - min-width: 32px;  
56 - height: 32px;  
57 - min-height: 32px;  
58 - padding: 0 0 2px;  
59 - margin: 2px;  
60 - line-height: 24px;  
61 -  
62 - ng-md-icon {  
63 - width: 24px;  
64 - height: 24px;  
65 -  
66 - svg {  
67 - width: inherit;  
68 - height: inherit;  
69 - } 52 + left: 0;
  53 + width: 32px;
  54 + min-width: 32px;
  55 + height: 32px;
  56 + min-height: 32px;
  57 + padding: 0 0 2px;
  58 + margin: 2px;
  59 + line-height: 24px;
  60 +
  61 + ng-md-icon {
  62 + width: 24px;
  63 + height: 24px;
  64 +
  65 + svg {
  66 + width: inherit;
  67 + height: inherit;
70 } 68 }
71 } 69 }
72 } 70 }
73 -  
74 - .trip-animation-tooltip {  
75 - position: absolute;  
76 - top: 38px;  
77 - right: 0;  
78 - z-index: 2;  
79 - padding: 10px;  
80 - background-color: #fff;  
81 - transition: .3s ease-in-out;  
82 -  
83 - &-hidden {  
84 - transform: translateX(110%);  
85 - } 71 + }
  72 +
  73 + .trip-animation-tooltip {
  74 + position: absolute;
  75 + top: 38px;
  76 + right: 0;
  77 + z-index: 2;
  78 + padding: 10px;
  79 + background-color: #fff;
  80 + transition: 0.3s ease-in-out;
  81 +
  82 + &-hidden {
  83 + transform: translateX(110%);
86 } 84 }
87 } 85 }
88 -  
89 - .trip-animation-control-panel {  
90 - position: relative;  
91 - box-sizing: border-box;  
92 - width: 100%;  
93 - padding-bottom: 16px;  
94 - padding-left: 10px;  
95 -  
96 - md-slider-container {  
97 - md-slider {  
98 - min-width: 80px;  
99 - }  
100 -  
101 - button.md-button.md-icon-button {  
102 - width: 44px;  
103 - min-width: 44px;  
104 - height: 44px;  
105 - min-height: 44px;  
106 - margin: 0;  
107 - line-height: 28px;  
108 -  
109 - md-icon {  
110 - width: 28px;  
111 - height: 28px;  
112 - font-size: 28px;  
113 -  
114 - svg {  
115 - width: inherit;  
116 - height: inherit;  
117 - } 86 + }
  87 +
  88 + .trip-animation-control-panel {
  89 + position: relative;
  90 + box-sizing: border-box;
  91 + width: 100%;
  92 + padding-bottom: 16px;
  93 + padding-left: 10px;
  94 +
  95 + md-slider-container {
  96 + md-slider {
  97 + min-width: 80px;
  98 + }
  99 +
  100 + button.md-button.md-icon-button {
  101 + width: 44px;
  102 + min-width: 44px;
  103 + height: 44px;
  104 + min-height: 44px;
  105 + margin: 0;
  106 + line-height: 28px;
  107 +
  108 + md-icon {
  109 + width: 28px;
  110 + height: 28px;
  111 + font-size: 28px;
  112 +
  113 + svg {
  114 + width: inherit;
  115 + height: inherit;
118 } 116 }
119 } 117 }
120 -  
121 - md-select {  
122 - margin: 0;  
123 - }  
124 } 118 }
125 -  
126 - .panel-timer {  
127 - max-width: none;  
128 - padding-right: 250px;  
129 - padding-left: 90px;  
130 - margin-top: -20px;  
131 - font-size: 12px;  
132 - font-weight: 500;  
133 - text-align: center; 119 +
  120 + md-select {
  121 + margin: 0;
134 } 122 }
135 } 123 }
  124 +
  125 + .panel-timer {
  126 + max-width: none;
  127 + padding-right: 250px;
  128 + padding-left: 90px;
  129 + margin-top: -20px;
  130 + font-size: 12px;
  131 + font-weight: 500;
  132 + text-align: center;
  133 + }
  134 + }
  135 +}
  136 +
  137 +.playpause {
  138 + label {
  139 + display: block;
  140 + box-sizing: border-box;
  141 +
  142 + width: 0;
  143 + height: 74px;
  144 +
  145 + cursor: pointer;
  146 +
  147 + border-color: transparent transparent transparent #202020;
  148 + transition: 100ms all ease;
  149 + will-change: border-width;
  150 +
  151 + // paused state
  152 + border-style: double;
  153 + border-width: 0px 0 0px 60px;
  154 + }
  155 + input[type="checkbox"] {
  156 + visibility: hidden;
  157 +
  158 + &:checked + label {
  159 + // play state
  160 + border-style: solid;
  161 + border-width: 37px 0 37px 60px;
  162 + }
136 } 163 }
137 -  
  164 +}
1 -import { Component, OnInit, Input } from '@angular/core'; 1 +import { Component, OnInit, OnChanges, Input, Output, EventEmitter, ChangeDetectorRef } from '@angular/core';
  2 +import { interval } from 'rxjs';
  3 +import { filter, tap } from 'rxjs/operators';
2 4
3 @Component({ 5 @Component({
4 selector: 'tb-history-selector', 6 selector: 'tb-history-selector',
5 templateUrl: './history-selector.component.html', 7 templateUrl: './history-selector.component.html',
6 styleUrls: ['./history-selector.component.scss'] 8 styleUrls: ['./history-selector.component.scss']
7 }) 9 })
8 -export class HistorySelectorComponent implements OnInit { 10 +export class HistorySelectorComponent implements OnInit, OnChanges {
9 11
10 @Input() settings 12 @Input() settings
  13 + @Input() intervals = [];
11 14
12 - animationTime 15 + @Output() onTimeUpdated = new EventEmitter();
13 16
  17 + animationTime;
  18 + minTimeIndex = 0;
  19 + maxTimeIndex = 0;
  20 + speed = 1;
  21 + index = 0;
  22 + playing = false;
  23 + interval;
14 24
15 - constructor() { } 25 +
  26 + constructor(private cd: ChangeDetectorRef) { }
16 27
17 ngOnInit(): void { 28 ngOnInit(): void {
18 - console.log(this.settings);  
19 - 29 + }
  30 +
  31 + ngOnChanges() {
  32 + this.maxTimeIndex = this.intervals?.length - 1;
  33 + }
  34 +
  35 + play() {
  36 + this.playing = true;
  37 + this.interval = interval(1000 / this.speed)
  38 + .pipe(
  39 + filter(() => this.playing),
  40 + tap(() => this.index++)).subscribe(() => {
  41 + if (this.index < this.maxTimeIndex) {
  42 + this.cd.detectChanges();
  43 + this.onTimeUpdated.emit(this.intervals[this.index]);
  44 + }
  45 + else {
  46 + this.interval.complete();
  47 + }
  48 + }, err => {
  49 + console.log(err);
  50 + }, () => {
  51 + this.index = this.minTimeIndex;
  52 + this.playing = false;
  53 + })
  54 + }
  55 +
  56 + pause() {
  57 + this.playing = false;
  58 + }
  59 + /*
  60 + setSpeed() {
  61 + if (this.interval) this.interval.unsubscribe();
  62 + this.interval = interval(1000 / this.speed)
  63 + .pipe(
  64 + takeWhile(() => this.index < this.maxTimeIndex),
  65 + filter(() => this.play),
  66 + tap(() => this.index++))
  67 + .subscribe(() => {
  68 + console.log(this.intervals);
  69 +
  70 + this.onTimeUpdated.emit(this.intervals[this.index]);
  71 +
  72 + }, err => {
  73 + console.log(err);
  74 + }, () => {
  75 + this.index = this.minTimeIndex;
  76 + this.play = false;
  77 + })
  78 + }*/
  79 +
  80 +
  81 +
  82 +
  83 + /*
  84 +
  85 + playMove(play) {
  86 + if (play && this.isPlaying) return;
  87 + if (play || this.isPlaying) this.isPlaying = true;
  88 + if (this.isPlaying) {
  89 + moveInc(1);
  90 + this.timeout = $timeout(function () {
  91 + this.playMove();
  92 + }, 1000 / this.speed)
  93 + }
  94 + };
  95 +
  96 + moveNext() {
  97 + this.stopPlay();
  98 + if (this.staticSettings.usePointAsAnchor) {
  99 + let newIndex = this.maxTimeIndex;
  100 + for (let index = this.index + 1; index < this.maxTimeIndex; index++) {
  101 + if (this.trips.some(function (trip) {
  102 + return calculateCurrentDate(trip.timeRange, index).hasAnchor;
  103 + })) {
  104 + newIndex = index;
  105 + break;
  106 + }
  107 + }
  108 + this.moveToIndex(newIndex);
  109 + } else moveInc(1);
  110 + };
  111 +
  112 + movePrev() {
  113 + this.stopPlay();
  114 + if (this.staticSettings.usePointAsAnchor) {
  115 + let newIndex = this.minTimeIndex;
  116 + for (let index = this.index - 1; index > this.minTimeIndex; index--) {
  117 + if (this.trips.some(function (trip) {
  118 + return calculateCurrentDate(trip.timeRange, index).hasAnchor;
  119 + })) {
  120 + newIndex = index;
  121 + break;
  122 + }
  123 + }
  124 + this.moveToIndex(newIndex);
  125 + } else moveInc(-1);
  126 + };
  127 +
  128 + moveStart = function () {
  129 + this.stopPlay();
  130 + this.moveToIndex(this.minTimeIndex);
  131 + };
  132 +
  133 + moveEnd = function () {
  134 + this.stopPlay();
  135 + this.moveToIndex(this.maxTimeIndex);
  136 + };
  137 +
  138 + stopPlay = function () {
  139 + if (this.isPlaying) {
  140 + this.isPlaying = false;
  141 + $timeout.cancel(this.timeout);
  142 + }
  143 + };
  144 +
  145 + moveInc(inc) {
  146 + let newIndex = this.index + inc;
  147 + this.moveToIndex(newIndex);
  148 + }
  149 +
  150 + moveToIndex(newIndex) {
  151 + if (newIndex > this.maxTimeIndex || newIndex < this.minTimeIndex) return;
  152 + this.index = newIndex;
  153 + this.animationTime = this.minTime + this.index * this.staticSettings.normalizationStep;
  154 + recalculateTrips();
  155 + }
  156 + */
  157 + recalculateTrips() {
  158 +
20 } 159 }
21 160
22 } 161 }