in src/PieChart.js [265:399]
render() {
const {
marginLeft,
marginRight,
marginTop,
marginBottom,
holeRadius,
} = this.props;
// sizes fallback based on provided info: given dimension -> radius + margin -> other dimension -> default
const width =
this.props.width ||
(this.props.radius
? this.props.radius * 2 + marginLeft + marginRight
: this.props.height) ||
DEFAULT_SIZE;
const height =
this.props.height ||
(this.props.radius
? this.props.radius * 2 + marginTop + marginBottom
: this.props.width) ||
DEFAULT_SIZE;
const radius =
this.props.radius ||
Math.min(
(width - (marginLeft + marginRight)) / 2,
(height - (marginTop + marginBottom)) / 2,
);
const center = { x: marginLeft + radius, y: marginTop + radius };
const {
data,
total,
centerLabel,
getPieSliceLabel,
markerLineValue,
markerLineOverhangInner,
markerLineOverhangOuter,
pieSliceClassName,
} = this.props;
const valueAccessor = makeAccessor(this.props.slice);
const sum = sumBy(data, valueAccessor);
const newTotal = total || sum;
const markerLinePercent = isFinite(markerLineValue)
? markerLineValue / newTotal
: null;
let startPercent = 0;
const slices = data.map(d => {
const slicePercent = valueAccessor(d) / newTotal;
const slice = {
start: startPercent,
end: startPercent + slicePercent,
};
startPercent += slicePercent;
return slice;
});
return (
<svg className="rct-pie-chart" {...{ width, height }}>
{data.map((d, i) => {
const [onMouseEnter, onMouseMove, onMouseLeave, onClick] = [
'onMouseEnterSlice',
'onMouseMoveSlice',
'onMouseLeaveSlice',
'onClick',
].map(eventName => {
// partially apply this slice's data point as 2nd callback argument
const callback = methodIfFuncProp(eventName, this.props, this);
return isFunction(callback) ? bindTrailingArgs(callback, d) : null;
});
const className = `rct-pie-slice rct-pie-slice-${i} ${getValue(
pieSliceClassName,
d,
i,
) || ''}`;
const slice = slices[i];
const pathStr = pieSlicePath(
slice.start,
slice.end,
center,
radius,
holeRadius,
);
const key = `pie-slice-${i}`;
return (
<path
{...{
className,
d: pathStr,
onMouseEnter,
onMouseMove,
onMouseLeave,
onClick,
key,
style: getValue(this.props.pieSliceStyle, d, i),
}}
/>
);
})}
{sum < newTotal ? ( // draw empty slice if the sum of slices is less than expected total
<path
className="rct-pie-slice rct-pie-slice-empty"
d={pieSlicePath(startPercent, 1, center, radius, holeRadius)}
key="pie-slice-empty"
/>
) : null}
{markerLinePercent !== null && isFinite(markerLinePercent)
? this.renderMarkerLine(
markerLine(
markerLinePercent,
center,
radius,
holeRadius,
markerLineOverhangOuter,
markerLineOverhangInner,
),
)
: null}
{centerLabel ? this.renderCenterLabel(center) : null}
{getPieSliceLabel
? data.map((d, i) =>
this.renderSliceLabel(d, slices[i], center, radius, i),
)
: null}
</svg>
);
}