diff --git a/package.json b/package.json index 73ae8d7..96dd164 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,8 @@ "private": true, "dependencies": { "d3-dsv": "=1.0.7", + "d3-interpolate": "=1.1.5", + "d3-shape": "=1.2.0", "moment": "=2.18.1", "react": "^16.0.0", "react-dom": "^16.0.0", diff --git a/src/AlignPie.js b/src/AlignPie.js new file mode 100644 index 0000000..00cbe46 --- /dev/null +++ b/src/AlignPie.js @@ -0,0 +1,101 @@ +import React, { Component } from 'react'; +import * as d3s from 'd3-shape'; +import * as d3i from 'd3-interpolate'; + +const maxDuration = 500; +const step = 10; +const padRadians = 2 * Math.PI * 0.01; +const minPercentageOfTotal = 0.02; // 2 percent + +const pieColors = d3i.interpolateRgbBasis([ + '#7C98B3', + '#B3B7EE', + '#AF90A9', + '#A05C7B', + '#944654', +]); + +class PieSlice extends Component { + render() { + const { slice, arcGen, progress, color } = this.props; + + return + + ; + } +} + +class AlignPie extends Component { + constructor(props) { + super(props); + this.state = { + intervalId: null, + tick: 0, + }; + this.handleInterval = this.handleInterval.bind(this); + } + + handleInterval() { + if (this.state.tick >= maxDuration) { + clearInterval(this.state.intervalId); + } else { + this.setState({ tick: this.state.tick + step }); + } + } + + componentWillMount() { + this.setState({intervalId: setInterval(this.handleInterval, 10)}); + } + + render() { + const size = 500; + const radius = size * 0.8 / 2; + const total = Array.from(this.props.data.values()) + .reduce((acc, val) => acc + val, 0); + const dataArray = Array.from(this.props.data.entries()) + .map(([key, value]) => value / total > minPercentageOfTotal ? [key, value] : [key, total * minPercentageOfTotal]); + const pie = d3s.pie() + .value((d) => d[1])(dataArray) + .map((slice) => { + slice.interpolator = d3i.interpolateNumber(slice.startAngle, slice.endAngle - padRadians); + return slice; + }); + + const path = d3s.arc() + .outerRadius(radius) + .innerRadius(0) + + const label = d3s.arc() + .outerRadius(radius * 0.8) + .innerRadius(radius * 0.8); + + return + + {pie.map((angle) => )} + {pie.map((angle) => { + const textPosition = label.centroid(angle); + const textAnchor = textPosition[0] <= 0 ? 'start' : 'middle'; + return + {angle.data[0]} + ; + })} + + ; + } +} + +export default AlignPie; diff --git a/src/App.js b/src/App.js index 622eee2..403dee5 100644 --- a/src/App.js +++ b/src/App.js @@ -2,7 +2,8 @@ import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; import { csvParse } from 'd3-dsv'; -import { combineCsvs } from './dataParsers'; +import * as parsers from './dataParsers'; +import AlignPie from './AlignPie'; class App extends Component { constructor(props) { @@ -21,7 +22,7 @@ class App extends Component { .then((response) => response.ok ? response.text() : Promise.reject(`Failed to fetch ${url}`)) .then((text) => csvParse(text)); })) - .then((parsedCsvs) => this.setState({ data: combineCsvs([ + .then((parsedCsvs) => this.setState({ data: parsers.combineCsvs([ { data: parsedCsvs[0], dateFormat: 'YYYY, MMMM', @@ -40,7 +41,8 @@ class App extends Component {

Welcome to React

- { this.state.data ? 'I loaded all the data!' : 'Loading...' } + { !this.state.data && 'Loading...' } + { this.state.data && }

); diff --git a/src/dataParsers.js b/src/dataParsers.js index 46fa4f3..5e4b16b 100644 --- a/src/dataParsers.js +++ b/src/dataParsers.js @@ -4,8 +4,19 @@ export const combineCsvs = (csvArray) => { return csvArray.reduce((acc, current) => { const dateFormatted = current.data.map((value) => { value['FIRST APPEARANCE'] = moment(value['FIRST APPEARANCE'], current.dateFormat).format('MM/YYYY'); + if (!value['ALIGN']) { + value['ALIGN'] = 'Unknown'; + } return value; }); return acc.concat(dateFormatted); }, []); }; + +export const extractAlignmentCounts = (data) => { + return data.reduce((acc, item) => { + const count = acc.get(item['ALIGN']) || 0; + acc.set(item['ALIGN'], count + 1); + return acc; + }, new Map()); +}; diff --git a/yarn.lock b/yarn.lock index f1abccc..c40b615 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1731,6 +1731,10 @@ currently-unhandled@^0.4.1: dependencies: array-find-index "^1.0.1" +d3-color@1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.0.3.tgz#bc7643fca8e53a8347e2fbdaffa236796b58509b" + d3-dsv@=1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-1.0.7.tgz#137076663f398428fc3d031ae65370522492b78f" @@ -1739,6 +1743,22 @@ d3-dsv@=1.0.7: iconv-lite "0.4" rw "1" +d3-interpolate@=1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.1.5.tgz#69e099ff39214716e563c9aec3ea9d1ea4b8a79f" + dependencies: + d3-color "1" + +d3-path@1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.5.tgz#241eb1849bd9e9e8021c0d0a799f8a0e8e441764" + +d3-shape@=1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.2.0.tgz#45d01538f064bafd05ea3d6d2cb748fd8c41f777" + dependencies: + d3-path "1" + d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f"