reactでChartを表示する際にはrechartsを使用するのが王道のようです。(chartjsもありますが、v2.0に対応しているライブラリがまだメジャーになってないなど色々あるようです。)
Pieチャートのラベルをカスタマイズしてみます。
http://recharts.org/#/en-US/examples/PieChartWithCustomizedLabel
チャートを描画する部分は以下のようになりますが、labelに独自の関数(以下の例だと「renderCustomizedLabel」)を定義することでカスタマイズができるようになります。
<PieChart width={800} height={500} onMouseEnter={this.onPieEnter}> <Pie data={data} cx={400} cy={200} innerRadius={40} outerRadius={180} fill="#8884d8" paddingAngle={0} labelLine={false} label={renderCustomizedLabel} > {data.map((entry, index) => ( <Cell key={entry.name} fill={ChartColors[index % ChartColors.length]} /> ))} </Pie> </PieChart>
ラベル部分はcanvasタグに従った書き方でいろいろとかけるようです。
グラフの内側に描画するラベル
const inner = this.calcLabelPosition(cx, cy, midAngle, innerRadius, outerRadius, 0.5);
グラフの外側に描画するラベル
const outer = this.calcLabelPosition(cx, cy, midAngle, innerRadius, outerRadius, 1.1);
のようにして
const renderCustomizedLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, percent, index }) => { const outer = this.calcLabelPosition(cx, cy, midAngle, innerRadius, outerRadius, 1.1); const inner = this.calcLabelPosition(cx, cy, midAngle, innerRadius, outerRadius, 0.5); const item = this.props.data[index]; return ( <g> <text x={outer.x} y={outer.y} fill={ChartColors[index % ChartColors.length]} textAnchor={outer.x > cx ? 'start' : 'end'} dominantBaseline="central" > {item.name} </text> <text x={inner.x} y={inner.y} fill="white" textAnchor="middle" dominantBaseline="central" style={{ fontWeight: 'bold', fontSize: `${FontSize[index % FontSize.length]}` }} > {`${(percent * 100).toFixed(0)}%`} </text> </g> ); };
最終形は以下のようになります。
import React, { Component, PropTypes } from 'react'; // Redux import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; // Material UI import * as colors from 'material-ui/styles/colors'; // chart import { ResponsiveContainer, PieChart, Pie, Legend, Tooltip, Cell, Sector } from 'recharts'; // Other const ChartColors = [colors.lightBlue500, colors.lime500, colors.orange500, colors.red500]; const FontSize = ['100%', '150%', '400%', '600%']; const RADIAN = Math.PI / 180; class BaseChart extends Component { calcLabelPosition(cx, cy, midAngle, innerRadius, outerRadius, param) { const diff = outerRadius - innerRadius; const diffPercent = diff * param; const radius = innerRadius + diffPercent; const cos = Math.cos((-midAngle) * RADIAN); const ax = radius * cos; const sin = Math.sin((-midAngle) * RADIAN); const ay = radius * sin; const x = cx + ax; const y = cy + ay; return { x, y }; } render() { const renderCustomizedLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, percent, index }) => { const outer = this.calcLabelPosition(cx, cy, midAngle, innerRadius, outerRadius, 1.1); const inner = this.calcLabelPosition(cx, cy, midAngle, innerRadius, outerRadius, 0.5); const item = this.props.data[index]; return ( <g> <text x={outer.x} y={outer.y} fill={ChartColors[index % ChartColors.length]} textAnchor={outer.x > cx ? 'start' : 'end'} dominantBaseline="central" > {item.name} </text> <text x={inner.x} y={inner.y} fill="white" textAnchor="middle" dominantBaseline="central" style={{ fontWeight: 'bold', fontSize: `${FontSize[index % FontSize.length]}` }} > {`${(percent * 100).toFixed(0)}%`} </text> </g> ); }; const { data } = this.props; return ( <PieChart width={800} height={500} onMouseEnter={this.onPieEnter}> <Pie data={data} cx={400} cy={200} innerRadius={40} outerRadius={180} fill="#8884d8" paddingAngle={0} labelLine={false} label={renderCustomizedLabel} > {data.map((entry, index) => ( <Cell key={entry.name} fill={ChartColors[index % ChartColors.length]} /> ))} </Pie> </PieChart> ); } } BaseChart.propTypes = { data: React.PropTypes.shape().isRequired, }; export default BaseChart;