您好,登錄后才能下訂單哦!
本文小編為大家詳細(xì)介紹“Flutter矢量圖SVG的區(qū)域填色怎么實(shí)現(xiàn)”,內(nèi)容詳細(xì),步驟清晰,細(xì)節(jié)處理妥當(dāng),希望這篇“Flutter矢量圖SVG的區(qū)域填色怎么實(shí)現(xiàn)”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識(shí)吧。
具體步驟: 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, ), ); }, )
讀到這里,這篇“Flutter矢量圖SVG的區(qū)域填色怎么實(shí)現(xiàn)”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識(shí)點(diǎn)還需要大家自己動(dòng)手實(shí)踐使用過才能領(lǐng)會(huì),如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。