diff --git a/package.json b/package.json
index c934693c..e018f952 100644
--- a/package.json
+++ b/package.json
@@ -90,16 +90,17 @@
},
"dependencies": {
"babel-polyfill": "*",
- "classnames": "^2.2.0",
"browserify-zlib": "ipfs/browserify-zlib",
+ "classnames": "^2.2.0",
"coriolis-data": "EDCD/coriolis-data",
"d3": "4.6.0",
"fbemitter": "^2.0.0",
"lodash": "^4.15.0",
"lz-string": "^1.4.4",
- "react-number-editor": "Athanasius/react-number-editor.git#miggy",
"react": "^15.0.1",
"react-dom": "^15.0.1",
+ "react-number-editor": "Athanasius/react-number-editor.git#miggy",
+ "recharts": "^0.21.2",
"superagent": "^1.4.0"
}
}
diff --git a/src/app/Coriolis.jsx b/src/app/Coriolis.jsx
index 5d676b5e..c0e3ea89 100644
--- a/src/app/Coriolis.jsx
+++ b/src/app/Coriolis.jsx
@@ -241,14 +241,19 @@ export default class Coriolis extends React.Component {
/**
* Show the term tip
* @param {string} term Term or Phrase
- * @param {Object} opts Options - dontCap, orientation (n,e,s,w)
+ * @param {Object} opts Options - dontCap, orientation (n,e,s,w) (can also be the event if no options supplied)
* @param {SyntheticEvent} event Event
+ * @param {SyntheticEvent} e2 Alternative location for synthetic event from charts (where 'Event' is actually a chart index)
*/
- _termtip(term, opts, event) {
- if (opts && opts.nativeEvent) { // Opts is a SyntheticEvent
+ _termtip(term, opts, event, e2) {
+ if (opts && opts.nativeEvent) { // Opts is the SyntheticEvent
event = opts;
opts = { cap: true };
}
+ if (e2 instanceof Object && e2.nativeEvent) { // E2 is the SyntheticEvent
+ event = e2;
+ }
+
this._tooltip(
{this.state.language.translate(term)}
,
event.currentTarget.getBoundingClientRect(),
diff --git a/src/app/components/Defence.jsx b/src/app/components/Defence.jsx
index 56a1bafc..d365206c 100644
--- a/src/app/components/Defence.jsx
+++ b/src/app/components/Defence.jsx
@@ -165,7 +165,7 @@ export default class Defence extends TranslatedComponent {
{translate('damage taken')}(%)
-
+
{translate('effective shield')}(MJ)
diff --git a/src/app/components/VerticalBarChart.jsx b/src/app/components/VerticalBarChart.jsx
index 617b1b4b..b8a709cf 100644
--- a/src/app/components/VerticalBarChart.jsx
+++ b/src/app/components/VerticalBarChart.jsx
@@ -1,12 +1,11 @@
-import React, { Component } from 'react';
-import Measure from 'react-measure';
-import * as d3 from 'd3';
import TranslatedComponent from './TranslatedComponent';
+import React, { PropTypes } from 'react';
+import Measure from 'react-measure';
+import { BarChart, Bar, XAxis, YAxis } from 'recharts';
const CORIOLIS_COLOURS = ['#FF8C0D', '#1FB0FF', '#71A052', '#D5D54D'];
const LABEL_COLOUR = '#000000';
-
-const margin = { top: 10, right: 0, bottom: 0, left: 55 };
+const AXIS_COLOUR = '#C06400';
const ASPECT = 1;
@@ -20,8 +19,8 @@ const merge = function(one, two) {
export default class VerticalBarChart extends TranslatedComponent {
static propTypes = {
- data : React.PropTypes.array.isRequired,
- yMax : React.PropTypes.number
+ data : PropTypes.array.isRequired,
+ yMax : PropTypes.number
};
/**
@@ -32,6 +31,8 @@ export default class VerticalBarChart extends TranslatedComponent {
constructor(props, context) {
super(props);
+ this._termtip = this._termtip.bind(this);
+
this.state = {
dimensions: {
width: 300,
@@ -41,97 +42,64 @@ export default class VerticalBarChart extends TranslatedComponent {
}
/**
- * Render the graph
- * @param {Object} props React Component properties
- */
- _renderGraph(props) {
- let { width, height } = this.state.dimensions;
- const { tooltip, termtip } = this.context;
-
- width = width - margin.left - margin.right,
- height = width * ASPECT - margin.top - margin.bottom;
-
- // X axis is a band scale with values being 'label'
- this.x = d3.scaleBand();
- this.x.domain(this.props.data.map(d => d.label)).padding(0.2);
- this.xAxis = d3.axisBottom(this.x).tickValues(this.props.data.map(d => d.label));
- this.x.range([0, width]);
-
- // Y axis is a numeric scale with values being 'value'
- this.y = d3.scaleLinear();
- if (props.yMax) {
- // Fixed maximum value (unless we go off the scale)
- const localMax = d3.max(this.props.data, d => d.value);
- this.y.domain([0, localMax > props.yMax ? localMax : props.yMax]);
- } else {
- this.y.domain([0, d3.max(this.props.data, d => d.value)]);
- }
- this.yAxis = d3.axisLeft(this.y);
- this.y.range([height, 0]);
-
- let svg = d3.select(this.svg).select('g');
-
- svg.selectAll('rect').remove();
- svg.selectAll('text').remove();
-
- svg.select('.x.axis').remove();
- svg.select('.y.axis').remove();
-
- svg.append('g')
- .attr('class', 'x axis')
- .attr('transform', `translate(0, ${height})`)
- .call(this.xAxis);
-
- svg.append('g')
- .attr('class', 'y axis')
- .call(this.yAxis)
- .attr('fill', CORIOLIS_COLOURS[0]);
-
- svg.selectAll('rect.bar')
- .data(props.data)
- .enter().append('rect')
- .attr('class', 'bar')
- .attr('x', d => this.x(d.label))
- .attr('width', this.x.bandwidth())
- .attr('y', d => this.y(d.value))
- .attr('height', d => height - this.y(d.value))
- .attr('fill', CORIOLIS_COLOURS[0]);
-
- svg.selectAll('text.bar')
- .data(props.data)
- .enter().append('text')
- .attr('class', 'bar')
- .attr('text-anchor', 'middle')
- .attr('x', 100)
- .attr('y', 100)
- .attr('stroke-width', '0px')
- .attr('fill', LABEL_COLOUR)
- .attr('x', d => this.x(d.label) + this.x.bandwidth() / 2)
- .attr('y', d => this.y(d.value) + 15)
- .text(d => d.value);
- }
-
- /**
- * Render the component
- * @returns {object} Markup
+ * Render the bar chart
+ * @returns {Object} the markup
*/
render() {
- const { width } = this.state.dimensions;
- const translate = `translate(${margin.left}, ${margin.top})`;
+ const { width, height } = this.state.dimensions;
+ const { tooltip, termtip } = this.context;
- const height = width * ASPECT;
-
- this._renderGraph(this.props);
+ // Calculate maximum for Y
+ let dataMax = Math.max(...this.props.data.map(d => d.value));
+ if (dataMax == -Infinity) dataMax = 0;
+ let yMax = this.props.yMax ? Math.round(this.props.yMax) : 0;
+ const localMax = Math.max(dataMax, yMax);
return (
-
{ this.setState({ dimensions }); }}>
-
- { this.x ?
-
: null }
+
this.setState({ dimensions }) }>
+
+
+
+
+ } fill={CORIOLIS_COLOURS[0]} isAnimationActive={false} onMouseOver={this._termtip} onMouseOut={tooltip.bind(null, null)}/>
+
);
}
+
+ /**
+ * Generate a term tip
+ * @param {Object} d the data
+ * @param {number} i the index
+ * @param {Object} e the event
+ * @returns {Object} termtip markup
+ */
+ _termtip(d, i, e) {
+ if (this.props.data[i].tooltip) {
+ return this.context.termtip(this.props.data[i].tooltip, e);
+ } else {
+ return null;
+ }
+ }
}
+
+/**
+ * A label that displays the value within the bar of the chart
+ */
+const ValueLabel = React.createClass({
+ propTypes: {
+ x: PropTypes.number,
+ y: PropTypes.number,
+ payload: PropTypes.object,
+ value: PropTypes.number
+ },
+
+ render() {
+ const { x, y, payload, value } = this.props;
+
+ return (
+
{value}
+ );
+ }
+});