React Powered Radial Progress with SVG
HTML
<script src="http://fb.me/JSXTransformer-0.10.0.js"></script>
<script src="http://fb.me/react-with-addons-0.10.0.js"></script>
<script src="http://fb.me/react-js-fiddle-integration.js"></script>
<div id="progress-container"></div>
SCSS
html, body {
width: 100%;
height: 100%;
}
#progress-container {
width: 100px;
height: 100px;
position: relative;
display: block;
margin-left: 50%;
transform: translate(-50%, 50%);
}
.progress-radial-track {
fill: #247fd8;
}
.progress-radial-bar {
fill: white;
}
JavaScript 1.7
/** @jsx React.DOM */
'use strict';
var clamp = function (n, min, max) {
return Math.max(min, Math.min(max, n));
};
var ProgressRadial = React.createClass({
getDefaultProps: function () {
return {
percent: 0, // a float from 0 to 1
radius: 50,
barThickness: 15
};
},
getInitialState: function () {
return {
percent: this.props.percent,
pathData: this.calculatePath(this.props.percent)
}
},
componentWillReceiveProps: function (nextProps) {
if(!isNaN(nextProps.percent) && nextProps.percent !== this.props.percent) {
this.setState({
percent: nextProps.percent,
pathData: this.calculatePath(nextProps.percent)
});
}
},
render: function () {
return <div ref="progressRadial" className="progress-radial"></div>;
},
componentDidMount: function () {
this.renderSvg();
},
componentDidUpdate: function () {
this.updateSvg();
},
renderSvg: function () {
var svgString = this.createSvgString(this.state.pathData);
var elem = this.refs.progressRadial.getDOMNode();
elem.innerHTML = svgString;
},
calculatePath: function (percent) {
if(isNaN(percent)) {
return;
}
percent = clamp(parseFloat(percent), 0, 1);
// 360 loops back to 0, so keep it within 0 to < 360
var angle = clamp(percent * 360, 0, 359.99999);
var paddedRadius = this.props.radius + 1;
var radians = (angle * Math.PI / 180);
var x = Math.sin(radians) * paddedRadius;
var y = Math.cos(radians) * - paddedRadius;
var mid = (angle > 180) ? 1 : 0;
var pathData = 'M 0 0 v -%@ A %@ %@ 1 '.replace(/%@/gi, paddedRadius)
+ mid + ' 1 '
+ x + ' '
+ y + ' z';
return pathData;
},
updateSvg: function () {
var elem = this.refs.progressRadial.getDOMNode();
var path =...