Skip to content

Instantly share code, notes, and snippets.

@sttts
Created January 16, 2015 10:28
Show Gist options
  • Save sttts/63d77ada72c81dc056a4 to your computer and use it in GitHub Desktop.
Save sttts/63d77ada72c81dc056a4 to your computer and use it in GitHub Desktop.
A React PieChart component without D3
"use strict";
/** @jsx React.DOM */
var React = require("react/addons");
module.exports = React.createClass({displayName: "Pie",
propTypes: {
data : React.PropTypes.array.isRequired,
innerRadius: React.PropTypes.number,
className : React.PropTypes.string
},
getDefaultProps: function() {
return {
innerRadius: 0,
className: "pie"
};
},
arcPathCommands:function(start, end) {
var cx = this.props.size / 2; // center x
var cy = this.props.size / 2; // center y
var or = this.props.size / 2; // outer radius
var ir = this.props.innerRadius; // inner radius
function circlePoint(rad, r) {
return [cx + r*Math.sin(rad), cy - r*Math.cos(rad)].join(" ");
}
// The 4 points of the arc:
//
// p1_
// / `,
// / \
// p0 \
// \ *
// p3------p2
//
var p = [
circlePoint(start, ir),
circlePoint(start, or),
circlePoint(end, or),
circlePoint(end, ir),
];
// create svg path commands
var radDiff = end - start;
var largeArc = (radDiff % (Math.PI * 2) > Math.PI) ? 1 : 0;
var commands = [];
commands.push("M" + p[0]);
commands.push("L" + p[1]);
commands.push("A" + [or, or].join(" ") + " 0 " + largeArc + " 1 " + p[2]);
commands.push("L" + p[3]);
commands.push("A" + [ir, ir].join(" ") + " 0 " + largeArc + " 0 " + p[0]);
commands.push("Z");
return commands.join(" ");
},
render:function() {
var self = this;
// normalize data to add up to 360 degrees and convert to radian
var dataSum = this.props.data.reduce(function(a, x) { return a + x.quantity; }, 0);
var start = 0;
var normalizedData = [];
this.props.data.forEach(function(d) {
if (d.quantity > 0) {
// convert degrees to radian
var radDiff = d.quantity * 2 * Math.PI / dataSum;
var className = ((d.className || "") + " arc").trim();
if (d.quantity === dataSum) {
// full 360 degrees => split in two
normalizedData.push({
"start": start, "end": start + radDiff / 2,
"className": className
}, {
"start": start + radDiff / 2, "end": start + radDiff,
"className": className
});
} else {
// <360 degress => one arc
normalizedData.push({
"start": start, "end": start + radDiff,
"className": className
});
}
start += radDiff;
}
});
return (
<svg width={this.props.size} height={this.props.size} className={this.props.className}
version="1.1" xmlns="http://www.w3.org/2000/svg">
{normalizedData.map(function(d, i){
return (
<path d={self.arcPathCommands(d.start, d.end)} className={d.className} key={i} />
);
})}
</svg>
);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment