update method
Generates rendering data needed to paint the data on the chart.
This is called during the post layout phase of the chart draw cycle.
Implementation
@override
void update(List<ImmutableSeries<D>> seriesList, bool isAnimatingThisDraw) {
_currentKeys.clear();
_currentGroupsStackKeys.clear();
final orderedSeriesList = getOrderedSeriesList(seriesList);
for (final series in orderedSeriesList) {
final domainAxis = series.getAttr(domainAxisKey)! as ImmutableAxis<D>;
final domainFn = series.domainFn;
final measureAxis = series.getAttr(measureAxisKey)! as ImmutableAxis<num>;
final measureFn = series.measureFn;
final colorFn = series.colorFn;
final dashPatternFn = series.dashPatternFn;
final fillColorFn = series.fillColorFn;
final seriesStackKey = series.getAttr(stackKeyKey);
final barGroupCount = series.getAttr(barGroupCountKey);
final barGroupIndex = series.getAttr(barGroupIndexKey);
final previousBarGroupWeight = series.getAttr(previousBarGroupWeightKey);
final barGroupWeight = series.getAttr(barGroupWeightKey);
final allBarGroupWeights = series.getAttr(allBarGroupWeightsKey);
final measureAxisPosition = measureAxis.getLocation(0.0);
final elementsList = series.getAttr(barElementsKey);
// Save off domainAxis for getNearest.
_prevDomainAxis = domainAxis;
for (var barIndex = 0; barIndex < series.data.length; barIndex++) {
final Object? datum = series.data[barIndex];
final details = elementsList![barIndex];
final domainValue = domainFn(barIndex);
final measureValue = measureFn(barIndex);
// TODO: remove this explicit `bool` type when no longer
// needed to work around
// https://github.com/dart-lang/language/issues/1785
final measureIsNull = measureValue == null;
final measureIsNegative = !measureIsNull && measureValue < 0;
// Each bar should be stored in barStackMap in a structure that mirrors
// the visual rendering of the bars. Thus, they should be grouped by
// domain value, series category (by way of the stack keys that were
// generated for each series in the preprocess step), and bar group
// index to account for all combinations of grouping and stacking.
final barStackMapKey = '$domainValue'
'__'
'$seriesStackKey'
'__'
'${measureIsNegative ? 'pos' : 'neg'}'
'__'
'$barGroupIndex';
final barKey = '$barStackMapKey${details.barStackIndex}';
final barStackList = _barStackMap.putIfAbsent(barStackMapKey, () => []);
// If we already have an AnimatingBar for that index, use it.
var animatingBar =
barStackList.firstWhereOrNull((bar) => bar.key == barKey);
// If we don't have any existing bar element, create a new bar and have
// it animate in from the domain axis.
// TODO: Animate bars in the middle of a stack from their
// nearest neighbors, instead of the measure axis.
if (animatingBar == null) {
// If the measure is null and there was no existing animating bar, it
// means we don't need to draw this bar at all.
if (!measureIsNull) {
animatingBar = makeAnimatedBar(
key: barKey,
series: series,
datum: datum,
barGroupIndex: barGroupIndex!,
previousBarGroupWeight: previousBarGroupWeight,
barGroupWeight: barGroupWeight,
allBarGroupWeights: allBarGroupWeights,
color: colorFn!(barIndex),
dashPattern: dashPatternFn!(barIndex),
details: details as R,
domainValue: domainFn(barIndex),
domainAxis: domainAxis,
domainWidth: domainAxis.rangeBand.round(),
fillColor: fillColorFn!(barIndex),
fillPattern: details.fillPattern,
measureValue: 0.0,
measureOffsetValue: 0.0,
measureAxisPosition: measureAxisPosition,
measureAxis: measureAxis,
numBarGroups: barGroupCount!,
strokeWidthPx: details.strokeWidthPx,
measureIsNull: measureIsNull,
measureIsNegative: measureIsNegative,
);
barStackList.add(animatingBar);
}
} else {
animatingBar
..datum = datum
..series = series
..domainValue = domainValue;
}
if (animatingBar == null) {
continue;
}
// Update the set of bars that still exist in the series data.
_currentKeys.add(barKey);
// Store off stack keys for each bar group to help getNearest identify
// groups of stacks.
_currentGroupsStackKeys
.putIfAbsent(domainValue, () => <String>{})
.add(barStackMapKey);
// Get the barElement we are going to setup.
// Optimization to prevent allocation in non-animating case.
final BaseBarRendererElement barElement = makeBarRendererElement(
barGroupIndex: barGroupIndex!,
previousBarGroupWeight: previousBarGroupWeight,
barGroupWeight: barGroupWeight,
allBarGroupWeights: allBarGroupWeights,
color: colorFn!(barIndex),
dashPattern: dashPatternFn!(barIndex),
details: details as R,
domainValue: domainFn(barIndex),
domainAxis: domainAxis,
domainWidth: domainAxis.rangeBand.round(),
fillColor: fillColorFn!(barIndex),
fillPattern: details.fillPattern,
measureValue: measureValue,
measureOffsetValue: details.measureOffset!,
measureAxisPosition: measureAxisPosition,
measureAxis: measureAxis,
numBarGroups: barGroupCount!,
strokeWidthPx: details.strokeWidthPx,
measureIsNull: measureIsNull,
measureIsNegative: measureIsNegative,
);
animatingBar.setNewTarget(barElement as R);
}
}
// Animate out bars that don't exist anymore.
_barStackMap.forEach((key, barStackList) {
for (var barIndex = 0; barIndex < barStackList.length; barIndex++) {
final bar = barStackList[barIndex];
if (!_currentKeys.contains(bar.key)) {
bar.animateOut();
}
}
});
}