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

Flutter动态生成自定义护照印章图像方案咨询

实现Flutter动态护照印章效果的最优方案

核心思路

放弃预存600张组合图的冗余方案,通过基础素材+Widget组合+颜色滤镜实现动态生成,仅需存储:

  • 10张形状素材(透明底,白色填充/描边,优先SVG格式保证缩放不失真)
  • 6张出行方式素材(透明底,白色图标,优先SVG格式)

总共仅需16张素材,完全避免冗余,且支持实时修改参数。

具体实现步骤

1. 素材准备

所有素材推荐使用SVG格式,可借助flutter_svg库加载;若用PNG,需确保是透明底、白色主体的高分辨率图片,方便后续染色。

2. 动态组合与染色组件

用Stack实现外层形状与内层出行图标的居中叠加,通过ColorFiltered统一为两者应用颜色滤镜,实现同步变色。

示例代码:

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

class PassportStamp extends StatelessWidget {
  final String shapeAsset;
  final String transportAsset;
  final Color stampColor;

  const PassportStamp({
    super.key,
    required this.shapeAsset,
    required this.transportAsset,
    this.stampColor = Colors.black,
  });

  @override
  Widget build(BuildContext context) {
    return ColorFiltered(
      colorFilter: ColorFilter.mode(
        stampColor,
        BlendMode.srcIn, // 仅对素材非透明区域染色
      ),
      child: Stack(
        alignment: Alignment.center,
        children: [
          // 外层形状,占满容器
          SvgPicture.asset(
            shapeAsset,
            width: 120,
            height: 120,
          ),
          // 内层出行图标,缩为形状的60%大小
          SvgPicture.asset(
            transportAsset,
            width: 72,
            height: 72,
          ),
        ],
      ),
    );
  }
}

3. 联动选择器实现

通过StatefulWidget管理选中状态,搭配横向滚动选择器,实现实时更新印章效果。

示例代码片段:

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

  @override
  State<StampSelectorPage> createState() => _StampSelectorPageState();
}

class _StampSelectorPageState extends State<StampSelectorPage> {
  String selectedShape = "assets/shapes/circle.svg";
  String selectedTransport = "assets/transports/plane.svg";
  Color selectedColor = Colors.black;

  // 模拟选项列表,实际替换为你的素材路径/颜色值
  final List<String> shapeOptions = [
    "assets/shapes/circle.svg",
    "assets/shapes/square.svg",
    // 其余8种形状...
  ];
  final List<String> transportOptions = [
    "assets/transports/plane.svg",
    "assets/transports/ship.svg",
    // 其余4种出行方式...
  ];
  final List<Color> colorOptions = [
    Colors.black,
    Colors.red,
    Colors.blue,
    // 其余7种颜色...
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          // 印章预览区
          Expanded(
            child: Center(
              child: PassportStamp(
                shapeAsset: selectedShape,
                transportAsset: selectedTransport,
                stampColor: selectedColor,
              ),
            ),
          ),
          // 形状选择器
          SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: Row(
              children: shapeOptions.map((shape) {
                return Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: GestureDetector(
                    onTap: () => setState(() => selectedShape = shape),
                    child: SvgPicture.asset(
                      shape,
                      width: 40,
                      height: 40,
                      colorFilter: ColorFilter.mode(
                        selectedShape == shape ? Colors.blue : Colors.grey,
                        BlendMode.srcIn,
                      ),
                    ),
                  ),
                );
              }).toList(),
            ),
          ),
          // 出行方式选择器(逻辑同形状选择器)
          // 颜色选择器
          SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: Row(
              children: colorOptions.map((color) {
                return Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: GestureDetector(
                    onTap: () => setState(() => selectedColor = color),
                    child: Container(
                      width: 40,
                      height: 40,
                      decoration: BoxDecoration(
                        color: color,
                        border: selectedColor == color
                            ? Border.all(color: Colors.blue, width: 2)
                            : null,
                        borderRadius: BorderRadius.circular(8),
                      ),
                    ),
                  ),
                );
              }).toList(),
            ),
          ),
        ],
      ),
    );
  }
}

4. 优化细节

  • 素材选型:SVG比PNG更省空间且缩放无模糊,flutter_svg是成熟的加载方案。
  • 性能保障:所有操作均为Widget层级的组合与滤镜,无额外图片解码开销,实时更新流畅。
  • 扩展性:新增形状、出行方式或颜色时,仅需添加对应素材/颜色值,无需修改核心逻辑。

替代方案(无法使用SVG时)

若只能用PNG,确保素材为透明底、白色主体的高分辨率图,同样可通过ColorFiltered实现染色,仅需注意缩放模糊问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 04:12:50