[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~

相关推荐
丁总学Java19 分钟前
微信小程序-npm支持-如何使用npm包
前端·微信小程序·npm·node.js
懒羊羊大王呀30 分钟前
CSS——属性值计算
前端·css
无咎.lsy1 小时前
vue之vuex的使用及举例
前端·javascript·vue.js
fishmemory7sec1 小时前
Electron 主进程与渲染进程、预加载preload.js
前端·javascript·electron
fishmemory7sec1 小时前
Electron 使⽤ electron-builder 打包应用
前端·javascript·electron
豆豆2 小时前
为什么用PageAdmin CMS建设网站?
服务器·开发语言·前端·php·软件构建
落落落sss2 小时前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
代码敲上天.3 小时前
数据库语句优化
android·数据库·adb
twins35203 小时前
解决Vue应用中遇到路由刷新后出现 404 错误
前端·javascript·vue.js
qiyi.sky3 小时前
JavaWeb——Vue组件库Element(3/6):常见组件:Dialog对话框、Form表单(介绍、使用、实际效果)
前端·javascript·vue.js