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

相关推荐
ZH15455891311 小时前
Flutter for OpenHarmony Python学习助手实战:面向对象编程实战的实现
python·学习·flutter
renke33642 小时前
Flutter for OpenHarmony:构建一个 Flutter 色彩调和师游戏,RGB 空间探索、感知色差计算与视觉认知训练的工程实现
flutter·游戏
王码码20352 小时前
Flutter for OpenHarmony 实战之基础组件:第三十一篇 Chip 系列组件 — 灵活的标签化交互
android·flutter·交互·harmonyos
ujainu3 小时前
Flutter + OpenHarmony 实现经典打砖块游戏开发实战—— 物理反弹、碰撞检测与关卡系统
flutter·游戏·openharmony·arkanoid·breakout
微祎_3 小时前
构建一个 Flutter 点击速度测试器:深入解析实时交互、性能度量与响应式 UI 设计
flutter·ui·交互
王码码20354 小时前
Flutter for OpenHarmony 实战之基础组件:第二十七篇 BottomSheet — 动态底部弹窗与底部栏菜单
android·flutter·harmonyos
ZH15455891314 小时前
Flutter for OpenHarmony Python学习助手实战:Web开发框架应用的实现
python·学习·flutter
晚霞的不甘4 小时前
Flutter for OpenHarmony 构建简洁高效的待办事项应用 实战解析
flutter·ui·前端框架·交互·鸿蒙
百锦再4 小时前
Vue高阶知识:利用 defineModel 特性开发搜索组件组合
前端·vue.js·学习·flutter·typescript·前端框架
廖松洋(Alina)5 小时前
【收尾以及复盘】flutter开发鸿蒙APP之成就徽章页面
flutter·华为·开源·harmonyos·鸿蒙