Реалізація анімації чарта/графіка у мобільних додатках
Статичний графік — це просто дані. Анімований — це історія. Коли стовпці в bar chart піднімаються знизу вверх послідовно, а лінія на line chart «малюється» зліва направо при завантаженні екрана, користувач проходить разом із даними, а не просто читає цифри. Але за цим ефектом стоїть нетривіальна технічна робота.
Підходи до реалізації
Перше питання: використовувати готову бібліотеку чи писати на Canvas/Core Graphics?
Бібліотеки:
- iOS: Charts (DGCharts), SwiftCharts (native, iOS 16+)
- Android: MPAndroidChart, Vico
- Flutter: fl_chart, syncfusion_flutter_charts
- React Native: Victory Native, react-native-chart-kit
Бібліотеки дають 80% потрібного за 20% часу, але кастомізація анімації обмежена. MPAndroidChart підтримує animateX() та animateY(), але налаштувати easing per-bar чи stagger-анімацію (стовпці з'являються поочерідно) — неможливо без кастомного Renderer.
Кастомна реалізація на Canvas потрібна коли: нестандартний тип чарта, stagger-ефект, анімація окремих точок по даних, інтерактивний tooltip з анімацією.
Stagger animation для bar chart
На Flutter через AnimationController + Interval:
// Кожен стовпець анімується з затримкою 80мс
for (int i = 0; i < bars.length; i++) {
final start = (i * 0.08).clamp(0.0, 1.0);
final end = (start + 0.4).clamp(0.0, 1.0);
animations[i] = Tween(begin: 0.0, end: bars[i].value).animate(
CurvedAnimation(
parent: controller,
curve: Interval(start, end, curve: Curves.easeOutCubic),
),
);
}
На iOS через CAKeyframeAnimation з keyTimes — кожен CAShapeLayer (один стовпець) отримує смущений beginTime:
bars.enumerated().forEach { index, layer in
let anim = CABasicAnimation(keyPath: "bounds.size.height")
anim.beginTime = CACurrentMediaTime() + Double(index) * 0.08
anim.duration = 0.4
anim.timingFunction = CAMediaTimingFunction(name: .easeOut)
layer.add(anim, forKey: nil)
}
Анімація line chart: strokeEnd
Line chart малюється через CAShapeLayer з strokeEnd: 0 → 1. Для додавання точок-маркерів, які з'являються в момент прохождення «кисті» — потрібно синхронізувати появу CALayer з прогресом strokeEnd. Реалізуємо через CAAnimationDelegate.animationDidStop для кожного сегмента або через displayLink з відстеженням presentation().strokeEnd.
Інтерактивний tooltip
Tooltip, що слідує за пальцем по графіку — окремо завдання. На iOS: UIGestureRecognizer → пересчет координати в значення даних → UIView.animate для tooltip. Важливо використовувати setNeedsDisplay() тільки для тієї частини CALayer, де малюється highlight-лінія — перерисовка всього canvas вбиває FPS при швидкому русі пальця.
Процес роботи
Отримуємо формат даних та Figma-дизайн чарта. Визначаємо тип реалізації: бібліотека чи кастомний Canvas. Реалізуємо базовий рендер → додаємо анімацію появи → тестуємо продуктивність через Instruments / Android Profiler (ціль: 60fps при будь-якому розмірі датасету). При великому обʼємі даних (500+ точок) обов'язково застосовуємо downsampling алгоритм Ramer–Douglas–Peucker.
Терміни: 1–3 дні залежно від типу та складності чарта.







