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

相关推荐
yuanlaile3 小时前
纯Dart Flutter库适配HarmonyOS
flutter·华为·harmonyos·flutter开发鸿蒙·harmonyos教程
yuanlaile3 小时前
Flutter开发HarmonyOS 鸿蒙App的好处、能力以及把Flutter项目打包成鸿蒙应用
flutter·华为·harmonyos·flutter开发鸿蒙
zacksleo5 小时前
鸿蒙原生开发手记:04-一个完整元服务案例
flutter
jcLee951 天前
Flutter/Dart:使用日志模块Logger Easier
flutter·log4j·dart·logger
tmacfrank1 天前
Flutter 异步编程简述
flutter
tmacfrank1 天前
Flutter 基础知识总结
flutter
叫我菜菜就好1 天前
【Flutter_Web】Flutter编译Web第三篇(网络请求篇):dio如何改造方法,变成web之后数据如何处理
前端·网络·flutter
AiFlutter1 天前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
m0_748247803 天前
Flutter Intl包使用指南:实现国际化和本地化
前端·javascript·flutter
迷雾漫步者3 天前
Flutter组件————PageView
flutter·跨平台·dart