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,
} from '@app/shared/models/telemetry/telemetry.models';
import {
AggregationType, calculateAggInterval,
AggregationType, calculateAggIntervalWithSubscriptionTimeWindow,
calculateIntervalComparisonEndTime,
calculateIntervalEndTime,
calculateIntervalStartEndTime,
@ -79,7 +79,7 @@ class AggDataMap {
}
calculateAggInterval(timestamp: number): [number, number] {
return calculateAggInterval(this.subsTw, this.endTs, timestamp);
return calculateAggIntervalWithSubscriptionTimeWindow(this.subsTw, this.endTs, timestamp);
}
updateLastInterval(endTs: number) {
@ -88,7 +88,7 @@ class AggDataMap {
const lastTs = this.map.maxKey();
if (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.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) {
(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).tbTimewindowInterval = this.ctx.defaultSubscription.timeWindow.interval;
(this.barChartOptions.xAxis as any).tbTimeWindow = this.ctx.defaultSubscription.timeWindow;
this.barChartOptions.series = this.updateSeries();
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();

View File

@ -37,7 +37,12 @@ import {
import { LabelLayout } from 'echarts/features';
import { CanvasRenderer, SVGRenderer } from 'echarts/renderers';
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 { Renderer2 } from '@angular/core';
import { DateFormatProcessor, DateFormatSettings, Font } from '@shared/models/widget-settings.models';
@ -52,13 +57,43 @@ class EChartsModule {
Axis.prototype.getBandWidth = function(){
const model: AxisModel = this.model;
const axisOption = model.option;
const tbTimewindowInterval: Interval = (axisOption as any).tbTimewindowInterval;
if (this.scale.type === 'time' && (isNumber(tbTimewindowInterval) || isString(tbTimewindowInterval))) {
const timeScale: TimeScale = this.scale;
const axisExtent: [number, number] = this._extent;
const dataExtent = timeScale.getExtent();
const size = Math.abs(axisExtent[1] - axisExtent[0]);
return IntervalMath.numberValue(tbTimewindowInterval) * (size / (dataExtent[1] - dataExtent[0]));
if (this.scale.type === 'time') {
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 axisExtent: [number, number] = this._extent;
const dataExtent = timeScale.getExtent();
const size = Math.abs(axisExtent[1] - axisExtent[0]);
return interval * (size / (dataExtent[1] - dataExtent[0]));
} else {
return axisGetBandWidth.call(this);
}
} else {
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 endIntervalTs: number;
if (typeof subsTw.aggregation.interval === 'number') {
const startTs = subsTw.startTs + subsTw.tsOffset;
startIntervalTs = startTs + Math.floor((timestamp - startTs) / subsTw.aggregation.interval) * subsTw.aggregation.interval;
endIntervalTs = startIntervalTs + subsTw.aggregation.interval;
if (typeof interval === 'number') {
const startTs = startTime + tsOffset;
startIntervalTs = startTs + Math.floor((timestamp - startTs) / interval) * interval;
endIntervalTs = startIntervalTs + interval;
} else {
const time = getTime(timestamp, subsTw.timezone);
let startInterval = startIntervalDate(time, subsTw.aggregation.interval);
const start = getTime(subsTw.startTs, subsTw.timezone);
const time = getTime(timestamp, timezone);
let startInterval = startIntervalDate(time, interval);
const start = getTime(startTime, timezone);
if (start.isAfter(startInterval)) {
startInterval = start;
}
const endInterval = endIntervalDate(time, subsTw.aggregation.interval).add(1, 'milliseconds');
startIntervalTs = startInterval.valueOf() + subsTw.tsOffset;
endIntervalTs = endInterval.valueOf() + subsTw.tsOffset;
const endInterval = endIntervalDate(time, interval).add(1, 'milliseconds');
startIntervalTs = startInterval.valueOf() + tsOffset;
endIntervalTs = endInterval.valueOf() + tsOffset;
}
endIntervalTs = Math.min(endIntervalTs, endTs);
endIntervalTs = Math.min(endIntervalTs, endTime);
return [startIntervalTs, endIntervalTs];
};