Flutter动画线条插件animated_lines的使用
Flutter动画线条插件animated_lines的使用
使用说明
animated_lines
插件可以绘制动画曲线和直线。它支持创建不同样式的线条,并且可以配置动画效果。
创建一个曲线线条
var curvedLine = LineInfo(
source: Offset.zero,
destination: const Offset(100, 100),
backgroundLineColor: Colors.black,
progressLineColor: Colors.lightGreen,
lineStyle: LineStyle.curved(),
strokeStyle: StrokeStyle.dashed(),
animationCount: 4,
);
创建一条直线
var straightLine = LineInfo(
source: Offset.zero,
destination: const Offset(100, 100),
backgroundLineColor: Colors.black,
progressLineColor: Colors.lightGreen,
lineStyle: LineStyle.straight(),
strokeStyle: StrokeStyle.dashed(),
animationCount: 4,
);
设置虚线样式
var strokeStyle = StrokeStyle.dashed(gapLength: 5, dashLength: 5);
gapLength
和 dashLength
都是可选参数。
设置实线样式
var strokeStyle = StrokeStyle.plain();
设置直线样式
var lineStyle = LineStyle.straight();
设置曲线样式
var lineStyle = LineStyle.curved(radius: 100, isClockwise: true);
radius
和 isClockwise
都是可选参数。
动画进度控制
line.animate();
如果在创建线条对象时将 animationCount
设为小于 0 的值,则表示动画将无限循环。
停止动画
line.stopAnimation();
重置动画
line.resetAnimation();
监听动画结束事件
line.onAnimationComplete = () {
// TODO: 执行动画结束后的代码
};
更新线条信息
line.update(
source: const Offset(2, 5),
backgroundLineColor: Colors.blue,
progress: 0.2,
);
完整示例
import 'dart:math';
import 'package:animated_lines/animated_lines.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Animated Line Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const AnimatedLinesExample(title: 'Animated Line Example'),
);
}
}
class AnimatedLinesExample extends StatefulWidget {
final String title;
const AnimatedLinesExample({
Key? key,
required this.title,
}) : super(key: key);
[@override](/user/override)
State<AnimatedLinesExample> createState() => _AnimatedLinesExampleState();
}
class _AnimatedLinesExampleState extends State<AnimatedLinesExample> with TickerProviderStateMixin {
bool _arePointsInitialized = false;
final List<LineInfo> _lines = [];
late double _maxRadius;
late double _containerWidth;
late double _containerHeight;
late Offset _profilePoint;
late Offset _groceryPoint;
late Offset _homePoint;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
onPressed: () {
for (var e in _lines) {
e.animate();
}
},
child: const Text("Animate"),
),
TextButton(
onPressed: () {
for (var e in _lines) {
e.stopAnimation();
}
},
child: const Text("Stop Animation"),
),
],
),
Expanded(
child: LayoutBuilder(
builder: (p0, p1) {
_containerWidth = p1.maxWidth;
_containerHeight = p1.maxHeight;
_initializeObjects(_containerWidth, _containerHeight);
return AnimatedLinesContainer(
lines: _lines,
child: !_arePointsInitialized
? Container()
: Stack(
children: [
_profileIcon(),
_groceryIcon(),
_homeIcon(),
],
),
);
},
),
),
],
),
);
}
Widget _profileIcon() {
return Positioned(
top: _profilePoint.dy,
left: _profilePoint.dx,
child: Transform.translate(
offset: const Offset(-30, -60),
child: Image.asset(
"assets/profile.png",
width: 60,
),
),
);
}
Widget _groceryIcon() {
return Positioned(
top: _groceryPoint.dy,
left: _groceryPoint.dx,
child: Transform.translate(
offset: const Offset(-30, -60),
child: Image.asset(
"assets/grocery.png",
width: 60,
),
),
);
}
Widget _homeIcon() {
return Positioned(
top: _homePoint.dy,
left: _homePoint.dx,
child: Transform.translate(
offset: const Offset(-30, 0),
child: Image.asset(
"assets/house.png",
width: 60,
),
),
);
}
void _initializeObjects(double width, double height) {
if (!_arePointsInitialized) {
Offset center = Offset(width / 2, height / 2);
_maxRadius = sqrt(pow(MediaQuery.of(context).size.width, 2) + pow(MediaQuery.of(context).size.height, 2)) * 0.2;
_profilePoint = center + Offset(-width / 4, -height / 8);
_groceryPoint = center + Offset(width / 4, -height / 8);
_homePoint = center + Offset(0, height / 8);
_createLines();
_arePointsInitialized = true;
}
}
void _createLines() {
// 创建一条虚线直线,从家到个人资料
const straightLineBottomLeftGap = Offset(-10, 0);
const straightLineTopLeftGap = Offset(-10, 5);
_lines.add(LineInfo(
source: _homePoint + straightLineBottomLeftGap,
destination: _profilePoint + straightLineTopLeftGap,
progressLineColor: Colors.green,
lineStyle: LineStyle.straight(),
strokeStyle: StrokeStyle.dashed(),
animationCount: 4,
onAnimationComplete: () {
debugPrint("Animation Complete for line between Home and Profile");
},
));
// 创建一条带虚线样式的曲线,从个人资料到杂货店
const curvedLineTopLeftGap = Offset(10, -5);
const curvedLineTopRightGap = Offset(-10, -5);
_lines.add(LineInfo(
source: _profilePoint + curvedLineTopLeftGap,
destination: _groceryPoint + curvedLineTopRightGap,
progressLineColor: Colors.lightGreen,
lineStyle: LineStyle.curved(radius: _maxRadius),
strokeStyle: StrokeStyle.dashed(
dashLength: 10,
gapLength: 5,
),
));
// 创建一条实线曲线,从杂货店到个人资料
const curvedLineBottomRightGap = Offset(-10, 5);
const curvedLineBottomLeftGap = Offset(10, 5);
_lines.add(LineInfo(
source: _groceryPoint + curvedLineBottomRightGap,
destination: _profilePoint + curvedLineBottomLeftGap,
progressLineColor: Colors.pink,
lineStyle: LineStyle.curved(radius: _maxRadius),
strokeStyle: StrokeStyle.plain(),
));
// 创建一条实线直线,从杂货店到家
const straightLineBottomRightGap = Offset(10, 0);
const straightLineTopRightGap = Offset(5, 5);
_lines.add(LineInfo(
source: _groceryPoint + straightLineTopRightGap,
destination: _homePoint + straightLineBottomRightGap,
progressLineColor: Colors.lightBlue,
lineStyle: LineStyle.straight(),
strokeStyle: StrokeStyle.plain(),
));
}
}
更多关于Flutter动画线条插件animated_lines的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter动画线条插件animated_lines的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于Flutter动画线条插件animated_lines
的使用,下面是一个简单的代码示例,展示了如何集成和使用这个插件来创建动画线条效果。
首先,确保你已经在pubspec.yaml
文件中添加了animated_lines
依赖项:
dependencies:
flutter:
sdk: flutter
animated_lines: ^最新版本号 # 请替换为实际最新版本号
然后运行flutter pub get
来安装依赖。
接下来,你可以在你的Flutter应用中这样使用animated_lines
插件:
import 'package:flutter/material.dart';
import 'package:animated_lines/animated_lines.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Animated Lines Demo'),
),
body: Center(
child: AnimatedLinesExample(),
),
),
);
}
}
class AnimatedLinesExample extends StatefulWidget {
@override
_AnimatedLinesExampleState createState() => _AnimatedLinesExampleState();
}
class _AnimatedLinesExampleState extends State<AnimatedLinesExample> with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
)..repeat(reverse: true);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
child: Container(
height: 200,
width: 200,
color: Colors.transparent,
),
builder: (context, child) {
return Stack(
children: [
// 背景容器
Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(10),
),
),
// 动画线条
AnimatedLines(
lines: [
Line(
start: Offset(50, 50),
end: Offset(150, 150),
color: Colors.blue,
strokeWidth: 2,
animationValue: _controller.value,
),
Line(
start: Offset(150, 50),
end: Offset(50, 150),
color: Colors.red,
strokeWidth: 2,
animationValue: _controller.value,
),
],
),
],
);
},
);
}
}
class Line {
final Offset start;
final Offset end;
final Color color;
final double strokeWidth;
final double animationValue;
Line({
required this.start,
required this.end,
required this.color,
required this.strokeWidth,
required this.animationValue,
});
}
注意:上面的代码是一个示例,其中Line
类并不是animated_lines
插件的一部分,而是为了方便说明而创建的。在实际使用中,你可能需要根据animated_lines
插件的具体API来调整代码。由于animated_lines
插件的API可能会有所不同,请参考其官方文档来获取最新的API信息。
另外,如果animated_lines
插件提供了自定义线条动画的API,你可能需要将Line
类的属性映射到该API上。上面的代码主要是为了展示如何结合AnimationController
和自定义动画效果。
如果animated_lines
插件的API有所不同,你可能需要查阅其官方文档或示例代码来获取正确的使用方法。