recharts
Version:
React charts
216 lines (215 loc) • 7.38 kB
JavaScript
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
import * as React from 'react';
import { clsx } from 'clsx';
import { filterProps } from '../util/ReactUtils';
import { polarToCartesian, RADIAN } from '../util/PolarUtils';
import { getPercentValue, mathSign } from '../util/DataUtils';
import { resolveDefaultProps } from '../util/resolveDefaultProps';
var getDeltaAngle = (startAngle, endAngle) => {
var sign = mathSign(endAngle - startAngle);
var deltaAngle = Math.min(Math.abs(endAngle - startAngle), 359.999);
return sign * deltaAngle;
};
var getTangentCircle = _ref => {
var {
cx,
cy,
radius,
angle,
sign,
isExternal,
cornerRadius,
cornerIsExternal
} = _ref;
var centerRadius = cornerRadius * (isExternal ? 1 : -1) + radius;
var theta = Math.asin(cornerRadius / centerRadius) / RADIAN;
var centerAngle = cornerIsExternal ? angle : angle + sign * theta;
var center = polarToCartesian(cx, cy, centerRadius, centerAngle);
// The coordinate of point which is tangent to the circle
var circleTangency = polarToCartesian(cx, cy, radius, centerAngle);
// The coordinate of point which is tangent to the radius line
var lineTangencyAngle = cornerIsExternal ? angle - sign * theta : angle;
var lineTangency = polarToCartesian(cx, cy, centerRadius * Math.cos(theta * RADIAN), lineTangencyAngle);
return {
center,
circleTangency,
lineTangency,
theta
};
};
var getSectorPath = _ref2 => {
var {
cx,
cy,
innerRadius,
outerRadius,
startAngle,
endAngle
} = _ref2;
var angle = getDeltaAngle(startAngle, endAngle);
// When the angle of sector equals to 360, star point and end point coincide
var tempEndAngle = startAngle + angle;
var outerStartPoint = polarToCartesian(cx, cy, outerRadius, startAngle);
var outerEndPoint = polarToCartesian(cx, cy, outerRadius, tempEndAngle);
var path = "M ".concat(outerStartPoint.x, ",").concat(outerStartPoint.y, "\n A ").concat(outerRadius, ",").concat(outerRadius, ",0,\n ").concat(+(Math.abs(angle) > 180), ",").concat(+(startAngle > tempEndAngle), ",\n ").concat(outerEndPoint.x, ",").concat(outerEndPoint.y, "\n ");
if (innerRadius > 0) {
var innerStartPoint = polarToCartesian(cx, cy, innerRadius, startAngle);
var innerEndPoint = polarToCartesian(cx, cy, innerRadius, tempEndAngle);
path += "L ".concat(innerEndPoint.x, ",").concat(innerEndPoint.y, "\n A ").concat(innerRadius, ",").concat(innerRadius, ",0,\n ").concat(+(Math.abs(angle) > 180), ",").concat(+(startAngle <= tempEndAngle), ",\n ").concat(innerStartPoint.x, ",").concat(innerStartPoint.y, " Z");
} else {
path += "L ".concat(cx, ",").concat(cy, " Z");
}
return path;
};
var getSectorWithCorner = _ref3 => {
var {
cx,
cy,
innerRadius,
outerRadius,
cornerRadius,
forceCornerRadius,
cornerIsExternal,
startAngle,
endAngle
} = _ref3;
var sign = mathSign(endAngle - startAngle);
var {
circleTangency: soct,
lineTangency: solt,
theta: sot
} = getTangentCircle({
cx,
cy,
radius: outerRadius,
angle: startAngle,
sign,
cornerRadius,
cornerIsExternal
});
var {
circleTangency: eoct,
lineTangency: eolt,
theta: eot
} = getTangentCircle({
cx,
cy,
radius: outerRadius,
angle: endAngle,
sign: -sign,
cornerRadius,
cornerIsExternal
});
var outerArcAngle = cornerIsExternal ? Math.abs(startAngle - endAngle) : Math.abs(startAngle - endAngle) - sot - eot;
if (outerArcAngle < 0) {
if (forceCornerRadius) {
return "M ".concat(solt.x, ",").concat(solt.y, "\n a").concat(cornerRadius, ",").concat(cornerRadius, ",0,0,1,").concat(cornerRadius * 2, ",0\n a").concat(cornerRadius, ",").concat(cornerRadius, ",0,0,1,").concat(-cornerRadius * 2, ",0\n ");
}
return getSectorPath({
cx,
cy,
innerRadius,
outerRadius,
startAngle,
endAngle
});
}
var path = "M ".concat(solt.x, ",").concat(solt.y, "\n A").concat(cornerRadius, ",").concat(cornerRadius, ",0,0,").concat(+(sign < 0), ",").concat(soct.x, ",").concat(soct.y, "\n A").concat(outerRadius, ",").concat(outerRadius, ",0,").concat(+(outerArcAngle > 180), ",").concat(+(sign < 0), ",").concat(eoct.x, ",").concat(eoct.y, "\n A").concat(cornerRadius, ",").concat(cornerRadius, ",0,0,").concat(+(sign < 0), ",").concat(eolt.x, ",").concat(eolt.y, "\n ");
if (innerRadius > 0) {
var {
circleTangency: sict,
lineTangency: silt,
theta: sit
} = getTangentCircle({
cx,
cy,
radius: innerRadius,
angle: startAngle,
sign,
isExternal: true,
cornerRadius,
cornerIsExternal
});
var {
circleTangency: eict,
lineTangency: eilt,
theta: eit
} = getTangentCircle({
cx,
cy,
radius: innerRadius,
angle: endAngle,
sign: -sign,
isExternal: true,
cornerRadius,
cornerIsExternal
});
var innerArcAngle = cornerIsExternal ? Math.abs(startAngle - endAngle) : Math.abs(startAngle - endAngle) - sit - eit;
if (innerArcAngle < 0 && cornerRadius === 0) {
return "".concat(path, "L").concat(cx, ",").concat(cy, "Z");
}
path += "L".concat(eilt.x, ",").concat(eilt.y, "\n A").concat(cornerRadius, ",").concat(cornerRadius, ",0,0,").concat(+(sign < 0), ",").concat(eict.x, ",").concat(eict.y, "\n A").concat(innerRadius, ",").concat(innerRadius, ",0,").concat(+(innerArcAngle > 180), ",").concat(+(sign > 0), ",").concat(sict.x, ",").concat(sict.y, "\n A").concat(cornerRadius, ",").concat(cornerRadius, ",0,0,").concat(+(sign < 0), ",").concat(silt.x, ",").concat(silt.y, "Z");
} else {
path += "L".concat(cx, ",").concat(cy, "Z");
}
return path;
};
var defaultProps = {
cx: 0,
cy: 0,
innerRadius: 0,
outerRadius: 0,
startAngle: 0,
endAngle: 0,
cornerRadius: 0,
forceCornerRadius: false,
cornerIsExternal: false
};
export var Sector = sectorProps => {
var props = resolveDefaultProps(sectorProps, defaultProps);
var {
cx,
cy,
innerRadius,
outerRadius,
cornerRadius,
forceCornerRadius,
cornerIsExternal,
startAngle,
endAngle,
className
} = props;
if (outerRadius < innerRadius || startAngle === endAngle) {
return null;
}
var layerClass = clsx('recharts-sector', className);
var deltaRadius = outerRadius - innerRadius;
var cr = getPercentValue(cornerRadius, deltaRadius, 0, true);
var path;
if (cr > 0 && Math.abs(startAngle - endAngle) < 360) {
path = getSectorWithCorner({
cx,
cy,
innerRadius,
outerRadius,
cornerRadius: Math.min(cr, deltaRadius / 2),
forceCornerRadius,
cornerIsExternal,
startAngle,
endAngle
});
} else {
path = getSectorPath({
cx,
cy,
innerRadius,
outerRadius,
startAngle,
endAngle
});
}
return /*#__PURE__*/React.createElement("path", _extends({}, filterProps(props, true), {
className: layerClass,
d: path
}));
};