Flutter动画路径插件animated_flight_paths的使用
Flutter动画路径插件animated_flight_paths的使用
Features
- 地图投影:包括墨卡托(Mercator)和罗宾逊(Robinson)世界地图投影。
- 或者设置任何自定义地图或其他背景。
- 自定义飞行路径:多种选项用于自定义飞行路径的颜色和动画曲线。
- 确定地图上的点:使用
debugShowOffsetOnTap
然后点击或点击来确定地图上的点。
Quick Start
示例代码
import 'package:animated_flight_paths/animated_flight_paths.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Animated Flight Paths Example',
debugShowCheckedModeBanner: false,
home: AnimatedFlightPathsExample(),
);
}
}
class AnimatedFlightPathsExample extends StatefulWidget {
const AnimatedFlightPathsExample({super.key});
@override
State<AnimatedFlightPathsExample> createState() =>
_AnimatedFlightPathsExampleState();
}
class _AnimatedFlightPathsExampleState extends State<AnimatedFlightPathsExample>
with SingleTickerProviderStateMixin {
late AnimationController controller;
@override
void initState() {
super.initState();
controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 12),
)..repeat();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: const EdgeInsets.all(32),
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
stops: [0.4, 1],
colors: [Color(0xFF27163e), Color(0xFF432a72)],
),
),
child: ListView(
children: [
Center(child: _title),
const SizedBox(height: 24),
Center(child: _animatedFlightPaths),
],
),
),
);
}
Widget get _title => AutoSizeText(
'AnimatedFlightPaths',
maxLines: 1,
style: GoogleFonts.righteous(
fontSize: 56,
foreground: Paint()
..style = PaintingStyle.stroke
..strokeWidth = 2
..color = SynthwaveColors.blue,
),
);
Widget get _animatedFlightPaths => AnimatedFlightPaths(
controller: controller,
debugShowOffsetOnTap: false,
flightSchedule: FlightSchedule(
start: DateTime.parse('2023-01-01 00:00:00'),
end: DateTime.parse('2023-01-01 23:59:00'),
flights: flights,
),
options: const FlightPathOptions(
showLabels: true,
fromEndpointColor: SynthwaveColors.yellow,
toEndpointColor: SynthwaveColors.yellow,
flightPathColor: SynthwaveColors.yellow,
fromEndpointCurve: Curves.easeInOut,
flightPathCurve: Curves.easeInOutSine,
toEndpointCurve: Curves.easeInOut,
flightPathStrokeWidth: 2,
endpointRadius: 5,
endpointToLabelSpacing: 12,
endpointDotAlwaysVisible: false,
endpointLabelAlwaysVisible: false,
keepFlightPathsVisible: false,
curveDepth: 0.5,
endpointWeight: 0.2,
),
child: const MapSvg(
map: FlightMap.worldMercatorProjection,
outlineColor: SynthwaveColors.pink,
fillColor: SynthwaveColors.black,
),
);
}
final flights = <Flight>[
Flight(
from: Cities.paris,
to: Cities.tokyo,
departureTime: DateTime.parse('2023-01-01 00:00:00'),
arrivalTime: DateTime.parse('2023-01-01 14:00:00'),
),
Flight(
from: Cities.sydney,
to: Cities.capeTown,
departureTime: DateTime.parse('2023-01-01 00:00:00'),
arrivalTime: DateTime.parse('2023-01-01 18:00:00'),
),
Flight(
from: Cities.buenosAires,
to: Cities.losAngeles,
departureTime: DateTime.parse('2023-01-01 06:00:00'),
arrivalTime: DateTime.parse('2023-01-01 21:00:00'),
),
Flight(
from: Cities.newYork,
to: Cities.london,
departureTime: DateTime.parse('2023-01-01 16:00:00'),
arrivalTime: DateTime.parse('2023-01-01 23:00:00'),
),
Flight(
from: Cities.cairo,
to: Cities.london,
departureTime: DateTime.parse('2023-01-01 17:00:00'),
arrivalTime: DateTime.parse('2023-01-01 23:00:00'),
),
Flight(
from: Cities.bangkok,
to: Cities.london,
departureTime: DateTime.parse('2023-01-01 10:00:00'),
arrivalTime: DateTime.parse('2023-01-01 23:00:00'),
),
];
abstract class Cities {
static final bangkok = FlightEndpoint(
offset: const Offset(75, 65),
label: const Label(text: 'Bangkok'),
);
static final buenosAires = FlightEndpoint(
offset: const Offset(32, 87),
label: const Label(text: 'Buenos Aires'),
);
static final cairo = FlightEndpoint(
offset: const Offset(56, 58),
label: const Label(text: 'Cairo'),
);
static final capeTown = FlightEndpoint(
offset: const Offset(53.5, 86),
label: const Label(text: 'Cape Town'),
);
static final losAngeles = FlightEndpoint(
offset: const Offset(16, 54),
label: const Label(text: 'Los Angeles'),
);
static final london = FlightEndpoint(
offset: const Offset(48, 45),
label: const Label(text: 'London'),
);
static final newYork = FlightEndpoint(
offset: const Offset(28, 51),
label: const Label(text: 'New York'),
);
static final paris = FlightEndpoint(
offset: const Offset(49, 48),
label: const Label(text: 'Paris'),
);
static final sydney = FlightEndpoint(
offset: const Offset(89, 87),
label: const Label(text: 'Sydney'),
);
static final tokyo = FlightEndpoint(
offset: const Offset(86, 54),
label: const Label(text: 'Tokyo'),
);
}
abstract class SynthwaveColors {
static const pink = Color(0xFFeb2bb2);
static const yellow = Color(0xFFfdfe43);
static const blue = Color(0xFF74f7ff);
static const black = Color(0xFF201130);
}
class Label extends StatelessWidget {
const Label({super.key, required this.text});
final String text;
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: SynthwaveColors.black,
border: Border.all(color: SynthwaveColors.blue, width: 2),
borderRadius: BorderRadius.circular(32),
),
child: Text(
text,
style: GoogleFonts.righteous(color: SynthwaveColors.blue, fontSize: 14),
),
);
}
}
确定飞行终点坐标
要确定地图上的点,可以使用 debugShowOffsetOnTap
属性。运行应用并点击或点击任何位置,会显示一个 📍 和一个带有该位置坐标的提示框。使用箭头键 [↑ ↓ → ←] 微调 📍 的位置。
AnimatedFlightPaths(
controller: controller,
debugShowOffsetOnTap: true, // 设置为 true
flightSchedule: FlightSchedule(
start: DateTime.parse('2023-01-01 00:00:00'),
end: DateTime.parse('2023-01-01 23:59:00'),
flights: <Flight>[],
),
);
在截图中,提示框显示的是 (21.99, 52.79),这是 Kansas City 的坐标。我们可以用这些坐标创建一个新的 FlightEndpoint
:
abstract class Cities {
static final kansasCity = FlightEndpoint(
offset: const Offset(21.99, 52.79),
label: const Text('Kansas City'),
);
}
现在可以在任何飞行路径中使用这个终点。
✈️ Bon Voyage!!
更多关于Flutter动画路径插件animated_flight_paths的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter动画路径插件animated_flight_paths的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter中使用animated_flight_paths
插件来创建动画路径的一个示例。这个插件允许你定义和渲染复杂的路径动画,非常适合展示飞行路线或任何需要沿路径移动的动画。
首先,确保你已经在pubspec.yaml
文件中添加了animated_flight_paths
依赖:
dependencies:
flutter:
sdk: flutter
animated_flight_paths: ^最新版本号 # 请替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,在你的Dart文件中(例如main.dart
),你可以按照以下步骤来创建和使用动画路径:
import 'package:flutter/material.dart';
import 'package:animated_flight_paths/animated_flight_paths.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Animated Flight Paths Demo'),
),
body: Center(
child: AnimatedFlightPathsDemo(),
),
),
);
}
}
class AnimatedFlightPathsDemo extends StatefulWidget {
@override
_AnimatedFlightPathsDemoState createState() => _AnimatedFlightPathsDemoState();
}
class _AnimatedFlightPathsDemoState extends State<AnimatedFlightPathsDemo> with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 5),
vsync: this,
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final path = Path()
..moveTo(50, 150)
..quadraticBezierTo(100, 100, 150, 150)
..lineTo(250, 150)
..cubicTo(300, 100, 350, 200, 400, 150);
return AnimatedFlightPaths(
points: [
FlightPathPoint(
path: path,
offset: 0.0,
child: Container(
width: 20,
height: 20,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.blue,
),
),
),
],
controller: _controller,
);
}
}
在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个AnimatedFlightPaths
组件。这个组件接受一个FlightPathPoint
列表,每个FlightPathPoint
定义了一个路径和在该路径上的一个子组件(在这个例子中是一个蓝色的圆形)。
- 定义路径:我们使用
Path
类来定义一个二次贝塞尔曲线和一个三次贝塞尔曲线的组合路径。 - 创建动画控制器:我们使用
AnimationController
来控制动画的时长和同步。 - 使用
AnimatedFlightPaths
:我们将路径和动画控制器传递给AnimatedFlightPaths
,并将一个带有蓝色圆形的FlightPathPoint
添加到路径点列表中。
运行这个应用,你将看到一个蓝色圆形沿着定义的路径移动。你可以根据需要调整路径和动画属性,以创建更复杂和有趣的动画效果。