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

升级flutter_svg至2.0.7后DrawableRoot失效,如何设置尺寸与颜色?

解决flutter_svg 2.x中SVG字符串转带尺寸/颜色的ui.Image问题

核心实现思路

flutter_svg 2.x废弃DrawableRoot后,需通过PictureRecorder手动管控绘制流程:在绘制SVG的Picture时指定尺寸缩放比例,同时通过Paint设置颜色滤镜,最终生成符合需求的ui.Image。

具体步骤与代码示例

import 'dart:ui' as ui;
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart' as vg;

Future<ui.Image> svgStringToImage(
  String svgString,
  Size targetSize,
  Color targetColor,
) async {
  // 1. 从字符串加载原始SVG矢量图
  final svgBytes = utf8.encode(svgString);
  final picture = await vg.loadPicture(
    vg.SvgBytesLoader(svgBytes),
    null,
  );

  // 2. 计算缩放比例(保持SVG原始宽高比,避免拉伸)
  final svgSize = Size(picture.width.toDouble(), picture.height.toDouble());
  final scaleX = targetSize.width / svgSize.width;
  final scaleY = targetSize.height / svgSize.height;
  final scale = min(scaleX, scaleY);
  // 可选:计算居中偏移,让SVG在目标尺寸内居中显示
  final offsetX = (targetSize.width - svgSize.width * scale) / 2;
  final offsetY = (targetSize.height - svgSize.height * scale) / 2;

  // 3. 创建绘制记录器与画布
  final recorder = ui.PictureRecorder();
  final canvas = ui.Canvas(recorder, Rect.fromLTWH(0, 0, targetSize.width, targetSize.height));
  
  // 4. 应用偏移、缩放与颜色滤镜
  canvas.save();
  canvas.translate(offsetX, offsetY);
  canvas.scale(scale);
  final paint = ui.Paint()
    ..colorFilter = ui.ColorFilter.mode(targetColor, ui.BlendMode.srcIn); // 保留SVG透明度,替换颜色
  canvas.drawPicture(picture, paint);
  canvas.restore();

  // 5. 生成并返回最终ui.Image
  final processedPicture = recorder.endRecording();
  final image = await processedPicture.toImage(
    targetSize.width.toInt(),
    targetSize.height.toInt(),
  );
  
  // 释放资源,避免内存泄漏
  picture.dispose();
  processedPicture.dispose();
  return image;
}

适配ShaderMask的用法示例

生成的ui.Image可直接用于创建水印Shader:

// 生成水印Image
final watermarkImage = await svgStringToImage(
  '<svg>你的SVG字符串内容</svg>',
  Size(120, 120),
  Colors.grey.withOpacity(0.3),
);

// 创建重复平铺的Shader
final watermarkShader = ImageShader(
  watermarkImage,
  TileMode.repeated,
  TileMode.repeated,
  Matrix4.identity().storage,
);

// 用于ShaderMask实现水印效果
ShaderMask(
  shaderCallback: (bounds) => watermarkShader,
  blendMode: BlendMode.srcOver,
  child: Container(
    width: double.infinity,
    height: double.infinity,
    child: yourTargetContentWidget, // 需要添加水印的内容组件
  ),
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 02:05:59