diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/nodes/DataVizBox/ChartBox.tsx | 4 | ||||
-rw-r--r-- | src/client/views/nodes/DataVizBox/LineChart.tsx | 124 |
2 files changed, 98 insertions, 30 deletions
diff --git a/src/client/views/nodes/DataVizBox/ChartBox.tsx b/src/client/views/nodes/DataVizBox/ChartBox.tsx index 36d23d30e..7424fbe5f 100644 --- a/src/client/views/nodes/DataVizBox/ChartBox.tsx +++ b/src/client/views/nodes/DataVizBox/ChartBox.tsx @@ -32,6 +32,7 @@ export interface ChartData { xLabel: string; yLabel: string; data: DataPoints[]; + tooltipContent: (data: DataPoints) => string; } @observer @@ -64,6 +65,9 @@ export class ChartBox extends React.Component<ChartBoxProps> { xLabel: '', yLabel: '', data: [], + tooltipContent: (data: DataPoints) => { + return `<b>x: ${data.x} y: ${data.y}</b>`; + }, }; if (this.props.pairs && this.props.pairs.length > 0) { diff --git a/src/client/views/nodes/DataVizBox/LineChart.tsx b/src/client/views/nodes/DataVizBox/LineChart.tsx index 2d2e67d4f..5ad8f0846 100644 --- a/src/client/views/nodes/DataVizBox/LineChart.tsx +++ b/src/client/views/nodes/DataVizBox/LineChart.tsx @@ -1,4 +1,4 @@ -import { computed, IReactionDisposer, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { ChartData, DataPoints } from './ChartBox'; @@ -11,9 +11,18 @@ interface LineChartProps { height: number; } +interface SelectedDataPoint { + x: number; + y: number; + elem: d3.Selection<d3.BaseType, unknown, SVGGElement, unknown>; +} + @observer export class LineChart extends React.Component<LineChartProps> { private _dataReactionDisposer: IReactionDisposer | undefined = undefined; + @observable private _x: number = 0; + @observable private _y: number = 0; + @observable private _currSelected: SelectedDataPoint | undefined = undefined; componentDidMount() { console.log('Getting to line chart'); @@ -27,9 +36,15 @@ export class LineChart extends React.Component<LineChartProps> { } } + tooltipContent(data: DataPoints) { + return `<b>x: ${data.x} y: ${data.y}</b>`; + } + drawChart() { - console.log('Getting called'); - console.log(this.props.data); + // clearing tooltip + d3.select('#chart-container').select('svg').remove(); + d3.select('#chart-container').select('.tooltip').remove(); + const margin = { top: 50, right: 50, bottom: 50, left: 50 }; const { data } = this.props; @@ -54,7 +69,7 @@ export class LineChart extends React.Component<LineChartProps> { // adding x axis const xScale = d3.scaleLinear().domain([xMin, xMax]).range([0, this.props.width]); - const yScale = d3.scaleLinear().domain([yMin, yMax]).range([this.props.height, 0]); + const yScale = d3.scaleLinear().domain([0, yMax]).range([this.props.height, 0]); // create a line function that takes in the data.data.x and data.data.y // TODO: nda - fix the types for the d here @@ -86,37 +101,86 @@ export class LineChart extends React.Component<LineChartProps> { svg.append('g').attr('class', 'y-axis').call(d3.axisLeft(yScale)); // draw the line - svg.append('path').datum(data.data).attr('fill', 'none').attr('stroke', '#f6c3d0').attr('stroke-width', 4).attr('class', 'line').attr('d', lineGen); + svg.append('path').datum(data.data).attr('fill', 'none').attr('stroke', 'rgba(53, 162, 235, 0.5)').attr('stroke-width', 2).attr('class', 'line').attr('d', lineGen); + + // draw the datapoint circles + svg.selectAll('.circle-d1') + .data(data.data) + .join('circle') // enter append + .attr('class', 'circle-d1') + .attr('r', '3') // radius + .attr('cx', d => xScale(d.x)) + .attr('cy', d => yScale(d.y)) + .attr('data-x', d => d.x) + .attr('data-y', d => d.y); + + // this.setupDatapointClickHandlers(); const focus = svg.append('g').attr('class', 'focus').style('display', 'none'); focus.append('circle').attr('r', 5).attr('class', 'circle'); - // const tooltip = d3.select('#container').append('div').attr('class', 'tooltip').style('opacity', 0); - - // const mousemove = (event) => { - // const bisect = d3.bisector((d: DataPoints) => d.x).left; - // const xPos = d3.pointer(this)[0]; - // const x0 = bisect(data.data, xScale.invert(xPos)); - // const d0 = data.data[x0]; - // focus.attr('transform', `translate(${xScale(d0.x)},${yScale(d0.y)})`); - // tooltip.transition().duration(300).style('opacity', 0.9); - // tooltip.html(d0.tooltipContent || d0.label).style('transform', `translate(${xScale(d0.label) + 30}px,${yScale(d0.value) - 30}px)`); - // } - - // svg.append('rect') - // .attr('class', 'overlay') - // .attr('width', this.props.width) - // .attr('height', this.props.height) - // .style('opacity', 0) - // .on('mouseover', () => { - // focus.style('display', null); - // }) - // .on('mouseout', () => { - // tooltip.transition().duration(300).style('opacity', 0); - // }) - // .on('mousemove', mousemove); + const tooltip = d3 + .select('#chart-container') + .append('div') + .attr('class', 'tooltip') + .style('opacity', 0) + .style('position', 'absolute') + // .style('z-index', '10') + .style('background', '#fff') + .style('border', '1px solid #ccc') + .style('padding', '5px') + .style('font-size', '12px'); + // add all the tooltipContent to the tooltip + // @action + const mousemove = action((e: any) => { + const bisect = d3.bisector((d: DataPoints) => d.x).left; + const xPos = d3.pointer(e)[0]; + const x0 = bisect(data.data, xScale.invert(xPos)); + const d0 = data.data[x0]; + this._x = d0.x; + this._y = d0.y; + focus.attr('transform', `translate(${xScale(d0.x)},${yScale(d0.y)})`); + // TODO: nda - implement tooltips + // tooltip.transition().duration(300).style('opacity', 0.9); + // tooltip.html(() => this.tooltipContent(d0)).attr('transform', `translate(${xScale(d0.x) + 30}px,${yScale(d0.y) + 30}px)`); + }); + + const onPointClick = action((e: any) => { + const bisect = d3.bisector((d: DataPoints) => d.x).left; + const xPos = d3.pointer(e)[0]; + const x0 = bisect(data.data, xScale.invert(xPos)); + const d0 = data.data[x0]; + this._x = d0.x; + this._y = d0.y; + // find .circle-d1 with data-x = d0.x and data-y = d0.y + const selected = svg.selectAll('.circle-d1').filter((d: any) => d['data-x'] === d0.x && d['data-y'] === d0.y); + this._currSelected = { x: d0.x, y: d0.y, elem: selected }; + console.log('Getting here'); + console.log(this._currSelected); + }); + + svg.append('rect') + .attr('class', 'overlay') + .attr('width', this.props.width) + .attr('height', this.props.height) + .style('opacity', 0) + .on('mouseover', () => { + focus.style('display', null); + }) + .on('mouseout', () => { + tooltip.transition().duration(300).style('opacity', 0); + }) + .on('mousemove', mousemove) + .on('click', onPointClick); } render() { - return <div id="chart-container"></div>; + return ( + <div id="chart-container"> + <span> + x: {this._x} y: {this._y} + Curr Selected: {this._currSelected ? `x: ${this._currSelected.x} y: ${this._currSelected.y}` : 'none'} + </span> + </div> + ); } } |