flutter 文字绘制与相对位置定点

Canvas的文字绘制已经有很多人写过了,这里只是对文字绘制的显示位置的归纳,过通自定义 Alignment 参数的使用从而避免对绘制文字大小的额外偏移计算。

先贴效果,一睹为快。

基础参数的相对位置图例

代码实现:

相对位置解析
arduino 复制代码
/// 文字绘制
extension StringCanvasExt on String {
  /// 文本绘制
  ///
  /// ```
  /// [offset]: 文字对齐点
  /// [alignment]: 文字相对 点[offset] 对齐的方式, 默认居中(文字中心与offset重叠)
  ///              eg: Alignment.bottomCenter 位于点offset中下方
  /// [maxLength]: 文字最大宽度
  /// [isDebugColor]: 是否显示背景色块
  /// ```
  draw(
    Canvas canvas,
    Offset offset, {
    TextStyle style = const TextStyle(fontSize: 12, color: Colors.black),
    Alignment alignment = Alignment.center,
    double? maxWidth,
    bool isDebugColor = false,
  }) {
    final text = TextPainter(
      text: TextSpan(
        text: this,
        style: style,
      ),
      // strutStyle: const StrutStyle(forceStrutHeight: true),
      textAlign: TextAlign.center,
      textDirection: TextDirection.ltr,
    );
    text.layout(maxWidth: maxWidth ?? double.infinity);
    final textSize = text.size;

    // 对文字本身做偏移
    final alignOffset = Offset(
            textSize.width / 2 * alignment.x, textSize.height / 2 * alignment.y)
        .translate(-textSize.width / 2, -textSize.height / 2);
    // 下面对位置偏移的操作,更容易理解
    // final alignOffset = Offset.zero
    //     .translate(-textSize.width / 2, -textSize.height / 2)
    //     .translate(textSize.width / 2 * alignment.x,
    //         textSize.height / 2 * alignment.y);
    
    // 绘制色块,方便调试
    if (!kReleaseMode && isDebugColor) {
      canvas.drawRect(
        (alignOffset + offset) & textSize,
        Paint()
          ..style = PaintingStyle.fill
          ..color = Colors.red.withOpacity(0.5),
      );
    }

    text.paint(canvas, alignOffset + offset);
  }
}

绘制代码中唯一需要注意的是 alignOffset 的值的计算含义:

  1. 校准 Alignment.center 的位置:

操作1: translate(-textSize.width / 2, -textSize.height / 2)

由于绘制默认布局起点为左上角 Offset(-1, -1) ,而我们传统意义上的 居中 为视图中心点 (size.width/2, size.height/2), 所以这里对计算值进行视图半宽高大小的偏移,以同步我们对传统意义上居中的理解。

  1. 通过对 Alignment(this.x, this.y) 值的进一步处理,实现布局的释义:

操作2: Offset( textSize.width / 2 * alignment.x, textSize.height / 2 * alignment.y)

通过 操作1 我们已经对渲染文本实现了绝对居中,现在结合 Alignment 的值只需要对 alignOffset 再进行一次位置偏移 操作2 就可以完成我们对布局的期望。

完成这两步后我们想要的结果就已经出来了。

换一个写法应该更容易理解:

arduino 复制代码
final alignOffset = Offset.zero
    .translate(-textSize.width / 2, -textSize.height / 2)
    .translate(textSize.width / 2 * alignment.x,
        textSize.height / 2 * alignment.y);

实现还是比较简单,记录下方便以后查找。

简单封装的坐标系代码也在里面。

Github: draw_text

相关推荐
九丝城主14 小时前
2025使用VM虚拟机安装配置Macos苹果系统下Flutter开发环境保姆级教程--上篇
服务器·flutter·macos·vmware
瓜子三百克19 小时前
七、性能优化
flutter·性能优化
恋猫de小郭1 天前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
小蜜蜂嗡嗡1 天前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
瓜子三百克2 天前
十、高级概念
flutter
帅次2 天前
Objective-C面向对象编程:类、对象、方法详解(保姆级教程)
flutter·macos·ios·objective-c·iphone·swift·safari
小蜜蜂嗡嗡2 天前
flutter flutter_vlc_player播放视频设置循环播放失效、初始化后获取不到视频宽高
flutter
孤鸿玉2 天前
[Flutter小技巧] Row中widget高度自适应的几种方法
flutter
bawomingtian1232 天前
FlutterView 源码解析
flutter
Zender Han2 天前
Flutter 进阶:实现带圆角的 CircularProgressIndicator
flutter