Flutter學(xué)習(xí)之矢量圖SVG的區(qū)域填色示例詳解
請(qǐng)先看效果

具體步驟: 1.SVG實(shí)際上就是一個(gè)xml文件,通過flutter自帶的package xml進(jìn)行進(jìn)行圖層解析 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(() {});
// 在這里處理點(diǎn)擊事件
},
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.動(dòng)畫:如此看來現(xiàn)在點(diǎn)擊填充的時(shí)候是不是有個(gè)動(dòng)畫就更好了?
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,
),
);
},
)
再次看效果

這樣就可以實(shí)現(xiàn)一個(gè)填色小應(yīng)用啦~代碼粗糙有待優(yōu)化 提供的是思路 自行修改 好了 能力有限就寫這么多啦~更多關(guān)于Flutter矢量圖SVG區(qū)域填色的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
AndroidView與Compose框架交互實(shí)現(xiàn)介紹
Android Compose自推出正式版本后,google 就一直推薦使用Compose來開發(fā)。正好疫情期間,作為一個(gè) Android 摸魚達(dá)人,就來摸索一下Compose的開發(fā)。說實(shí)話開發(fā)了2天感覺對(duì)Android 開發(fā)人員來說變化是巨大的,但是作為從業(yè)者我們還必須學(xué)習(xí)和學(xué)會(huì),才能不被甩開2022-09-09
Flutter onTap中讓你脫穎而出的5條規(guī)則
這篇文章主要為大家介紹了Flutter onTap中讓你脫穎而出的5條規(guī)則,小事情決定了你的熟練程度,這些小細(xì)節(jié)的有趣之處在于它們的豐富性2023-11-11
談?wù)凙ndroid開發(fā)之RecyclerView的使用全解
這篇文章主要介紹了談?wù)凙ndroid開發(fā)之RecyclerView的使用全解,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2016-12-12
Android 按后退鍵退出Android程序的實(shí)現(xiàn)方法
本篇文章介紹了,在Android中按后退鍵退出Android程序的實(shí)現(xiàn)方法。需要的朋友參考下2013-04-04
Flutter 用自定義轉(zhuǎn)場(chǎng)動(dòng)畫實(shí)現(xiàn)頁(yè)面切換
本篇介紹了 fluro 導(dǎo)航到其他頁(yè)面的自定義轉(zhuǎn)場(chǎng)動(dòng)畫實(shí)現(xiàn),F(xiàn)lutter本身提供了不少預(yù)定義的轉(zhuǎn)場(chǎng)動(dòng)畫,可以通過 transitionBuilder 參數(shù)設(shè)計(jì)多種多樣的轉(zhuǎn)場(chǎng)動(dòng)畫,也可以通過自定義的 AnimatedWidget實(shí)現(xiàn)個(gè)性化的轉(zhuǎn)場(chǎng)動(dòng)畫效果。2021-06-06
android使用ItemDecoration給RecyclerView 添加水印
本篇文章主要介紹了android使用ItemDecoration給RecyclerView 添加水印,介紹了自定義Drawable來完成水印圖片和使用ItemDecoration來布局水印,有興趣的可以了解一下。2017-02-02
詳解Android系統(tǒng)中跨應(yīng)用數(shù)據(jù)分享功能的實(shí)現(xiàn)
這篇文章主要介紹了Android系統(tǒng)中跨應(yīng)用數(shù)據(jù)分享功能的實(shí)現(xiàn),文中分為發(fā)送文字、二進(jìn)制內(nèi)容和圖片三種情況來講,需要的朋友可以參考下2016-04-04
Android編程獲取地理位置的經(jīng)度和緯度實(shí)例
這篇文章主要介紹了Android編程獲取地理位置的經(jīng)度和緯度實(shí)現(xiàn)方法,結(jié)合實(shí)例形式詳細(xì)分析了Android操作系統(tǒng)服務(wù)調(diào)用GPS實(shí)現(xiàn)定位的相關(guān)技巧,需要的朋友可以參考下2016-01-01

