setTargetsForNids method

void setTargetsForNids(
  1. Map<int, double> targets, {
  2. required Duration duration,
  3. required Curve curve,
  4. required bool snap,
})

Re-targets the preview to exactly targets, mapping nid to held offset.

  • A nid whose existing target equals its new target is left UNTOUCHED, so its animation or hold continues. Re-resolving to the same slot must not restart motion.
  • A nid with a different target re-baselines from its CURRENT value (no visual jump).
  • Active nids absent from targets are released toward zero and removed on arrival.
  • snap applies everything instantly (global animations disabled or zero duration) and notifies once so paint refreshes.

Implementation

void setTargetsForNids(
  Map<int, double> targets, {
  required Duration duration,
  required Curve curve,
  required bool snap,
}) {
  if (snap) {
    _entries.clear();
    for (final entry in targets.entries) {
      if (entry.value == 0.0) {
        continue;
      }
      _entries[entry.key] = _PreviewEntry(
        start: entry.value,
        current: entry.value,
        target: entry.value,
        startElapsed: Duration.zero,
        duration: Duration.zero,
        curve: curve,
        done: true,
      );
    }
    _ticker?.stop();
    _onTick();
    return;
  }

  if (_ticker == null || !_ticker!.isActive) {
    _lastTickElapsed = Duration.zero;
  }

  var anyAnimating = false;
  // Retarget / install the requested nids.
  for (final requested in targets.entries) {
    final nid = requested.key;
    final target = requested.value;
    final existing = _entries[nid];
    if (existing != null) {
      if (existing.target == target) {
        if (!existing.done) {
          anyAnimating = true;
        }
        continue;
      }
      existing.start = existing.current;
      existing.target = target;
      existing.startElapsed = _lastTickElapsed;
      existing.duration = duration;
      existing.curve = curve;
      existing.done = false;
      anyAnimating = true;
    } else {
      if (target == 0.0) {
        continue;
      }
      _entries[nid] = _PreviewEntry(
        start: 0.0,
        current: 0.0,
        target: target,
        startElapsed: _lastTickElapsed,
        duration: duration,
        curve: curve,
      );
      anyAnimating = true;
    }
  }
  // Release everything this batch no longer wants.
  final toRemove = <int>[];
  for (final entry in _entries.entries) {
    if (targets.containsKey(entry.key)) {
      continue;
    }
    final e = entry.value;
    if (e.current == 0.0) {
      toRemove.add(entry.key);
      continue;
    }
    if (e.target != 0.0 || e.done) {
      e.start = e.current;
      e.target = 0.0;
      e.startElapsed = _lastTickElapsed;
      e.duration = duration;
      e.curve = curve;
      e.done = false;
    }
    anyAnimating = true;
  }
  for (final nid in toRemove) {
    _entries.remove(nid);
  }

  if (!anyAnimating) {
    return;
  }
  final ticker = _ticker ??= _vsync.createTicker(_onPreviewTick);
  if (!ticker.isActive) {
    ticker.start();
  }
}