UI: Improvement trip animation: fixed calculate start/endpoint; fixed update current position
This commit is contained in:
		
							parent
							
								
									a3206358c7
								
							
						
					
					
						commit
						5764287a12
					
				
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -178,7 +178,7 @@ export interface MapImage {
 | 
			
		||||
    update?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type TripAnimationSettings = {
 | 
			
		||||
export interface TripAnimationSettings extends PolygonSettings {
 | 
			
		||||
    showPoints: boolean;
 | 
			
		||||
    pointColor: string;
 | 
			
		||||
    pointSize: number;
 | 
			
		||||
@ -203,7 +203,7 @@ export type TripAnimationSettings = {
 | 
			
		||||
    labelFunction: GenericFunction;
 | 
			
		||||
    useColorPointFunction: boolean;
 | 
			
		||||
    colorPointFunction: GenericFunction;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type actionsHandler = ($event: Event, datasource: Datasource) => void;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -29,11 +29,17 @@ import {
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
import { FormattedData, MapProviders, TripAnimationSettings } from '@home/components/widget/lib/maps/map-models';
 | 
			
		||||
import { addCondition, addGroupInfo, addToSchema, initSchema } from '@app/core/schema-utils';
 | 
			
		||||
import { mapPolygonSchema, pathSchema, pointSchema, tripAnimationSchema } from '@home/components/widget/lib/maps/schemes';
 | 
			
		||||
import {
 | 
			
		||||
  mapPolygonSchema,
 | 
			
		||||
  pathSchema,
 | 
			
		||||
  pointSchema,
 | 
			
		||||
  tripAnimationSchema
 | 
			
		||||
} from '@home/components/widget/lib/maps/schemes';
 | 
			
		||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
 | 
			
		||||
import { WidgetContext } from '@app/modules/home/models/widget-component.models';
 | 
			
		||||
import {
 | 
			
		||||
  findAngle, getProviderSchema,
 | 
			
		||||
  findAngle,
 | 
			
		||||
  getProviderSchema,
 | 
			
		||||
  getRatio,
 | 
			
		||||
  interpolateOnLineSegment,
 | 
			
		||||
  parseArray,
 | 
			
		||||
@ -43,7 +49,7 @@ import {
 | 
			
		||||
} from '@home/components/widget/lib/maps/common-maps-utils';
 | 
			
		||||
import { JsonSettingsSchema, WidgetConfig } from '@shared/models/widget.models';
 | 
			
		||||
import moment from 'moment';
 | 
			
		||||
import { isUndefined } from '@core/utils';
 | 
			
		||||
import { isDefined, isUndefined } from '@core/utils';
 | 
			
		||||
import { ResizeObserver } from '@juggle/resize-observer';
 | 
			
		||||
import { MapWidgetInterface } from '@home/components/widget/lib/maps/map-widget.interface';
 | 
			
		||||
 | 
			
		||||
@ -117,12 +123,17 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
 | 
			
		||||
    this.normalizationStep = this.settings.normalizationStep;
 | 
			
		||||
    const subscription = this.ctx.defaultSubscription;
 | 
			
		||||
    subscription.callbacks.onDataUpdated = () => {
 | 
			
		||||
      this.historicalData = parseArray(this.ctx.data).filter(arr => arr.length);
 | 
			
		||||
      this.historicalData = parseArray(this.ctx.data).map(item => this.clearIncorrectFirsLastDatapoint(item)).filter(arr => arr.length);
 | 
			
		||||
      this.interpolatedTimeData.length = 0;
 | 
			
		||||
      this.formattedInterpolatedTimeData.length = 0;
 | 
			
		||||
      if (this.historicalData.length) {
 | 
			
		||||
        const prevMinTime = this.minTime;
 | 
			
		||||
        const prevMaxTime = this.maxTime;
 | 
			
		||||
        this.calculateIntervals();
 | 
			
		||||
        this.timeUpdated(this.minTime);
 | 
			
		||||
        const currentTime = this.calculateCurrentTime(prevMinTime, prevMaxTime);
 | 
			
		||||
        if (currentTime !== this.currentTime) {
 | 
			
		||||
          this.timeUpdated(currentTime);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      this.mapWidget.map.map?.invalidateSize();
 | 
			
		||||
      this.cd.detectChanges();
 | 
			
		||||
@ -214,9 +225,15 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  calculateIntervals() {
 | 
			
		||||
    let minTime = Infinity;
 | 
			
		||||
    let maxTime = -Infinity;
 | 
			
		||||
    this.historicalData.forEach((dataSource) => {
 | 
			
		||||
      minTime = Math.min(dataSource[0].time, minTime);
 | 
			
		||||
      maxTime = Math.max(dataSource[dataSource.length - 1].time, maxTime);
 | 
			
		||||
    });
 | 
			
		||||
    this.minTime = minTime;
 | 
			
		||||
    this.maxTime = maxTime;
 | 
			
		||||
    this.historicalData.forEach((dataSource, index) => {
 | 
			
		||||
      this.minTime = dataSource[0]?.time || Infinity;
 | 
			
		||||
      this.maxTime = dataSource[dataSource.length - 1]?.time || -Infinity;
 | 
			
		||||
      this.interpolatedTimeData[index] = this.interpolateArray(dataSource);
 | 
			
		||||
    });
 | 
			
		||||
    this.formattedInterpolatedTimeData = this.interpolatedTimeData.map(ds => _.values(ds));
 | 
			
		||||
@ -255,7 +272,7 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
 | 
			
		||||
    this.label = this.sanitizer.bypassSecurityTrustHtml(parseWithTranslation.parseTemplate(labelText, data, true));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  interpolateArray(originData: FormattedData[]): {[time: number]: FormattedData} {
 | 
			
		||||
  private interpolateArray(originData: FormattedData[]): {[time: number]: FormattedData} {
 | 
			
		||||
    const result: {[time: number]: FormattedData} = {};
 | 
			
		||||
    const latKeyName = this.settings.latKeyName;
 | 
			
		||||
    const lngKeyName = this.settings.lngKeyName;
 | 
			
		||||
@ -271,10 +288,57 @@ export class TripAnimationComponent implements OnInit, AfterViewInit, OnDestroy
 | 
			
		||||
    }
 | 
			
		||||
    const timeStamp = Object.keys(result);
 | 
			
		||||
    for (let i = 0; i < timeStamp.length - 1; i++) {
 | 
			
		||||
      if (isUndefined(result[timeStamp[i + 1]][latKeyName]) || isUndefined(result[timeStamp[i + 1]][lngKeyName])) {
 | 
			
		||||
        for (let j = i + 2; j < timeStamp.length - 1; j++) {
 | 
			
		||||
          if (isDefined(result[timeStamp[j]][latKeyName]) || isDefined(result[timeStamp[j]][lngKeyName])) {
 | 
			
		||||
            const ratio = getRatio(Number(timeStamp[i]), Number(timeStamp[j]), Number(timeStamp[i + 1]));
 | 
			
		||||
            result[timeStamp[i + 1]] = {
 | 
			
		||||
              ...interpolateOnLineSegment(result[timeStamp[i]], result[timeStamp[j]], latKeyName, lngKeyName, ratio),
 | 
			
		||||
              ...result[timeStamp[i + 1]],
 | 
			
		||||
            };
 | 
			
		||||
            break;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      result[timeStamp[i]].rotationAngle += findAngle(result[timeStamp[i]], result[timeStamp[i + 1]], latKeyName, lngKeyName);
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private calculateCurrentTime(minTime: number, maxTime: number): number {
 | 
			
		||||
    if (minTime !== this.minTime || maxTime !== this.maxTime) {
 | 
			
		||||
      if (this.minTime >= this.currentTime || isUndefined(this.currentTime)) {
 | 
			
		||||
        return this.minTime;
 | 
			
		||||
      } else if (this.maxTime <= this.currentTime) {
 | 
			
		||||
        return this.maxTime;
 | 
			
		||||
      } else {
 | 
			
		||||
        return this.minTime + Math.ceil((this.currentTime - this.minTime) / this.normalizationStep) * this.normalizationStep;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return this.currentTime;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private clearIncorrectFirsLastDatapoint(dataSource: FormattedData[]): FormattedData[] {
 | 
			
		||||
    const firstHistoricalDataIndexCoordinate = dataSource.findIndex(this.findFirstHistoricalDataIndexCoordinate);
 | 
			
		||||
    if (firstHistoricalDataIndexCoordinate === -1) {
 | 
			
		||||
      return [];
 | 
			
		||||
    }
 | 
			
		||||
    let lastIndex = dataSource.length - 1;
 | 
			
		||||
    for (lastIndex; lastIndex > 0; lastIndex--) {
 | 
			
		||||
      if (this.findFirstHistoricalDataIndexCoordinate(dataSource[lastIndex])) {
 | 
			
		||||
        lastIndex++;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (firstHistoricalDataIndexCoordinate > 0 || lastIndex < dataSource.length) {
 | 
			
		||||
      return dataSource.slice(firstHistoricalDataIndexCoordinate, lastIndex);
 | 
			
		||||
    }
 | 
			
		||||
    return dataSource;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private findFirstHistoricalDataIndexCoordinate = (item: FormattedData): boolean => {
 | 
			
		||||
    return isDefined(item[this.settings.latKeyName]) && isDefined(item[this.settings.lngKeyName]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export let TbTripAnimationWidget = TripAnimationComponent;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user