Ми не раз бачили, як замовник приносить макет із діаграмою, де стовпці злітають один за одним, а лінія вимальовується наче рукою художника. На перший погляд — проста анімація. Але коли доходить до коду, з'ясовується, що готова бібліотека не вміє такого stagger-ефекту, а кастомна реалізація на Canvas потребує глибокого розуміння Core Animation або Android Canvas API. Ми беремося за такі задачі та за 1-3 дні впроваджуємо анімацію будь-якого рівня складності, будь то bar chart, line chart або кругова діаграма. У цій статті розберемо типові проблеми та способи їх вирішення.
Перед тим як обрати бібліотеку або писати з нуля, важливо розуміти, які анімації потрібні: просте з'явлення чи послідовний stagger, підтримка touch-подій та tooltip, робота з великими даними (500+ точок) без просідання FPS. Ми використовуємо профілювання (Instruments, Android Profiler) на кожному етапі, щоб гарантувати 60fps.
Як обрати між бібліотекою та кастомним Canvas?
Вибір між готовою бібліотекою та кастомною реалізацією — ключове рішення. Бібліотеки на зразок MPAndroidChart або Swift Charts дають 80% потрібного за 20% часу, але кастомізація анімації в них обмежена. Наприклад, MPAndroidChart підтримує animateX() і animateY(), але налаштувати easing per-bar або зробити stagger-анімацію (стовпці з'являються по черзі) — не можна без кастомного Renderer. Кастомний Canvas виправданий, коли потрібен нестандартний тип чарту, stagger-ефект, анімація окремих точок або інтерактивний tooltip.
| Критерій | Бібліотека (MPAndroidChart, Swift Charts) | Кастомний Canvas |
|---|---|---|
| Час реалізації | Години | 1-3 дні |
| Кастомізація анімації | Обмежена (easing, stagger) | Повна (будь-яка крива, затримки) |
| Продуктивність 500+ точок | Середня (можливі лаги) | Висока (downsampling + LOD) |
| Підтримка жестів | Вбудована (неглибока) | Налаштовувана (будь-яка логіка) |
Чому stagger-анімація важлива для сприйняття даних?
Stagger-анімація (почергова поява елементів) привертає увагу до кожного стовпця або точки, роблячи дані більш читабельними. Кастомна реалізація на Canvas дає в 3 рази більше контролю над анімацією порівняно з готовими бібліотеками, що критично для складних дашбордів. Ми реалізували її на 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 анімується через CAShapeLayer з strokeEnd: 0 → 1. Для додавання точок-маркерів, які з'являються в момент проходження «пензля», потрібно синхронізувати появу CALayer з прогресом strokeEnd. Реалізуємо через CAAnimationDelegate.animationDidStop для кожного сегмента або через displayLink з відстеженням presentation().strokeEnd.
Інтерактивний tooltip: як не втратити FPS
Tooltip, що слідує за пальцем по графіку — окрема задача. На iOS: UIGestureRecognizer → перерахунок координати в значення даних → UIView.animate для tooltip. Важно використовувати setNeedsDisplay() лише для тієї частини CALayer, де малюється highlight-лінія — перемальовка всього canvas вбиває FPS при швидкому русі пальця. Ми гарантуємо 60fps навіть при інтенсивній взаємодії завдяки інкрементальному рендерингу.
Що входить в роботу
- Вихідний код анімованого компонента на Swift/Kotlin/Dart/TypeScript
- Документація з кастомізації (кольори, шрифти, параметри анімації)
- Інтеграція в існуючий проєкт та налаштування тестового оточення
- Оптимізація продуктивності (downsampling для наборів >500 точок, LOD)
- Гарантія 60fps на пристроях середнього сегменту
Ми розробляємо мобільні застосунки більше 5 років та реалізували понад 15 проєктів з анімованою графікою (фінтех, аналітичні дашборди). Для роботи використовуємо сучасний стек: SwiftUI + Combine, Jetpack Compose + Coroutines, Flutter 3.x. Рекомендації Apple з анімації: використовуйте CAMediaTiming для синхронізації.
Як реалізувати stagger-анімацію за 4 кроки
- Ініціалізуйте
AnimationController(абоCADisplayLink). - Створіть масив затримок:
delay = index * intervalTime. - Для кожного елемента застосуйте анімацію
TweenзCurvedAnimationтаInterval. - Запустіть загальний контролер — елементи почнуть анімуватися послідовно.
Що таке downsampling і навіщо він потрібен?
Downsampling (проріджування точок) застосовується при відмальовці великих наборів даних (500+ точок) для збереження 60fps. [Алгоритм Рамера–Дугласа–Пекера](https://ru.wikipedia.org/wiki/Алгоритм_Рамера_—_Дугласа_—_Пекера) видаляє точки, що лежать на прямій в межах заданого епсилон, зберігаючи візуальну форму графіка.| Платформа | Механізм анімації | Ключові класи |
|---|---|---|
| iOS | Core Animation (CALayer) | CABasicAnimation, CAKeyframeAnimation |
| Android | Canvas + ValueAnimator | ValueAnimator, ObjectAnimator |
| Flutter | AnimationController + Tween | AnimationController, Tween, Interval |
| React Native | Animated API | Animated.Value, Animated.timing |
Зв'яжіться з нами, щоб обговорити ваш графік — оцінимо проєкт безкоштовно. Замовте розробку анімації графіка під ключ.







