React D3 Donut Chart
source link: https://dev.to/vineethtrv/react-d3-donut-chart-49cm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
React D3 Donut Chart
Jun 20
・4 min read
D3.js is one of the best JavaScript library for data visualizations,
let's combine D3 and React create a simple Donut Chart.
I am not going to explain how we can create react app 😉
We can start from d3 onboarding.
Add D3 on you project
npm i --save d3
Create DonutChart component
After installing D3 we will create a new react component called DonutChart
. here I am giving file name 'DonutChart.js'.
import React , { Component} from 'react';
class DonutChart extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
}
render() {
return <>
<div></div>
</>
}
}
export default DonutChart;
Use D3 in React component
We will import D3 in to our component
import * as d3 from 'd3';
Create D3 selectors with React refs
class DonutChart extends Component {
constructor(props) {
super(props);
this.chRef = React.createRef();
}
componentDidMount() {
const divEl = d3.select(this.chRef.current)
}
render() {
return <>
<div ref={this.chRef}></div>
</>
}
}
Donut Painting
Create a colors Array for the donut partition painting
const colors = [ '#8ce8ad', '#57e188', '#34c768', '#2db757', '#27acaa', '#42c9c2', '#60e6e1', '#93f0e6', '#87d3f2', '#4ebeeb', '#35a4e8', '#188ce5', '#542ea5', '#724bc3', '#9c82d4', '#c981b2', '#b14891', '#ff6d00', '#ff810a', '#ff9831', '#ffb46a', '#ff9a91', '#ff736a', '#f95d54', '#ff4136', '#c4c4cd' ];
Or else we can create random color generator. in this option you need to also consider text colors for readability and better user experiences
const colors = ()=> { '#' + Math.floor(Math.random()*16777215).toString(16)}
Draw donut chart
let's deep in to the show 🏊🏻, We will create a drawChart()
method for portability.
// DrawChart
drawChart(){
const {data } = this.props;
const svgContainer = d3.select(this.chRef.current).node();
const width = svgContainer.getBoundingClientRect().width;
const height = width;
const margin = 15;
let radius = Math.min(width, height) / 2 - margin;
// Create SVG
const svg = d3.select(this.chRef.current)
.append('svg')
.attr("width", '100%')
.attr("height", '100%')
.attr('viewBox', '0 0 ' + width + ' ' + width )
//.attr('preserveAspectRatio','xMinYMin')
.append("g")
.attr("transform", "translate(" + Math.min(width,height) / 2 + "," + Math.min(width,height) / 2 + ")");
let pie = d3.pie()
.value( d => d.value )
let data_ready = pie(data)
// Donut partition
svg
.selectAll('whatever')
.data(data_ready)
.enter()
.append('path')
.attr('d', d3.arc()
.innerRadius(radius/ 1.75) // This is the size of the donut hole
.outerRadius(radius)
)
.attr('fill', (d) => colors[d.index] )
.attr("stroke", "#fff")
.style("stroke-width", "2")
.style("opacity", "0.8")
}
Show partition name and value
We can add labels also for identifying the donut partition.
// legend Position
let legendPosition = d3.arc().innerRadius(radius/1.75).outerRadius(radius);
// Legend group and legend name
svg
.selectAll('mySlices')
.data(data_ready)
.enter()
.append('g')
.attr("transform", d => `translate(${legendPosition.centroid(d)})`)
.attr("class", 'legend-g')
.style("user-select", "none")
.append('text')
.text(d => d.data.name)
.style("text-anchor", "middle")
.style("font-weight", 700)
.style("fill", '#222')
.style("font-size", 14);
//Label for value
svg
.selectAll('.legend-g')
.append('text')
.text((d) => { return d.data.value })
.style("fill", '#444')
.style("font-size", 12)
.style("text-anchor", "middle")
.attr("y", 16);
View DonutChart.js
let's see full picture of DonutChart.js
import React , { Component} from 'react';
import * as d3 from 'd3';
const colors = [ '#8ce8ad', '#57e188', '#34c768', '#2db757', '#27acaa', '#42c9c2', '#60e6e1', '#93f0e6', '#87d3f2', '#4ebeeb', '#35a4e8', '#188ce5', '#542ea5', '#724bc3', '#9c82d4', '#c981b2', '#b14891', '#ff6d00', '#ff810a', '#ff9831', '#ffb46a', '#ff9a91', '#ff736a', '#f95d54', '#ff4136', '#c4c4cd' ];
class DonutChart extends Component {
constructor(props) {
super(props);
this.chRef = React.createRef();
}
// Chart load after component Mount
componentDidMount() {
this.drawChart()
}
// DrawChart
drawChart(){
const {data } = this.props;
const svgContainer = d3.select(this.chRef.current).node();
const width = svgContainer.getBoundingClientRect().width;
const height = width;
const margin = 15;
let radius = Math.min(width, height) / 2 - margin;
// legend Position
let legendPosition = d3.arc().innerRadius(radius/1.75).outerRadius(radius);
// Create SVG
const svg = d3.select(this.chRef.current)
.append('svg')
.attr("width", '100%')
.attr("height", '100%')
.attr('viewBox', '0 0 ' + width + ' ' + width )
//.attr('preserveAspectRatio','xMinYMin')
.append("g")
.attr("transform", "translate(" + Math.min(width,height) / 2 + "," + Math.min(width,height) / 2 + ")");
let pie = d3.pie()
.value( d => d.value )
let data_ready = pie(data)
// Donut partition
svg
.selectAll('whatever')
.data(data_ready)
.enter()
.append('path')
.attr('d', d3.arc()
.innerRadius(radius/ 1.75) // This is the size of the donut hole
.outerRadius(radius)
)
.attr('fill', (d) => colors[d.index] )
.attr("stroke", "#fff")
.style("stroke-width", "2")
.style("opacity", "0.8")
// Legend group and legend name
svg
.selectAll('mySlices')
.data(data_ready)
.enter()
.append('g')
.attr("transform", d => `translate(${legendPosition.centroid(d)})`)
.attr("class", 'legend-g')
.style("user-select", "none")
.append('text')
.text(d => d.data.name)
.style("text-anchor", "middle")
.style("font-weight", 700)
.style("fill", '#222')
.style("font-size", 14);
//Label for value
svg
.selectAll('.legend-g')
.append('text')
.text((d)=>{ return d.data.value})
.style("fill", '#444')
.style("font-size", 12)
.style("text-anchor", "middle")
.attr("y", 16 );
}
render() {
return <>
<div ref={this.chRef}></div> </>
}
}
export default DonutChart;
Import and Use
Let's Import and use DonutChart
in application
import './App.css';
import DonutChart from './charts/DonutChart.js';
const donutData = [
{name: "<5", value: 19},
{name: "5-9", value: 20},
{name: "10-14", value: 19},
{name: "15-19", value: 24},
{name: "20-24", value: 22},
{name: "25-29", value: 29},
{name: "30-34", value: 22},
{name: "35-39", value: 18},
{name: "40-44", value: 23},
{name: "45-49", value: 19},
{name: "50-54", value: 16},
{name: "55-59", value: 19},
{name: "60-64", value: 28},
{name: "65-69", value: 17},
{name: "70-74", value: 20},
{name: "75-79", value: 17},
{name: "80-84", value: 18},
{name: "≥85", value: 21}
]
function App() {
return (
<div className="App">
<DonutChart data={donutData} />
</div>
);
}
export default App;
Result
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK