From 21bada27b42f88315fef3715d1c57f5487b6330d Mon Sep 17 00:00:00 2001 From: tylercchase Date: Thu, 24 Oct 2024 10:05:43 -0400 Subject: [PATCH] fix: chart rerendering issue --- .../timeseries-results-menu.component.ts | 1 - .../timeseries-chart.component.html | 2 - .../timeseries-chart.component.ts | 255 ++++++------------ 3 files changed, 85 insertions(+), 173 deletions(-) diff --git a/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.ts b/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.ts index 6d608ba16..a95ae4d2c 100644 --- a/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.ts +++ b/src/app/components/results-menu/timeseries-results-menu/timeseries-results-menu.component.ts @@ -223,7 +223,6 @@ export class TimeseriesResultsMenuComponent implements OnInit, OnDestroy { let format = new WKT(); let wktRepresentation = format.writeGeometry(this.pointHistory[index]); this.mapService.loadPolygonFrom(wktRepresentation.toString()) - } console.log('updateSeries() task', task); console.log('updateSeries() task.subtasks', task.subtasks); diff --git a/src/app/components/timeseries-chart/timeseries-chart.component.html b/src/app/components/timeseries-chart/timeseries-chart.component.html index 74511aba3..c458f0d75 100644 --- a/src/app/components/timeseries-chart/timeseries-chart.component.html +++ b/src/app/components/timeseries-chart/timeseries-chart.component.html @@ -16,6 +16,4 @@ } -
- diff --git a/src/app/components/timeseries-chart/timeseries-chart.component.ts b/src/app/components/timeseries-chart/timeseries-chart.component.ts index 6d76c2193..44b8b90c8 100644 --- a/src/app/components/timeseries-chart/timeseries-chart.component.ts +++ b/src/app/components/timeseries-chart/timeseries-chart.component.ts @@ -70,6 +70,7 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { private thing: d3.Selection private hoveredElement; private data: any; + private lines; // private selectedScene: string; @Input() isLoading: boolean = false; @@ -95,14 +96,6 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { this.initChart(data); }) - // this.subs.add( - // this.store$.select(sceneStore.getSelectedScene).subscribe(test => { - // this.selectedScene = test.id; - // this.updateChart(); - // - // }) - // ); - this.subs.add( this.store$.select(chartsStore.getShowLines).subscribe( showLines => { @@ -118,22 +111,21 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { ) this.subs.add( - this.language.translate.onLangChange.subscribe( () => { - this.language.translate.get('SCENE').subscribe( (translated: string) => { - console.log(translated); - this.translateChartText(); - this.createSVG(); - }); - } + this.language.translate.onLangChange.subscribe(() => { + this.language.translate.get('SCENE').subscribe((_translated: string) => { + this.translateChartText(); + this.createSVG(); + }); + } ) ); } public translateChartText() { this.xAxisTitle = this.language.translate.instant('SCENE') + ' ' + - this.language.translate.instant('DATE'); + this.language.translate.instant('DATE'); this.yAxisTitle = this.language.translate.instant('SHORTWAVE_DISPLACEMENT') + ' (' + - this.language.translate.instant('METERS') + ')'; + this.language.translate.instant('METERS') + ')'; } public onZoomIn(): void { @@ -152,54 +144,48 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { } public initChart(data): void { - console.log('****** timeseries-chart init data *******', data); this.dataSource = [] - if(data !== null) { + if (data !== null) { let aoi: string = ''; - console.log('****** timeseries-chart init data *******', data); - for (let result of data) { - aoi = ''; - // pre-process data, remove test v_2 files from results - // won't be necessary in production - for (let key of Object.keys(result)) { - if (key.startsWith('v_2_')) { - delete result[key]; + for (let result of data) { + aoi = ''; + // pre-process data, remove test v_2 files from results + // won't be necessary in production + for (let key of Object.keys(result)) { + if (key.startsWith('v_2_')) { + delete result[key]; + } + if (key.startsWith('aoi')) { + aoi = result[key]; + } } - if (key.startsWith('aoi')) { - aoi = result[key]; + this.timeSeriesData = []; + for (let key of Object.keys(result).filter(x => x !== 'mean' && x !== 'aoi')) { + this.dataSource.push({ + 'aoi': aoi, + 'unwrapped_phase': result[key].unwrapped_phase, + 'interferometric_correlation': result[key].interferometric_correlation, + 'temporal_coherence': result[key].temporal_coherence, + 'date': result[key].secondary_datetime, + 'file_name': result[key].source_file_name, + 'id': key, + 'temporal_baseline': result[key].temporal_baseline + }) + this.timeSeriesData.push({ + 'unwrapped_phase': result[key].unwrapped_phase, + 'date': result[key].secondary_datetime + }); } - } - this.timeSeriesData = []; - for (let key of Object.keys(result).filter(x => x !== 'mean' && x !== 'aoi')) { - console.log('timeseries-chart init key', key); - console.log('timeseries-chart init result', result); - console.log('timeseries-chart init result[key]', result[key]); - this.dataSource.push({ - 'aoi': aoi, - 'unwrapped_phase': result[key].unwrapped_phase, - 'interferometric_correlation': result[key].interferometric_correlation, - 'temporal_coherence': result[key].temporal_coherence, - 'date': result[key].secondary_datetime, - 'file_name': result[key].source_file_name, - 'id': key, - 'temporal_baseline': result[key].temporal_baseline + this.dataReadyForChart.push({ 'name': aoi, 'values': this.timeSeriesData }); + this.averageData = ({ + ...data.mean }) - this.timeSeriesData.push({ - 'unwrapped_phase': result[key].unwrapped_phase, - 'date': result[key].secondary_datetime - }); } - this.dataReadyForChart.push({ 'name': aoi, 'values': this.timeSeriesData }); - this.averageData = ({ - ...data.mean - }) - } } else { this.dataSource = []; this.averageData = {}; } - console.log('timeseries-chart init dataReadyForChart', this.dataReadyForChart); this.svg.selectChildren().remove(); @@ -245,30 +231,26 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { this.toolTip.attr('transform', `translate(0, 0)`).style('text-anchor', 'middle').style('z-index', 100).style('opacity', 0) this.allGroup = [...new Set(this.dataReadyForChart.map(d => d.name))]; - console.log('allGroup', this.allGroup); this.lineGraph = this.clipContainer.append("path"); // A color scale: one color for each group const colorPalette = d3.scaleOrdinal() - .domain(this.allGroup) - .range(d3.schemeSet2); + .domain(this.allGroup) + .range(d3.schemeSet2); const self = this; - console.log('dataSource', this.dataSource); const points = this.dataSource.map((d) => [this.x(new Date(d.date)), this.y(d.unwrapped_phase), d.aoi]); - console.log('points', points); - const groups = d3.rollup(points, v => Object.assign(v, {z: v[0][2]}), d => d[2]); - console.log('groups', groups); - + const groups = d3.rollup(points, v => Object.assign(v, { z: v[0][2] }), d => d[2]); + groups // just do something this.dots = this.clipContainer.append('g') .selectAll("myDots") .data(this.dataReadyForChart) .enter() - .append('g') - // @ts-ignore - .style("fill", function (d: DataReady){ return colorPalette(d.name) }) + .append('g') + // @ts-ignore + .style("fill", function (d: DataReady) { return colorPalette(d.name) }) .selectAll('circle') .data(d => d.values) // .data(this.dataSource) @@ -291,23 +273,13 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { .duration(500) .style('opacity', 0); }) - // .on('click', (_event, d) => { - // this.store$.dispatch(new sceneStore.SetSelectedScene(d.id)) - // }) - // .attr('class', (d) => { - // if (this.selectedScene === d.id) { - // return 'timeseries-selected'; - // } else { - // return 'timeseries-base'; - // } - // }) .attr('r', 5); this.zoom = d3.zoom() .extent([[0, 0], [this.width, this.height]]) .on('zoom', (eve: d3.D3ZoomEvent) => { this.currentTransform = eve.transform; - this.initChart(this.data); + this.updateChart(); }); this.thing = d3.select('#timeseriesChart').selectChild() this.thing.call(this.zoom) @@ -320,16 +292,15 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { .attr('x', 0) .attr('y', 0); - if(this.dataSource.length <= 0) { + if (this.dataSource.length <= 0) { this.svg.append('rect') - .attr('width', this.width) - .attr('height', this.height) - .attr('x', 0) - .attr('y', 0) - .attr('class', 'loading-rect'); + .attr('width', this.width) + .attr('height', this.height) + .attr('x', 0) + .attr('y', 0) + .attr('class', 'loading-rect'); } - this.svg.append('text') .attr('transform', `translate(${this.width / 2}, ${this.height + this.margin.bottom - 20})`) .style('text-anchor', 'middle') @@ -344,39 +315,30 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { .attr('class', 'ts-chart-label') .text(this.yAxisTitle); - // this.svg - // .on("pointerenter", pointerentered) - // .on("pointermove", pointermoved) - // .on("pointerleave", pointerleft) - // .on("touchstart", event => event.preventDefault()); - // - // // When the pointer moves, find the closest point, update the interactive tip, and highlight - // // the corresponding line. Note: we don't actually use Voronoi here, since an exhaustive search - // // is fast enough. - // function pointermoved(event) { - // const [xm, ym] = d3.pointer(event); - // // @ts-ignore - // const i = d3.leastIndex(points, ([x, y]) => Math.hypot(x - xm, y - ym)); - // const [x, y, k] = points[i]; - // this.path.style("stroke", ({z}) => z === k ? null : "#ddd").filter(({z}) => z === k).raise(); - // this.dot.attr("transform", `translate(${x},${y})`); - // this.dot.select("text").text(k); - // // @ts-ignore - // self.svg.property("value", self.dataReadyForChart[i]).dispatch("input", {bubbles: true}); - // } - // - // function pointerentered() { - // this.path.style("mix-blend-mode", null).style("stroke", "#ddd"); - // this.dot.attr("display", null); - // } - // - // function pointerleft() { - // this.path.style("mix-blend-mode", "multiply").style("stroke", null); - // this.dot.attr("display", "none"); - // this.svg.node().value = null; - // // @ts-ignore - // self.svg.dispatch("input", {bubbles: true}); - // } + + if (this.showLines) { + + const colorPalette = d3.scaleOrdinal() + .domain(this.allGroup) + .range(d3.schemeSet2); + + // Add the lines + let line = d3.line() + .x(function (d) { return self.x(Date.parse(d.date)); }) + .y(function (d) { return self.y(d.unwrapped_phase); }) + this.lines = this.svg.selectAll("myLines") + .data(this.dataReadyForChart) + .enter() + .append("path") + .attr('clip-path', 'url(#clip)') + .attr("d", function (d) { // @ts-ignore + return line(d.values) + }) + // @ts-ignore + .attr("stroke", function (d: DataReady) { return colorPalette(d.name) }) + .style("stroke-width", 2) + .style("fill", "none") + } this.updateChart(); } @@ -395,58 +357,18 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { .ticks(smallChart ? 10 : 5, 's') ); - // var lineFunction = d3.line() - // .x(function (d) { return newX(Date.parse(d.date)); }) - // .y(function (d) { return newY(d.unwrapped_phase); }) - - this.dots .attr('cx', d => newX(Date.parse(d.date))) .attr('cy', d => newY(d.unwrapped_phase)) - // .attr('class', (d) => { - // if (this.selectedScene === d.id) { - // return 'timeseries-selected'; - // } else { - // return 'timeseries-base'; - // } - // }) - // .on('click', (_event, d) => { - // this.store$.dispatch(new sceneStore.SetSelectedScene(d.id)) - // }) - if (this.showLines) { - // this.addPairAttributes( - // this.lineGraph - // // .data(this.dataReadyForChart) - // .join("path") - // // .attr("d", d => line(d.values)) - // // .attr("stroke", d => (d.name)) - // .attr('d', _ => lineFunction(this.dataReadyForChart.flatMap(d => d.values))) - // .attr('fill', 'none') - // ) - - // A color scale: one color for each group - const colorPalette = d3.scaleOrdinal() - .domain(this.allGroup) - .range(d3.schemeSet2); - - // Add the lines - let line = d3.line() - .x(function (d) { return newX(Date.parse(d.date)); }) - .y(function (d) { return newY(d.unwrapped_phase); }) - this.svg.selectAll("myLines") - .data(this.dataReadyForChart) - .enter() - .append("path") - .attr('clip-path', 'url(#clip)') - .attr("d", function(d){ // @ts-ignore - return line(d.values) } ) - // @ts-ignore - .attr("stroke", function (d: DataReady){ return colorPalette(d.name) }) - .style("stroke-width", 2) - .style("fill", "none") + const line = d3.line() + .x(function (d) { return newX(Date.parse(d.date)); }) + .y(function (d) { return newY(d.unwrapped_phase); }) - } + this.lines + .attr("d", function (d) { // @ts-ignore + return line(d.values) + }) } private updateTooltip() { @@ -456,13 +378,6 @@ export class TimeseriesChartComponent implements OnInit, OnDestroy { .style('top', `${bounding.y - 10}px`); } - // private addPairAttributes(ps) { - // return ps - // .attr('class', 'base-line') - // .attr('stroke', 'steelblue') - // .attr('stroke-width', 1) - // }; - public onResized() { this.createSVG(); }