Donut Chart using Styled Components
import React, { Component } from "react"; | |
import PropTypes from "prop-types"; | |
import styled from "styled-components"; | |
const dimsFromProps = ({ size, strokeWidth, value }) => { | |
const halfsize = size * 0.5; | |
const radius = halfsize - strokeWidth * 0.5; | |
const circumference = 2 * Math.PI * radius; | |
const strokeVal = value * circumference / 100; | |
const dashVal = strokeVal + " " + circumference; | |
const rotateVal = "rotate(-90 " + halfsize + "," + halfsize + ")"; | |
return { | |
halfsize, | |
radius, | |
circumference, | |
strokeVal, | |
dashVal, | |
rotateVal, | |
size, | |
value, | |
strokeWidth, | |
}; | |
}; | |
const Container = styled.span` | |
border-radius: 50%; | |
display: block; | |
position: relative; | |
`; | |
const Track = styled.circle` | |
fill: transparent; | |
stroke: #dae2e5; | |
`; | |
const Indicator = styled.circle` | |
fill: transparent; | |
stroke: #009688; | |
stroke-dasharray: ${props => dimsFromProps(props).dashVal || "0 10000"}; | |
transition: stroke-dasharray 0.3s ease; | |
`; | |
const Text = styled.span` | |
width: ${({ width }) => width + "px"}; | |
height: ${({ height }) => height + "px"}; | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
justify-content: center; | |
position: absolute; | |
top: 0; | |
left: 0; | |
`; | |
class DonutChart extends Component { | |
static defaultProps = { | |
value: 50, | |
size: 116, | |
strokeWidth: 26, | |
}; | |
render() { | |
const { | |
halfsize, | |
radius, | |
rotateVal, | |
size, | |
value, | |
strokeWidth, | |
} = dimsFromProps(this.props); | |
const { className, children } = this.props; | |
return ( | |
<Container className={className} width={size} height={size}> | |
<svg width={size} height={size}> | |
<Track | |
r={radius} | |
cx={halfsize} | |
cy={halfsize} | |
transform={rotateVal} | |
value={value} | |
size={size} | |
strokeWidth={strokeWidth} | |
/> | |
<Indicator | |
r={radius} | |
cx={halfsize} | |
cy={halfsize} | |
transform={rotateVal} | |
value={value} | |
size={size} | |
strokeWidth={strokeWidth} | |
/> | |
</svg> | |
<Text width={size} height={size}> | |
{children} | |
</Text> | |
</Container> | |
); | |
} | |
} | |
DonutChart.propTypes = { | |
className: PropTypes.string, | |
value: PropTypes.number, // value the chart should show | |
size: PropTypes.number, // diameter of chart | |
strokeWidth: PropTypes.number, // width of chart line | |
}; | |
export default DonutChart; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment