update method

  1. @override
void update(
  1. List<ImmutableSeries<D>> seriesList,
  2. bool isAnimatingThisDraw
)
inherited

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 (var 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);

    var 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 bool 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.
      var barStackMapKey = '$domainValue'
          '__'
          '$seriesStackKey'
          '__'
          '${measureIsNegative ? 'pos' : 'neg'}'
          '__'
          '$barGroupIndex';

      var barKey = '$barStackMapKey${details.barStackIndex}';

      var barStackList = _barStackMap.putIfAbsent(barStackMapKey, () => []);

      // If we already have an AnimatingBarfor that index, use it.
      var animatingBar =
          barStackList.firstWhereOrNull((B 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.
      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((String key, List<B> barStackList) {
    for (var barIndex = 0; barIndex < barStackList.length; barIndex++) {
      final bar = barStackList[barIndex];
      if (_currentKeys.contains(bar.key) != true) {
        bar.animateOut();
      }
    }
  });
}