decorate method
void
decorate(
- List<
ArcRendererElementList< arcElementsList,D> > - ChartCanvas canvas,
- GraphicsFactory graphicsFactory, {
- required Rectangle<
num> drawBounds, - required double animationPercent,
- bool rtl = false,
Implementation
@override
void decorate(
List<ArcRendererElementList<D>> arcElementsList,
ChartCanvas canvas,
GraphicsFactory graphicsFactory, {
required Rectangle drawBounds,
required double animationPercent,
bool rtl = false,
}) {
// Only decorate the arcs when animation is at 100%.
if (animationPercent != 1.0) {
return;
}
// Create [TextStyle] from [TextStyleSpec] to be used by all the elements.
// The [GraphicsFactory] is needed so it can't be created earlier.
final insideLabelStyle =
_getTextStyle(graphicsFactory, insideLabelStyleSpec);
final outsideLabelStyle =
_getTextStyle(graphicsFactory, outsideLabelStyleSpec);
// Track the Y position of the previous outside label for collision
// detection purposes.
for (final arcElements in arcElementsList) {
_previousOutsideLabelY = null;
_previousLabelLeftOfChart = null;
for (final element in arcElements.arcs) {
final labelFn = element.series.labelAccessorFn;
final datumIndex = element.index;
final label = (labelFn != null) ? labelFn(datumIndex) : null;
// If there are custom styles, use that instead of the default or the
// style defined for the entire decorator.
final datumInsideLabelStyle = _getDatumStyle(
element.series.insideLabelStyleAccessorFn,
datumIndex,
graphicsFactory,
defaultStyle: insideLabelStyle,
);
final datumOutsideLabelStyle = _getDatumStyle(
element.series.outsideLabelStyleAccessorFn,
datumIndex,
graphicsFactory,
defaultStyle: outsideLabelStyle,
);
// Skip calculation and drawing for this element if no label.
if (label == null || label.isEmpty) {
continue;
}
final arcAngle = element.endAngle - element.startAngle;
final centerAngle = element.startAngle + (arcAngle / 2);
final centerRadius = arcElements.innerRadius +
((arcElements.radius - arcElements.innerRadius) / 2);
final outerPoint = Point<double>(
arcElements.center.x + arcElements.radius * cos(centerAngle),
arcElements.center.y + arcElements.radius * sin(centerAngle),
);
final bounds =
Rectangle<double>.fromPoints(arcElements.center, outerPoint);
// Get space available inside and outside the arc.
final totalPadding = labelPadding * 2;
final insideArcWidth = min(
(((arcAngle * 180 / pi) / 360) * (2 * pi * centerRadius)).round(),
(arcElements.radius - arcElements.innerRadius) - labelPadding,
).round();
final leaderLineLength =
showLeaderLines ? leaderLineStyleSpec.length : 0;
final outsideArcWidth = ((drawBounds.width / 2) -
bounds.width -
totalPadding -
// Half of the leader line is drawn inside the arc
leaderLineLength / 2)
.round();
final labelElement = graphicsFactory.createTextElement(label)
..maxWidthStrategy = MaxWidthStrategy.ellipsize;
final calculatedLabelPosition = calculateLabelPosition(
labelElement,
datumInsideLabelStyle,
insideArcWidth,
outsideArcWidth,
element,
labelPosition,
);
// Set the max width and text style.
if (calculatedLabelPosition == ArcLabelPosition.inside) {
labelElement
..textStyle = datumInsideLabelStyle
..maxWidth = insideArcWidth;
} else {
// calculatedLabelPosition == LabelPosition.outside
labelElement
..textStyle = datumOutsideLabelStyle
..maxWidth = outsideArcWidth;
}
// Only calculate and draw label if there's actually space for the
// label.
if (labelElement.maxWidth! > 0) {
// Calculate the start position of label based on [labelAnchor].
if (calculatedLabelPosition == ArcLabelPosition.inside) {
_drawInsideLabel(canvas, arcElements, labelElement, centerAngle);
} else {
final l = _drawOutsideLabel(
canvas,
drawBounds,
arcElements,
labelElement,
centerAngle,
);
if (l != null) {
updateCollisionDetectionParams(l);
}
}
}
}
}
}