Skip to content

Commit

Permalink
#13: refactor and reduce SVG height
Browse files Browse the repository at this point in the history
  • Loading branch information
jennyxu6 committed Mar 22, 2018
1 parent 9915a49 commit fbad643
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 103 deletions.
103 changes: 62 additions & 41 deletions components/StackedBarChart/StackedBarChart.js
Original file line number Diff line number Diff line change
@@ -1,73 +1,94 @@
import React from 'react';

import React, { PropTypes } from 'react';
import * as d3 from 'd3';
import rd3 from 'react-d3-library';
import { Slider } from 'react-mdl';

import d3StackedBarChart from './d3StackedBarChart';
import s from './StackedBarChart.css';
import {Slider, Grid, Cell} from 'react-mdl';
import * as d3 from 'd3';

class StackedBarChart extends React.Component {
const minYear = 2013;
const maxYear = 2017;
const defaultYear = 2017;
const defaultHeight = 500;
const defaultWidth = 960;

class StackedBarChart extends React.Component {
constructor(props) {
super(props);
this.state = {d3: '', year: 2017};
this.state = { d3: '', year: defaultYear };
}

componentDidMount() {
this.setState({d3: d3StackedBarChart.getNode(this.props.data)});
this.setState({ d3: d3StackedBarChart.getNode(this.props.data, defaultHeight, defaultWidth) });
this.applyTransition();
}

applyTransition = () => {
let format = d3.format(",d");
let div = d3.select("#barChart").append("div").attr("class", s.tooltip).style("opacity", 0);
let format = d3.format(',d');
let div = d3
.select('#barChart')
.append('div')
.attr('class', s.tooltip)
.style('opacity', 0);

d3.selectAll('.segment').on("mouseover", function(d) {
let value = d[1]-d[0];
let segmentName = Object.keys(d.data).find(key => d.data[key] === value);
div.transition().duration(200).style("opacity", .9);
div.style("left", d3.select(this).attr("x") +"px");
div.style("top", d3.select(this).attr("y") +"px");
div.style("display", "inline-block");
div.html(segmentName + ": " + format(value));
}).on('mouseout', () => {
div.transition()
.duration(500)
.style("opacity", 0);
});
d3
.selectAll('.segment')
.on('mouseover', function(d) {
let value = d[1] - d[0];
let segmentName = Object.keys(d.data).find(key => d.data[key] === value);
div
.transition()
.duration(200)
.style('opacity', 0.9);
div.style('left', d3.select(this).attr('x') + 'px');
div.style('top', d3.select(this).attr('y') + 'px');
div.style('display', 'inline-block');
div.html(segmentName + ': ' + format(value));
})
.on('mouseout', () => {
div
.transition()
.duration(500)
.style('opacity', 0);
});

let changeTabHandler = this.props.changeTabHandler;
let viz = this.props.viz;
d3.selectAll('.segment').on("click", (d) => {
let segmentName = Object.keys(d.data).find(key => d.data[key] === (d[1]-d[0]));
d3.selectAll('.segment').on('click', d => {
let segmentName = Object.keys(d.data).find(key => d.data[key] === d[1] - d[0]);
changeTabHandler(4, viz, d.data.id, segmentName);
});

};

redraw = (event) => {
this.setState({d3: d3StackedBarChart.redraw(this.props.data, event.target.value), year: event.target.value});
redraw = event => {
this.setState({
d3: d3StackedBarChart.redraw(this.props.data, event.target.value, defaultHeight, defaultWidth),
year: event.target.value
});
};

render() {
const RD3Component = rd3.Component;

return (
<Grid>
<Cell col={12}>
<div className={`${s.barChart}`}>
{this.state.d3 && <Slider min={2013} max={2017} defaultValue={2017} onChange={this.redraw} />}
{this.state.year}
</div>
</Cell>
<Cell col={12}>
<div className={`${s.barChart}`} id="barChart">
<svg height="640" width="960"></svg>
{this.state.d3 && this.state.d3.length > 0 && <RD3Component data={this.state.d3} ref="barSvg"/>}
</div>
</Cell>
</Grid>
<div>
<div className={`${s.barChart}`}>
{this.state.d3 && <Slider min={minYear} max={maxYear} defaultValue={defaultYear} onChange={this.redraw} />}
{this.state.year}
</div>
<div className={`${s.barChart}`} id="barChart">
<svg height={defaultHeight} width={defaultWidth} />
{this.state.d3 && this.state.d3.length > 0 && <RD3Component data={this.state.d3} ref="barSvg" />}
</div>
</div>
);
}
}

StackedBarChart.propTypes = {
changeTabHandler: PropTypes.func,
data: PropTypes.array,
viz: PropTypes.string
};

export default StackedBarChart;
142 changes: 80 additions & 62 deletions components/StackedBarChart/d3StackedBarChart.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
import * as d3 from 'd3';

function getNode(data) {
let svg = d3.select("svg");
svg.selectAll("*").remove();
function getNode(data, defaultHeight, defaultWidth) {
let svg = d3.select('svg');
svg.selectAll('*').remove();

let qaFilteredData = data.filter(d => d.value.find(v => v > 0) > 0);
if(qaFilteredData.length > 0) {
let margin = {top: 20, right: 50, bottom: 30, left: 20}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom;
let keys = ["Structural decision", "Behavioral decision", "Non-existence - ban decision"];
let x = d3.scaleBand().rangeRound([0, width]).padding(0.3).align(0.3);
if (qaFilteredData.length > 0) {
let margin = { top: 20, right: 50, bottom: 30, left: 20 },
width = defaultWidth - margin.left - margin.right,
height = defaultHeight - margin.top - margin.bottom;
let keys = ['Structural decision', 'Behavioral decision', 'Non-existence - ban decision'];
let x = d3
.scaleBand()
.rangeRound([0, width])
.padding(0.3)
.align(0.3);
let y = d3.scaleLinear().rangeRound([height, 0]);
let z = d3.scaleOrdinal(d3.schemeCategory20);
let format = d3.format(",d");
let g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
let g = svg.append('g').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

qaFilteredData.map(qa => {
keys.map((k, i) => { qa.value[i] = +qa.value[i]; qa[k] = qa.value[i]; });
keys.map((k, i) => {
qa.value[i] = +qa.value[i];
qa[k] = qa.value[i];
});
qa.total = qa.value.reduce((a, b) => a + b, 0);
});

Expand All @@ -25,73 +33,83 @@ function getNode(data) {
y.domain([0, d3.max(qaFilteredData, d => d.total)]).nice();
z.domain(keys);

g.selectAll(".series")
g
.selectAll('.series')
.data(d3.stack().keys(keys)(qaFilteredData))
.enter().append("g")
.attr("class", "series")
.attr("fill", d => z(d.key))
.selectAll("rect")
.enter()
.append('g')
.attr('class', 'series')
.attr('fill', d => z(d.key))
.selectAll('rect')
.data(d => d)
.enter().append("rect")
.attr("class", "segment")
.attr("x", d => x(d.data.id))
.attr("y", d => y(d[1]))
.attr("height", d => y(d[0]) - y(d[1]))
.attr("width", x.bandwidth());


g.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.enter()
.append('rect')
.attr('class', 'segment')
.attr('x', d => x(d.data.id))
.attr('y', d => y(d[1]))
.attr('height', d => y(d[0]) - y(d[1]))
.attr('width', x.bandwidth());

g
.append('g')
.attr('class', 'axis')
.attr('transform', 'translate(0,' + height + ')')
.call(d3.axisBottom(x));

g.append("g")
.attr("class", "axis")
.call(d3.axisLeft(y).ticks(null, "s"))
.append("text")
.attr("x", 2)
.attr("y", y(y.ticks().pop()) + 0.5)
.attr("dy", "0.32em")
.attr("fill", "#000")
.attr("font-weight", "bold")
.attr("text-anchor", "start")
.text("Count");

let legend = g.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "end")
.selectAll("g")
g
.append('g')
.attr('class', 'axis')
.call(d3.axisLeft(y).ticks(null, 's'))
.append('text')
.attr('x', 2)
.attr('y', y(y.ticks().pop()) + 0.5)
.attr('dy', '0.32em')
.attr('fill', '#000')
.attr('font-weight', 'bold')
.attr('text-anchor', 'start')
.text('Count');

let legend = g
.append('g')
.attr('font-family', 'sans-serif')
.attr('font-size', 10)
.attr('text-anchor', 'end')
.selectAll('g')
.data(keys.slice().reverse())
.enter().append("g")
.attr("transform", (d, i) => "translate(0," + i * 20 + ")");

legend.append("rect")
.attr("x", width - 19)
.attr("width", 19)
.attr("height", 19)
.attr("fill", z);

legend.append("text")
.attr("x", width - 24)
.attr("y", 9.5)
.attr("dy", "0.32em")
.enter()
.append('g')
.attr('transform', (d, i) => 'translate(0,' + i * 20 + ')');

legend
.append('rect')
.attr('x', width - 19)
.attr('width', 19)
.attr('height', 19)
.attr('fill', z);

legend
.append('text')
.attr('x', width - 24)
.attr('y', 9.5)
.attr('dy', '0.32em')
.text(d => d);

} else {
svg.append('text').text('No Data!').attr("x", "300").attr("y", "300").style("font-size", "20px");
svg
.append('text')
.text('There is no data for this year. Please select another year.')
.attr('x', '300')
.attr('y', '200');
}
return svg;
}

function redraw(data, year) {
function redraw(data, year, defaultHeight, defaultWidth) {
let newData = data.map(d => {
let e = d.values.filter(v => v.year == year);
if(e.length > 0)
d.value = e[0].value;
if (e.length > 0) d.value = e[0].value;
return d;
});
return getNode(newData);
return getNode(newData, defaultHeight, defaultWidth);
}

let d3StackedBarChart = {
Expand Down

0 comments on commit fbad643

Please sign in to comment.