Flutter如何填充Google Map自定义图标Marker的透明中心区域?
Marker中心透明问题解决方法
当前Marker中心区域为透明,无法显示预期的白色填充效果,以下是针对你提供的代码的修改方案:
问题原因
你在createBitmapDescriptorFromIconData方法中注释掉了填充中心圆形的_paintCircleFill和绘制外圈边框的_paintCircleStroke方法调用,导致中心区域没有被填充;同时图标绘制偏移设置错误,导致图标位置偏离中心。
修改步骤
- 取消
_paintCircleFill和_paintCircleStroke的注释,确保先绘制背景填充,再绘制图标,让图标叠加在填充区域上方。 - 调整图标的绘制参数,让图标居中显示在填充圆形上。
修改后的完整代码如下:
import 'dart:math'; import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; class MarkerGenerator { final _markerSize; double _circleStrokeWidth = 0; double _circleOffset = 0; double _outlineCircleWidth = 0; double _fillCircleWidth = 0; double _iconSize = 0; double _iconOffset = 0; MarkerGenerator(this._markerSize) { // 计算Marker尺寸参数 _circleStrokeWidth = _markerSize / 10.0; _circleOffset = _markerSize / 2; _outlineCircleWidth = _circleOffset - (_circleStrokeWidth / 2); _fillCircleWidth = _markerSize / 3; final outlineCircleInnerWidth = _markerSize - (2 * _circleStrokeWidth); _iconSize = sqrt(pow(outlineCircleInnerWidth, 2) / 2); final rectDiagonal = sqrt(2 * pow(_markerSize, 2)); final circleDistanceToCorners = (rectDiagonal - outlineCircleInnerWidth) / 2; _iconOffset = sqrt(pow(circleDistanceToCorners, 2) / 2); } /// 从IconData创建BitmapDescriptor Future<BitmapDescriptor> createBitmapDescriptorFromIconData(IconData iconData, Color iconColor, Color circleColor, Color backgroundColor) async { final pictureRecorder = PictureRecorder(); final canvas = Canvas(pictureRecorder); // 绘制中心填充圆形 _paintCircleFill(canvas, backgroundColor); // 绘制外圈边框(不需要可注释) _paintCircleStroke(canvas, circleColor); // 绘制图标 _paintIcon(canvas, iconColor, iconData); final picture = pictureRecorder.endRecording(); final image = await picture.toImage(_markerSize.round(), _markerSize.round()); final bytes = await image.toByteData(format: ImageByteFormat.png); return BitmapDescriptor.fromBytes(bytes!.buffer.asUint8List()); } /// 绘制图标背景填充 void _paintCircleFill(Canvas canvas, Color color) { final paint = Paint() ..style = PaintingStyle.fill ..color = color; canvas.drawCircle( Offset(_circleOffset, _circleOffset), _fillCircleWidth, paint); } /// 绘制图标外圈边框 void _paintCircleStroke(Canvas canvas, Color color) { final paint = Paint() ..style = PaintingStyle.stroke ..color = color ..strokeWidth = _circleStrokeWidth; canvas.drawCircle( Offset(_circleOffset, _circleOffset), _outlineCircleWidth, paint); } /// 绘制图标 void _paintIcon(Canvas canvas, Color color, IconData iconData) { final textPainter = TextPainter(textDirection: TextDirection.ltr); textPainter.text = TextSpan( text: String.fromCharCode(iconData.codePoint), style: TextStyle( letterSpacing: 0.0, fontSize: _iconSize, // 使用计算好的合适尺寸 fontFamily: iconData.fontFamily, color: color, )); textPainter.layout(); // 计算偏移让图标居中 final offsetX = (_markerSize - textPainter.width) / 2; final offsetY = (_markerSize - textPainter.height) / 2; textPainter.paint(canvas, Offset(offsetX, offsetY)); } }
关键修改说明
- 恢复
_paintCircleFill方法调用,传入Colors.white作为backgroundColor即可填充中心白色区域。 - 调整图标字体大小为计算好的
_iconSize,并通过偏移计算让图标在填充圆形内居中显示,避免位置偏移。 - 如果不需要外圈黑色边框,可再次注释
_paintCircleStroke方法调用。
使用时,调用createBitmapDescriptorFromIconData时传入backgroundColor: Colors.white,就能得到中心白色填充的Marker。
内容的提问来源于stack exchange,提问作者theriaca01
相关产品推荐
相关产品推荐

