Skip to content

Commit 75d7618

Browse files
committed
#327 Fix: Change of the visible line do not remove the zoom
1 parent da5b631 commit 75d7618

File tree

2 files changed

+75
-62
lines changed

2 files changed

+75
-62
lines changed

frontend/src/app/modules/time-series/components/time-series-line-chart/time-series-line-chart.component.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ export class TimeSeriesLineChartComponent implements AfterContentInit, OnChanges
6767

6868
this.spinnerService.hideSpinner("time-series-line-chart-spinner");
6969

70-
this.lineChartService.setLegendData(this.timeSeriesResults);
7170
this.lineChartService.drawLineChart(this.timeSeriesResults);
7271
}
7372

frontend/src/app/modules/time-series/services/line-chart.service.ts

Lines changed: 75 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -315,13 +315,33 @@ export class LineChartService {
315315
this._legendGroupHeight = Math.ceil(labels.length / this._legendGroupColumns) * ChartCommons.LABEL_HEIGHT + 30;
316316
};
317317

318-
return (incomingData: EventResultDataDTO) => {
318+
/**
319+
* Set the data for the legend after the incoming data is received
320+
*/
321+
const setLegendData = (incomingData: EventResultDataDTO) => {
319322
if (incomingData.series.length == 0) {
320323
return;
321324
}
322325

326+
const labelDataMap = {};
327+
incomingData.series.forEach((data: EventResultSeriesDTO) => {
328+
if (incomingData.summaryLabels.length > 0 && incomingData.summaryLabels[0].key != "measurand") {
329+
data.identifier = this.translateMeasurand(data);
330+
}
331+
const key = this.generateKey(data);
332+
labelDataMap[key] = {
333+
text: data.identifier,
334+
key: key,
335+
show: true
336+
}
337+
});
338+
this.legendDataMap = labelDataMap;
339+
};
340+
341+
return (incomingData: EventResultDataDTO) => {
323342
prepareCleanState();
324343

344+
setLegendData(incomingData);
325345
const data: TimeSeries[] = prepareData(incomingData);
326346
const chart: D3Selection<D3BaseType, {}, D3ContainerElement, {}> = d3Select('g#time-series-chart-drawing-area');
327347
const xScale: D3ScaleTime<number, number> = this.lineChartScaleService.getXScale(data, this._width);
@@ -334,7 +354,7 @@ export class LineChartService {
334354
createContextMenu();
335355
this.addBrush(chart, xScale, yScale, data);
336356

337-
this.addLegendsToChart(chart, incomingData);
357+
this.addLegendsToChart(chart, xScale, yScale, data)();
338358
this.setSummaryLabel(chart, incomingData.summaryLabels);
339359
this.addDataLinesToChart(chart, xScale, yScale, data);
340360

@@ -348,29 +368,6 @@ export class LineChartService {
348368
}
349369
})();
350370

351-
/**
352-
* Set the data for the legend after the incoming data is received
353-
*/
354-
public setLegendData(incomingData: EventResultDataDTO) {
355-
if (incomingData.series.length == 0) {
356-
return;
357-
}
358-
359-
const labelDataMap = {};
360-
incomingData.series.forEach((data: EventResultSeriesDTO) => {
361-
if (incomingData.summaryLabels.length > 0 && incomingData.summaryLabels[0].key != "measurand") {
362-
data.identifier = this.translateMeasurand(data);
363-
}
364-
const key = this.generateKey(data);
365-
labelDataMap[key] = {
366-
text: data.identifier,
367-
key: key,
368-
show: true
369-
}
370-
});
371-
this.legendDataMap = labelDataMap;
372-
}
373-
374371
private translateMeasurand(data: EventResultSeriesDTO): string {
375372
const splitLabelList: string[] = data.identifier.split(' | ');
376373
const splitLabel: string = this.translationService.instant('frontend.de.iteratec.isr.measurand.' + splitLabelList[0]);
@@ -769,8 +766,8 @@ export class LineChartService {
769766
.transition()
770767
.duration(500)
771768
.style('opacity', (timeSeries: TimeSeries) => {
772-
return (this.legendDataMap[timeSeries.key].show) ? '1' : '0.1';
773-
});
769+
return (this.legendDataMap[timeSeries.key].show) ? '1' : '0.1';
770+
});
774771
};
775772

776773
const addDataPointsToChart = (timeSeries: TimeSeries[], xScale: D3ScaleTime<number, number>, yScale: D3ScaleLinear<number, number>): void => {
@@ -860,18 +857,22 @@ export class LineChartService {
860857
})
861858
}
862859

860+
private hideMarker() {
861+
d3Select('.marker-line').style('opacity', 0);
862+
d3Select('#marker-tooltip').style('opacity', 0);
863+
this.hideOldDotsOnMarker();
864+
};
865+
863866
private prepareMouseEventCatcher = (() => {
864867
const showMarker = () => {
868+
if(this._dotsOnMarker && this._dotsOnMarker.empty()) {
869+
return;
870+
}
871+
865872
d3Select('.marker-line').style('opacity', 1);
866873
d3Select('#marker-tooltip').style('opacity', 1);
867874
};
868875

869-
const hideMarker = () => {
870-
d3Select('.marker-line').style('opacity', 0);
871-
d3Select('#marker-tooltip').style('opacity', 0);
872-
this.hideOldDotsOnMarker();
873-
};
874-
875876
return (chart: D3Selection<D3BaseType, {}, D3ContainerElement, {}>) => {
876877
if (!chart.select('.chart-content').empty()) {
877878
return;
@@ -884,7 +885,7 @@ export class LineChartService {
884885
.attr('height', this._height)
885886
.attr('fill', 'none')
886887
.on('mouseenter', () => showMarker())
887-
.on('mouseleave', () => hideMarker())
888+
.on('mouseleave', () => this.hideMarker())
888889
.on("contextmenu", () => d3Event.preventDefault())
889890
.on('mousemove', (_, index, nodes: D3ContainerElement[]) => {
890891
this.moveMarker(nodes[index], this._height)
@@ -927,19 +928,13 @@ export class LineChartService {
927928
}
928929
};
929930

930-
private moveMarker(node: D3ContainerElement, containerHeight: number) {
931-
const mouseCoordinates = d3Mouse(node);
932-
933-
if (this._xAxisCluster.length < 2) {
934-
return;
935-
}
936-
931+
private moveMarker = (() => {
937932
const pointsCompareDistance = (p1, p2): number => {
938933
// Taxicab/Manhattan approximation of euclidean distance
939934
return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
940935
};
941936

942-
const findNearestDot = (dots) => {
937+
const findNearestDot = (mouseCoordinates: [number, number], dots) => {
943938
const mousePosition = {x: mouseCoordinates[0], y: mouseCoordinates[1]};
944939

945940
let nearestDot = null;
@@ -983,21 +978,34 @@ export class LineChartService {
983978
});
984979
};
985980

986-
const nearestDot = findNearestDot(d3SelectAll('.dot'));
987-
const markerPositionX = nearestDot.attr('cx');
988-
//draw marker line
989-
const markerPath = `M${markerPositionX},${containerHeight} ${markerPositionX},0`;
990-
d3Select('.marker-line').attr('d', markerPath);
981+
return (node: D3ContainerElement, containerHeight: number) => {
982+
if (this._xAxisCluster.length < 2) {
983+
return;
984+
}
991985

992-
this.hideOldDotsOnMarker();
993-
const dotsOnMarker = findDotsOnMarker(markerPositionX);
994-
showDotsOnMarker(dotsOnMarker);
995-
nearestDot.attr('r', this.DOT_HIGHLIGHT_RADIUS);
986+
const nearestDot = findNearestDot(d3Mouse(node), d3SelectAll('.dot'));
996987

997-
this._dotsOnMarker = dotsOnMarker;
988+
if(!nearestDot) {
989+
this._dotsOnMarker = d3Select(null);
990+
this.hideMarker();
991+
return;
992+
}
998993

999-
this.showTooltip(nearestDot, dotsOnMarker, nearestDot.datum().date);
1000-
}
994+
const markerPositionX = nearestDot.attr('cx');
995+
//draw marker line
996+
const markerPath = `M${markerPositionX},${containerHeight} ${markerPositionX},0`;
997+
d3Select('.marker-line').attr('d', markerPath);
998+
999+
this.hideOldDotsOnMarker();
1000+
const dotsOnMarker = findDotsOnMarker(markerPositionX);
1001+
showDotsOnMarker(dotsOnMarker);
1002+
nearestDot.attr('r', this.DOT_HIGHLIGHT_RADIUS);
1003+
1004+
this._dotsOnMarker = dotsOnMarker;
1005+
1006+
this.showTooltip(nearestDot, dotsOnMarker, nearestDot.datum().date);
1007+
};
1008+
})();
10011009

10021010
private showContextMenu(menu: ContextMenuPosition[]) {
10031011
// this gets executed when a contextmenu event occurs
@@ -1181,8 +1189,8 @@ export class LineChartService {
11811189
};
11821190
})();
11831191

1184-
private addLegendsToChart = (() => {
1185-
const onLegendClick = (labelKey: string, incomingData: EventResultDataDTO): void => {
1192+
private addLegendsToChart = ((chart, xScale, yScale, data: TimeSeries[]) => {
1193+
const onLegendClick = (labelKey: string): void => {
11861194
if (d3Event.metaKey || d3Event.ctrlKey) {
11871195
this.legendDataMap[labelKey].show = !this.legendDataMap[labelKey].show;
11881196
} else {
@@ -1204,7 +1212,9 @@ export class LineChartService {
12041212
}
12051213

12061214
//redraw chart
1207-
this.drawLineChart(incomingData);
1215+
this.addDataLinesToChart(chart, xScale, yScale, data);
1216+
//redraw legend
1217+
drawLegend();
12081218
};
12091219

12101220
const getPosition = (index: number): string => {
@@ -1214,7 +1224,7 @@ export class LineChartService {
12141224
return "translate(" + x + "," + y + ")";
12151225
};
12161226

1217-
return (chart: D3Selection<D3BaseType, {}, D3ContainerElement, {}>, incomingData: EventResultDataDTO): void => {
1227+
const drawLegend = () => {
12181228
const legendGroup = d3Select('.legend-group');
12191229

12201230
// Remove old legend elements
@@ -1239,7 +1249,7 @@ export class LineChartService {
12391249
.attr("rx", 2)
12401250
.attr("ry", 2)
12411251
.attr('fill', (key: string, index: number) => {
1242-
return getColorScheme()[incomingData.series.length - index - 1]
1252+
return getColorScheme()[data.length - index - 1]
12431253
});
12441254
legendElement
12451255
.append('text')
@@ -1257,7 +1267,11 @@ export class LineChartService {
12571267
.remove()
12581268
)
12591269
.attr("transform", (_, index: number) => getPosition(index))
1260-
.on('click', (datum: string) => onLegendClick(datum, incomingData));
1270+
.on('click', (datum: string) => onLegendClick(datum));
12611271
};
1262-
})();
1272+
1273+
return (): void => {
1274+
drawLegend();
1275+
};
1276+
});
12631277
}

0 commit comments

Comments
 (0)