You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Flutter Canvas中使用flutter_svg绘制SVG及图形遇到问题

问题分析与解决方案

你的代码核心问题是在paint方法里执行异步加载SVG的操作——paint是同步执行的绘制方法,当异步回调(then里的代码)触发时,当前的绘制周期已经结束,Canvas的绘制上下文早已失效,所以SVG图像根本画不出来。另外热重载时的空引用警告,也是因为异步回调里引用的对象(比如paint、Canvas)可能已经被销毁。

正确的实现思路

  1. 提前预加载SVG资源:在组件初始化阶段(比如initState)完成SVG的加载,不要放到paint里。
  2. 管理加载状态:用状态变量保存加载好的Picture或Image,加载完成后触发重绘。
  3. 同步绘制:在paint里直接使用预加载好的资源进行同步绘制。

完整代码示例

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';

class SvgCanvasDemo extends StatefulWidget {
  const SvgCanvasDemo({super.key});

  @override
  State<SvgCanvasDemo> createState() => _SvgCanvasDemoState();
}

class _SvgCanvasDemoState extends State<SvgCanvasDemo> {
  Picture? _svgPicture;

  @override
  void initState() {
    super.initState();
    // 初始化时预加载SVG
    _loadSvg();
  }

  Future<void> _loadSvg() async {
    final svgPicture = await vg.loadPicture(
      const SvgAssetLoader("assets/Monogramme_dark.svg"),
      null,
    );
    setState(() {
      _svgPicture = svgPicture.picture;
    });
  }

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: _MyCanvasPainter(svgPicture: _svgPicture),
      size: const Size(double.infinity, double.infinity),
    );
  }
}

class _MyCanvasPainter extends CustomPainter {
  final Picture? svgPicture;

  _MyCanvasPainter({this.svgPicture});

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()..color = const Color.fromARGB(255, 15, 9, 184);

    // 绘制蓝色圆形
    canvas.drawCircle(const Offset(50.0, 20.0), 10, paint);

    // SVG加载完成后绘制
    if (svgPicture != null) {
      // 方法1:直接绘制Picture(推荐,比转Image更高效)
      canvas.save();
      canvas.translate(100, 100); // 定位SVG
      canvas.scale(0.5); // 根据需要缩放
      canvas.drawPicture(svgPicture!);
      canvas.restore();

      // 方法2:转成Image绘制(如果需要对Image做更多处理)
      // svgPicture!.toImage(50, 50).then((image) {
      //   // 注意:如果要在这里绘制,需要确保当前Canvas有效,建议用方法1
      //   canvas.drawImage(image, const Offset(100, 100), paint);
      // });
    }
  }

  @override
  bool shouldRepaint(_MyCanvasPainter oldDelegate) {
    // 当SVGPicture变化时触发重绘
    return oldDelegate.svgPicture != svgPicture;
  }
}

关键说明

  • 预加载资源:把SVG加载逻辑放到initState里,确保在绘制前完成加载,加载完成后通过setState触发重绘。
  • 直接绘制Picture:flutter_svg返回的Picture可以直接用canvas.drawPicture绘制,比转成Image更高效,还能保留矢量特性(缩放不失真)。
  • shouldRepaint逻辑:当传入的svgPicture变化时(从null变成加载好的Picture),告诉Flutter需要重绘,这样SVG就能显示出来。

内容的提问来源于stack exchange,提问作者pim999

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 20:33:26