[Flutter]如何用代码自定义 Market显示在高德地图上方案

前景

事情是这样的,我们的有个产品的高德地图上会有很多种类的图片。如图所示,大概又 12 种图标类型,每一种在区分选中未选中,就有 24 种。众所周知,高德地图显示的 market 图标只能是图片资源,所以像 ios 和 android 图标大小还得不同,就成了 48 种...甚至不止,没有细数。

然后就寻思着能不能用代码绘制一个图标,控制圆角、底色、文字等,这样就少了很多的资源以及繁琐的判断配置等。

方案一(已废弃,不推荐)

一开始想着,flutter 将组件转换为 base64 的图片,然后渲染到高德地图上。

原理是绘制一个组件,然后组件渲染后把组件转成图片。

这种方案,消耗资源很多,而且需要等待组件渲染完成后转成图片,这个是很耗性能和影响体验的,如果是一个简单的图标还好,如果像我需求这么多的图标,无意启动这个页面先卡很多很多秒....不建议,与其使用这个方案,不如多切几个图。

具体可参考:

www.jianshu.com/p/b26cd3326...

附:如果使用设计切图

可以通过该函数来控制图标的不同大小,这样可以有效减少资源数量。避免同样的图标,要好几套不同大小的。

arduino 复制代码
/// 根据资源地址获取指定大小的图片
static Future<Uint8List> getImageBytesFromAsset(
    String path, int width, int height) async {
  final data = await rootBundle.load(path);
  ui.Codec codec = await ui.instantiateImageCodec(
    data.buffer.asUint8List(),
    targetWidth: width,
    targetHeight: height,
  );
  ui.FrameInfo fi = await codec.getNextFrame();
  return (await fi.image.toByteData(format: ui.ImageByteFormat.png))!
      .buffer
      .asUint8List();
}

方案二(推荐)

思路: 大家用flutter 脑海里习惯上是各种 Widget,但是实际上,flutter 是建立在 dart 之上的。如果想绘制一张图片,我们完全没必要通过 flutter 的 Widget 的方式,而是可以通过 dart:ui 依赖包来实现!!!

稍微了解下 dart:ui官方库,我们很快就可以得到,ui.Canvas转 base64 图片是完全可行的!

那接下来直接看成果。

以下代码,绘制了 圆角矩形,中间带文字、可设置背景色、大小、边框的小图标。

代码

dart 复制代码
//绘制图标
static Future<Uint8List> drawMapIcon({
  String? text,
  int width = 50,
  int height = 50,
  double radius = 10,
  double fontSize = 30,
  Color backgroundColor = Colors.red,
  Color outlineColor = Colors.red,
  double outlineSize = 0.0,
  Color textColor = Colors.white,
}) async {
  // 获取画布
  ui.PictureRecorder recorder = ui.PictureRecorder();
  ui.Canvas canvas = ui.Canvas(recorder);
  if (outlineSize != 0) {
    // 绘制圆形轮廓
    canvas.drawRRect(
      ui.RRect.fromLTRBR(
        0,
        0,
        width.toDouble(),
        height.toDouble(),
        Radius.circular(radius),
      ),
      ui.Paint()..color = outlineColor,
    );
  }
  // 绘制圆形图标
  canvas.drawRRect(
    ui.RRect.fromLTRBR(
      outlineSize,
      outlineSize,
      (width - outlineSize).toDouble(),
      (height - outlineSize).toDouble(),
      Radius.circular(radius - outlineSize),
    ),
    ui.Paint()..color = backgroundColor,
  );
  // 绘制数字
  if (text != null) {
    ui.ParagraphBuilder paragraph = ui.ParagraphBuilder(
      ui.ParagraphStyle(textAlign: ui.TextAlign.center),
    );
    //font size
    paragraph.pushStyle(ui.TextStyle(
      fontSize: fontSize,
      fontWeight: ui.FontWeight.bold,
      color: textColor,
    ));
    paragraph.addText(text);
    final p = paragraph.build();
    p.layout(
      ui.ParagraphConstraints(
        width: width.toDouble(),
      ),
    );
    canvas.drawParagraph(
      p,
      Offset(0, (height - fontSize - (2 * outlineSize)) / 2),
    );
  }

  //转换成字节
  final picture = recorder.endRecording();
  final img = await picture.toImage(width, height);
  final byteData = await img.toByteData(format: ui.ImageByteFormat.png);
  picture.dispose();
  return byteData!.buffer.asUint8List();
}

Bye~

相关推荐
Ndmzi18 小时前
Matlab编程技巧:自定义Simulink菜单(理解补充)
前端·javascript·python
我命由我1234519 小时前
VSCode - VSCode 修改文件树缩进
前端·ide·vscode·前端框架·编辑器·html·js
a31582380619 小时前
Android Framework开发知识点整理
android·java·linux·服务器·framework·android源码开发
SoaringHeart19 小时前
Flutter组件封装:验证码倒计时按钮 TimerButton
前端·flutter
k***825119 小时前
图文详述:MySQL的下载、安装、配置、使用
android·mysql·adb
San30.19 小时前
深入理解 JavaScript OOP:从一个「就地编辑组件」看清封装、状态与原型链
开发语言·前端·javascript·ecmascript
lqj_本人20 小时前
Flutter 适配鸿蒙桌面快捷入口完整指南
flutter·华为·harmonyos
AAA阿giao20 小时前
JavaScript 原型与原型链:从零到精通的深度解析
前端·javascript·原型·原型模式·prototype·原型链
烛阴20 小时前
C#异常概念与try-catch入门
前端·c#
钮钴禄·爱因斯晨20 小时前
# 企业级前端智能化架构:DevUI与MateChat融合实践深度剖析
前端·架构