UI: Calculate correct interval length for echarts axis pointer.

This commit is contained in:
Igor Kulikov 2024-01-12 18:03:40 +02:00
parent d677f7c790
commit d2ba3d2d84
4 changed files with 70 additions and 25 deletions

View File

@ -19,7 +19,7 @@ import {
IndexedSubscriptionData, IndexedSubscriptionData,
} from '@app/shared/models/telemetry/telemetry.models'; } from '@app/shared/models/telemetry/telemetry.models';
import { import {
AggregationType, calculateAggInterval, AggregationType, calculateAggIntervalWithSubscriptionTimeWindow,
calculateIntervalComparisonEndTime, calculateIntervalComparisonEndTime,
calculateIntervalEndTime, calculateIntervalEndTime,
calculateIntervalStartEndTime, calculateIntervalStartEndTime,
@ -79,7 +79,7 @@ class AggDataMap {
} }
calculateAggInterval(timestamp: number): [number, number] { calculateAggInterval(timestamp: number): [number, number] {
return calculateAggInterval(this.subsTw, this.endTs, timestamp); return calculateAggIntervalWithSubscriptionTimeWindow(this.subsTw, this.endTs, timestamp);
} }
updateLastInterval(endTs: number) { updateLastInterval(endTs: number) {
@ -88,7 +88,7 @@ class AggDataMap {
const lastTs = this.map.maxKey(); const lastTs = this.map.maxKey();
if (lastTs) { if (lastTs) {
const data = this.map.get(lastTs); const data = this.map.get(lastTs);
const interval = calculateAggInterval(this.subsTw, endTs, data.ts); const interval = calculateAggIntervalWithSubscriptionTimeWindow(this.subsTw, endTs, data.ts);
data.interval = interval; data.interval = interval;
data.ts = interval[0] + Math.floor((interval[1] - interval[0]) / 2); data.ts = interval[0] + Math.floor((interval[1] - interval[0]) / 2);
} }

View File

@ -306,7 +306,7 @@ export class BarChartWithLabelsWidgetComponent implements OnInit, OnDestroy, Aft
if (this.barChart) { if (this.barChart) {
(this.barChartOptions.xAxis as any).min = this.ctx.defaultSubscription.timeWindow.minTime; (this.barChartOptions.xAxis as any).min = this.ctx.defaultSubscription.timeWindow.minTime;
(this.barChartOptions.xAxis as any).max = this.ctx.defaultSubscription.timeWindow.maxTime; (this.barChartOptions.xAxis as any).max = this.ctx.defaultSubscription.timeWindow.maxTime;
(this.barChartOptions.xAxis as any).tbTimewindowInterval = this.ctx.defaultSubscription.timeWindow.interval; (this.barChartOptions.xAxis as any).tbTimeWindow = this.ctx.defaultSubscription.timeWindow;
this.barChartOptions.series = this.updateSeries(); this.barChartOptions.series = this.updateSeries();
this.barChart.setOption(this.barChartOptions); this.barChart.setOption(this.barChartOptions);
} }
@ -417,7 +417,7 @@ export class BarChartWithLabelsWidgetComponent implements OnInit, OnDestroy, Aft
} }
}; };
(this.barChartOptions.xAxis as any).tbTimewindowInterval = this.ctx.defaultSubscription.timeWindow.interval; (this.barChartOptions.xAxis as any).tbTimeWindow = this.ctx.defaultSubscription.timeWindow;
this.barChartOptions.series = this.updateSeries(); this.barChartOptions.series = this.updateSeries();

View File

@ -37,7 +37,12 @@ import {
import { LabelLayout } from 'echarts/features'; import { LabelLayout } from 'echarts/features';
import { CanvasRenderer, SVGRenderer } from 'echarts/renderers'; import { CanvasRenderer, SVGRenderer } from 'echarts/renderers';
import { DataEntry, DataSet } from '@shared/models/widget.models'; import { DataEntry, DataSet } from '@shared/models/widget.models';
import { Interval, IntervalMath } from '@shared/models/time/time.models'; import {
calculateAggIntervalWithWidgetTimeWindow,
Interval,
IntervalMath,
WidgetTimewindow
} from '@shared/models/time/time.models';
import { CallbackDataParams } from 'echarts/types/dist/shared'; import { CallbackDataParams } from 'echarts/types/dist/shared';
import { Renderer2 } from '@angular/core'; import { Renderer2 } from '@angular/core';
import { DateFormatProcessor, DateFormatSettings, Font } from '@shared/models/widget-settings.models'; import { DateFormatProcessor, DateFormatSettings, Font } from '@shared/models/widget-settings.models';
@ -52,13 +57,43 @@ class EChartsModule {
Axis.prototype.getBandWidth = function(){ Axis.prototype.getBandWidth = function(){
const model: AxisModel = this.model; const model: AxisModel = this.model;
const axisOption = model.option; const axisOption = model.option;
const tbTimewindowInterval: Interval = (axisOption as any).tbTimewindowInterval; if (this.scale.type === 'time') {
if (this.scale.type === 'time' && (isNumber(tbTimewindowInterval) || isString(tbTimewindowInterval))) { let interval: number;
const seriesDataIndices = axisOption.axisPointer?.seriesDataIndices;
if (seriesDataIndices?.length) {
const seriesDataIndex = seriesDataIndices[0];
const series = model.ecModel.getSeriesByIndex(seriesDataIndex.seriesIndex);
if (series) {
const values = series.getData().getValues(seriesDataIndex.dataIndex);
const start = values[2];
const end = values[3];
if (typeof start === 'number' && typeof end === 'number') {
interval = Math.max(end - start, 1);
}
}
}
if (!interval) {
const tbTimeWindow: WidgetTimewindow = (axisOption as any).tbTimeWindow;
if (isDefinedAndNotNull(tbTimeWindow)) {
if (axisOption.axisPointer?.value && typeof axisOption.axisPointer?.value === 'number') {
const intervalArray = calculateAggIntervalWithWidgetTimeWindow(tbTimeWindow, axisOption.axisPointer.value);
const start = intervalArray[0];
const end = intervalArray[1];
interval = Math.max(end - start, 1);
} else {
interval = IntervalMath.numberValue(tbTimeWindow.interval);
}
}
}
if (interval) {
const timeScale: TimeScale = this.scale; const timeScale: TimeScale = this.scale;
const axisExtent: [number, number] = this._extent; const axisExtent: [number, number] = this._extent;
const dataExtent = timeScale.getExtent(); const dataExtent = timeScale.getExtent();
const size = Math.abs(axisExtent[1] - axisExtent[0]); const size = Math.abs(axisExtent[1] - axisExtent[0]);
return IntervalMath.numberValue(tbTimewindowInterval) * (size / (dataExtent[1] - dataExtent[0])); return interval * (size / (dataExtent[1] - dataExtent[0]));
} else {
return axisGetBandWidth.call(this);
}
} else { } else {
return axisGetBandWidth.call(this); return axisGetBandWidth.call(this);
} }

View File

@ -1115,25 +1115,35 @@ export const endIntervalDate = (current: moment_.Moment, interval: IntervalType)
} }
}; };
export const calculateAggInterval = (subsTw: SubscriptionTimewindow, endTs: number, timestamp: number): [number, number] => { export const calculateAggIntervalWithSubscriptionTimeWindow
= (subsTw: SubscriptionTimewindow, endTs: number, timestamp: number): [number, number] =>
calculateInterval(subsTw.startTs, endTs, subsTw.aggregation.interval, subsTw.tsOffset, subsTw.timezone, timestamp);
export const calculateAggIntervalWithWidgetTimeWindow
= (widgetTimeWindow: WidgetTimewindow, timestamp: number): [number, number] =>
calculateInterval(widgetTimeWindow.minTime - widgetTimeWindow.tsOffset,
widgetTimeWindow.maxTime, widgetTimeWindow.interval, widgetTimeWindow.tsOffset, widgetTimeWindow.timezone, timestamp);
export const calculateInterval = (startTime: number, endTime: number,
interval: Interval, tsOffset: number, timezone: string, timestamp: number): [number, number] => {
let startIntervalTs: number; let startIntervalTs: number;
let endIntervalTs: number; let endIntervalTs: number;
if (typeof subsTw.aggregation.interval === 'number') { if (typeof interval === 'number') {
const startTs = subsTw.startTs + subsTw.tsOffset; const startTs = startTime + tsOffset;
startIntervalTs = startTs + Math.floor((timestamp - startTs) / subsTw.aggregation.interval) * subsTw.aggregation.interval; startIntervalTs = startTs + Math.floor((timestamp - startTs) / interval) * interval;
endIntervalTs = startIntervalTs + subsTw.aggregation.interval; endIntervalTs = startIntervalTs + interval;
} else { } else {
const time = getTime(timestamp, subsTw.timezone); const time = getTime(timestamp, timezone);
let startInterval = startIntervalDate(time, subsTw.aggregation.interval); let startInterval = startIntervalDate(time, interval);
const start = getTime(subsTw.startTs, subsTw.timezone); const start = getTime(startTime, timezone);
if (start.isAfter(startInterval)) { if (start.isAfter(startInterval)) {
startInterval = start; startInterval = start;
} }
const endInterval = endIntervalDate(time, subsTw.aggregation.interval).add(1, 'milliseconds'); const endInterval = endIntervalDate(time, interval).add(1, 'milliseconds');
startIntervalTs = startInterval.valueOf() + subsTw.tsOffset; startIntervalTs = startInterval.valueOf() + tsOffset;
endIntervalTs = endInterval.valueOf() + subsTw.tsOffset; endIntervalTs = endInterval.valueOf() + tsOffset;
} }
endIntervalTs = Math.min(endIntervalTs, endTs); endIntervalTs = Math.min(endIntervalTs, endTime);
return [startIntervalTs, endIntervalTs]; return [startIntervalTs, endIntervalTs];
}; };