[Flutter]如何用代码自定义 Market显示在高德地图上方案
前景
事情是这样的,我们的有个产品的高德地图上会有很多种类的图片。如图所示,大概又 12 种图标类型,每一种在区分选中未选中,就有 24 种。众所周知,高德地图显示的 market 图标只能是图片资源,所以像 ios 和 android 图标大小还得不同,就成了 48 种...甚至不止,没有细数。
然后就寻思着能不能用代码绘制一个图标,控制圆角、底色、文字等,这样就少了很多的资源以及繁琐的判断配置等。
方案一(已废弃,不推荐)
一开始想着,flutter 将组件转换为 base64 的图片,然后渲染到高德地图上。
原理是绘制一个组件,然后组件渲染后把组件转成图片。
这种方案,消耗资源很多,而且需要等待组件渲染完成后转成图片,这个是很耗性能和影响体验的,如果是一个简单的图标还好,如果像我需求这么多的图标,无意启动这个页面先卡很多很多秒....不建议,与其使用这个方案,不如多切几个图。
具体可参考:
附:如果使用设计切图
可以通过该函数来控制图标的不同大小,这样可以有效减少资源数量。避免同样的图标,要好几套不同大小的。
/// 根据资源地址获取指定大小的图片
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 图片是完全可行的!
那接下来直接看成果。
以下代码,绘制了 圆角矩形,中间带文字、可设置背景色、大小、边框的小图标。
代码
//绘制图标
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~
转载自:https://juejin.cn/post/7350197071943794751