如何在Flutter Canvas中实现仅绘制文字描边的效果
Flutter Canvas 实现文字描边/填充样式切换方案
核心原理
Flutter的ui.Paint类自带绘制模式配置,配合文字路径转换能力,就能直接实现类似设计软件的文字样式效果:
PaintingStyle.fill对应填充模式,为默认绘制样式PaintingStyle.stroke对应描边模式,可搭配strokeWidth调整描边粗细- 需要描边+填充同时显示时,分层绘制即可,先画底层描边再画上层填充,避免描边覆盖填充区域
完整实现代码
import 'package:flutter/material.dart'; import 'dart:ui' as ui; // 文字样式枚举 enum TextStyleMode { fill, stroke, fillAndStroke } class StyledTextPainter extends CustomPainter { final String text; final double fontSize; final Color fillColor; final Color strokeColor; final double strokeWidth; final TextStyleMode mode; StyledTextPainter({ required this.text, required this.fontSize, required this.fillColor, required this.strokeColor, required this.strokeWidth, required this.mode, }); @override void paint(Canvas canvas, Size size) { // 配置基础文本样式 final textStyle = TextStyle( fontSize: fontSize, // 可替换为自定义字体,需提前在pubspec.yaml中配置 fontFamily: 'system', ); final textSpan = TextSpan(text: text, style: textStyle); final textPainter = TextPainter( text: textSpan, textDirection: TextDirection.ltr, ); textPainter.layout(); // 生成居中的文字路径 final textOffset = Offset( (size.width - textPainter.width) / 2, (size.height - textPainter.height) / 2, ); final textPath = textPainter.text!.toPath(textOffset); // 按选中模式绘制 switch (mode) { case TextStyleMode.fill: final fillPaint = Paint() ..style = PaintingStyle.fill ..color = fillColor; canvas.drawPath(textPath, fillPaint); break; case TextStyleMode.stroke: final strokePaint = Paint() ..style = PaintingStyle.stroke ..strokeWidth = strokeWidth ..strokeCap = StrokeCap.round ..strokeJoin = StrokeJoin.round ..color = strokeColor; canvas.drawPath(textPath, strokePaint); break; case TextStyleMode.fillAndStroke: // 先画描边底层,再画填充上层,效果更符合设计预期 final strokePaint = Paint() ..style = PaintingStyle.stroke ..strokeWidth = strokeWidth ..strokeCap = StrokeCap.round ..strokeJoin = StrokeJoin.round ..color = strokeColor; final fillPaint = Paint() ..style = PaintingStyle.fill ..color = fillColor; canvas.drawPath(textPath, strokePaint); canvas.drawPath(textPath, fillPaint); break; } } @override bool shouldRepaint(covariant StyledTextPainter oldDelegate) { return oldDelegate.text != text || oldDelegate.fontSize != fontSize || oldDelegate.fillColor != fillColor || oldDelegate.strokeColor != strokeColor || oldDelegate.strokeWidth != strokeWidth || oldDelegate.mode != mode; } }
使用示例
直接通过CustomPaint组件调用即可,需要切换样式时仅修改mode参数触发重绘就行:
// 仅描边模式示例,效果见下图 CustomPaint( size: const Size(350, 120), painter: StyledTextPainter( text: "STROKE TEXT", fontSize: 52, fillColor: Colors.white, strokeColor: Colors.black, strokeWidth: 2, mode: TextStyleMode.stroke, ), )

注意事项
- 拐角处描边出现毛刺时,调整
strokeJoin和strokeCap为round即可优化显示效果 - 使用自定义字体时需要提前在
pubspec.yaml中完成字体注册,否则样式不生效 - 文字转路径的API仅支持Flutter 2.0及以上版本,低版本项目需要先升级SDK
内容的提问来源于stack exchange,提问作者Zihan
相关产品推荐
相关产品推荐

