Flutter矢量图SVG的区域填色怎么实现
本文小编为大家详细介绍“Flutter矢量图SVG的区域填色怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“Flutter矢量图SVG的区域填色怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
具体步骤: 1.SVG实际上就是一个xml文件,通过flutter自带的package xml进行进行图层解析 import 'package:xml/xml.dart';
这里是解析的部分代码
Future<void> load() async {
draws.clear();
colors.clear();
actualColors.clear();
String assetName = 'lib/1057.svg';
String svg = await rootBundle.loadString(assetName);
final document = XmlDocument.parse(svg);
final svgRoot = document.rootElement;
Iterable<XmlElement> pathNodes = svgRoot.findAllElements('path');
List<XmlElement> pathNodesList = pathNodes.toList();
RegExp colorRegex = RegExp(r"#w{6}");
for (int i = 0; i < pathNodesList.length; i++) {
XmlElement element = pathNodesList[i];
String? d = element.getAttribute('d');
final Path path = parseSvgPathData(d ?? '');
draws.add(path);
String? style = element.getAttribute('style');
assemblyColor(colorRegex, style);
}
setState(() {});
}
2.绘制到canvas上:解析完成后,就是绘制呀 这里是绘制的代码
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
for (int i = 0; i < draws.length; i++) {
Path path = draws[i];
canvas.drawPath(path, Paint()..color = colors[i]);
}
}
Future<void> onTap(Offset offset) async {
for (int i = 0; i < draws.length; i++) {
Path path = draws[i];
if (path.contains(offset)) {
colors[i] = actualColors[i];
return;
}
}
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
3.容器缩放:绘制完成后,一定要缩放啊 不然小小的多不开心 这里是容器的代码
@override
Widget build(BuildContext context) {
var width = MediaQuery.of(context).size.width;
return InteractiveViewer(
boundaryMargin: const EdgeInsets.all(50),
maxScale: 6,
child: OverflowBox(
child: GestureDetector(
onTapDown: (TapDownDetails details) {
Offset offset = Offset(
details.localPosition.dx / (width / size.width),
details.localPosition.dy / (width / size.width));
_painter.onTap(offset);
setState(() {});
// 在这里处理点击事件
},
child: Container(
color: Colors.white,
width: width,
height: width,
child: Center(
child: Transform.translate(
offset: Offset(
-(size.width - width) / 2.0 * (width / size.width),
-(size.width - width) / 2.0 * (width / size.width)),
child: Transform.scale(
scale: width / size.width,
child: RepaintBoundary(
child: CustomPaint(
isComplex: true,
size: Size(size.width, size.width),
painter: MyPainter(),
),
),
),
),
),
),
),
),
);
}
}
4.动画:如此看来现在点击填充的时候是不是有个动画就更好了?
class _FillWidgetState extends State<FillWidget>
with SingleTickerProviderStateMixin {
@override
void initState() {
_animationController = AnimationController(
duration: const Duration(milliseconds: 500), vsync: this)
..repeat(reverse: true)
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
print("Animation completed");
setState(() {});
} else if (status == AnimationStatus.dismissed) {
print("Animation dismissed");
}
});
_radiusAnimation =
Tween<double>(begin: 0.0, end: 1.0).animate(_animationController);
load();
super.initState();
}
child: AnimatedBuilder(
animation: _animationController,
builder: (BuildContext context, Widget? child) {
return RepaintBoundary(
child: CustomPaint(
key: UniqueKey(),
isComplex: true,
size: Size(size.width, size.width),
painter: _painter,
),
);
},
)
相关内容
这些是最新的
热门排行
- THINKPHP5+GatewayWorker+Workerman 开发在线客服系统
- 在手机浏览器网页中点击链接跳转到微信界面的方法
- 尊云网站目录系统 ThinkPHP5网站分类目录程序 v2.2.221011
- CentOS 7安装shadowsock(一键安装脚本)
- AdminTemplate 基于LayUI 2.4.5实现的网站后台管理模板
- 用NW.js(node-webkit)开发多平台的桌面客户端
- PHP生成随机昵称/用户名
- THINKPHP5网站分类目录程序 尊云网站目录系统
- 织梦(DEDECMS)微信支付接口 微信插件
- 基于LayUI开发的 网站后台管理模板 BeginnerAdmin
- 响应式后台网站模板 - AMA.ADMIN
- layuiAdmin后台管理模板 Iframe版
- LayUI 1.0.9 升级 至 LayUI 2.1.4 方法
- 简洁清爽的会员中心模板
- jQuery幸运大转盘抽奖活动代码