Ответ @Alaric указывает вам на пару пакетов, но не дает никакого обоснования того, почему вы их используете.
Проблема в том, что анимация, о которой вы говоритеумеренно сложен с точки зрения того, как это на самом деле работает.Есть несколько элементов, которые меняются со временем и, возможно, даже становятся одним большим элементом.
Существует два подхода к решению этой проблемы.Первый - использовать внешний инструмент анимации для создания этой анимации, используя любые функции, которые инструмент анимации должен выполнять для изменения и слияния элементов.Затем, когда у вас есть анимация, которая работает к вашему удовольствию, вы должны как-то импортировать ее в свой проект.Вот тут-то и появляются плагины fluttie и flare_flutter - если вы использовали Aftereffects, вы используете Lottie для экспорта файла, а затем плагин fluttie для его отображения.Flare немного проще, так как он предназначен для флаттера, но вы все равно создаете анимацию извне, а затем добавляете файл в ваши активы для рендеринга.
Другой подход - сделать анимацию самостоятельно.Это влечет за собой три вещи:
- Создание виджета, содержащего анимацию.
- Создание CustomPainter для фактического рисования результата.
- Дополнительно, другой класс, который действует как контроллер для запуска / остановки / и т. Д. Анимации.
Виджет, содержащий анимацию, может также быть контроллером, если вы используете GlobalKey для доступаэто и выставить методы запуска / остановки, но это немного грязно.Лучше иметь внешний объект, который является контроллером - и вы могли бы даже использовать AnimationController как есть, хотя он был бы менее «чистым».
Если вы не передадите его, вы бывероятно, в вашем виджете есть AnimationController, который вы запускаете и останавливаете из своего контроллера или класса.По сути, он будет просто переходить от 0 к 1 и обратно и будет отвечать за перестройку CustomPainter (возможно, с использованием AnimatedBuilder).
Это очень простой пример, которому не нужен внешний контроллер в качестве жестаобнаружение происходит внутри виджета.Обратите внимание, что я не вызываю setState каждый раз, когда задан элемент «begin», потому что на самом деле я не хочу, чтобы он перестраивался при его изменении.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: StartStop(),
),
),
);
}
}
class StartStop extends StatefulWidget {
@override
StartStopState createState() {
return new StartStopState();
}
}
class StartStopState extends State<StartStop> with TickerProviderStateMixin<StartStop> {
bool started = false;
AnimationController animationController;
@override
void initState() {
animationController = AnimationController(vsync: this, duration: Duration(milliseconds: 300));
super.initState();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
started ? animationController.forward() : animationController.reverse();
started = !started;
},
child: SizedBox(
width: 100,
height: 100,
child: AnimatedBuilder(
animation: animationController,
builder: (context, child) {
return CustomPaint(
painter: StartStopPainter(animationController.value),
size: Size.infinite,
child: child,
);
},
),
),
);
}
}
class StartStopPainter extends CustomPainter {
final double percentAnimated;
StartStopPainter(this.percentAnimated) : assert(percentAnimated >= 0 && percentAnimated <= 1);
@override
void paint(Canvas canvas, Size size) {
var pausePaint = Paint()..color = Colors.black.withOpacity(1 - percentAnimated);
canvas.drawRect(Rect.fromLTRB(20, 10, 40, 90), pausePaint);
canvas.drawRect(Rect.fromLTRB(60, 10, 80, 90), pausePaint);
var playPaint = Paint()..color = Colors.black.withOpacity(percentAnimated);
canvas.drawPath(Path()..addPolygon([Offset(20, 10), Offset(20, 90), Offset(80, 50)], true), playPaint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
Я оставлю фактическую пользовательскую частьанимация (где вы делаете прямоугольник изменится на треугольник и т. д.) для вас.Вместо того, чтобы использовать непрозрачность и несколько различных вызовов рисования, вы просто использовали бы ввод percentAnimated
, чтобы решить, какой путь или многоугольник рисовать.