getAnimations method
Produces a list of per-character animations for the given progress.
progress ranges from 0.0 (start) to 1.0 (end). The returned list
must have exactly charCount elements.
Implementation
@override
List<CharacterAnimation> getAnimations(double progress, int charCount) {
if (charCount <= 1) return List.filled(charCount, const CharacterAnimation());
final curved = applyCurve(progress);
// Generate drop positions along [0, 1] using deterministic hashing.
final drops = List.generate(dropCount, (i) {
final h = ((seed + i * 7919) * 374761393) & 0x7FFFFFFF;
return (h % 10000) / 10000.0;
});
final charPositions = List.generate(charCount, (i) => charCount > 1 ? i / (charCount - 1) : 0.5);
return List.generate(charCount, (index) {
final charPos = charPositions[index];
// Find distance to nearest drop center.
var minDist = double.infinity;
for (final drop in drops) {
final dist = (charPos - drop).abs();
if (dist < minDist) minDist = dist;
}
// Normalize distance: 0 at drop, 1 at spreadDistance away.
final normalizedDist = (minDist / (spreadDistance / (charCount - 1))).clamp(0.0, 1.0);
// Character is revealed when curved progress exceeds its distance threshold.
final revealT = ((curved - normalizedDist) / (1.0 - normalizedDist)).clamp(0.0, 1.0);
// Scale: ink splatter starts small and grows to full size.
final scale = 0.3 + 0.7 * revealT;
// Opacity: fully opaque after reveal.
final opacity = revealT;
return CharacterAnimation(
opacity: opacity.clamp(0.0, 1.0),
scale: scale,
blurSigma: (1.0 - revealT) * 2.0,
);
});
}