Android Google Maps如何使用Polyline在Polygon中裁剪出镂空区域
是否可以使用
Polyline裁剪镂空区域(或创建类似遮罩的效果) 原生地图SDK的Polyline组件本身不支持直接作为遮罩擦除底层Polygon的填充区域,以下是两种可落地的替代实现方案:
方案1:将轨迹转换为带宽度的闭合多边形作为Polygon镂空
你可以把每一段轨迹根据线宽参数扩展为闭合的多边形区域,直接作为全地图Polygon的镂空洞传入,避开Polyline无法直接裁剪的限制:
- 操作逻辑:每次新增轨迹点时,根据当前设置的线宽,对现有轨迹点做偏移计算,生成左右两条边界线,首尾闭合后得到对应轨迹的闭合多边形
- 注意事项:每次新增点后重新计算完整的镂空多边形列表,传入
Polygon的holes参数即可,只要闭合多边形坐标顺序合法,不会出现填充消失的问题
方案2:自定义遮罩图层(更适合动态轨迹场景,推荐)
直接在地图上层叠加一个自定义透明View,用Android的图形混合模式实现擦除效果,完全避开地图SDK的Polygon镂空限制:
实现步骤
- 给地图添加一个同尺寸的自定义View,层级覆盖在地图之上
- 在View的
onDraw方法中先绘制半透明的全屏遮罩,再用PorterDuff.Mode.CLEAR的画笔绘制轨迹路径,即可得到轨迹位置镂空的效果 - 每次收到新的定位点时,更新轨迹路径后调用
invalidate()刷新View即可
参考代码
你可以把原有的轨迹绘制逻辑替换为以下实现:
// 自定义遮罩View代码 class MaskOverlayView(context: Context) : View(context) { private val maskPaint = Paint().apply { color = 0xAA000000 // 半透明黑色遮罩,可自定义 style = Paint.Style.FILL } private val erasePaint = Paint().apply { isAntiAlias = true strokeWidth = 20f // 轨迹宽度,可自定义 style = Paint.Style.STROKE strokeCap = Paint.Cap.ROUND xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) setLayerType(LAYER_TYPE_HARDWARE, null) } private val trailPath = Path() fun addTrailPoint(latLng: LatLng) { // 将地图坐标转换为View的屏幕坐标 val point = map.projection.toScreenLocation(latLng) if (trailPath.isEmpty) { trailPath.moveTo(point.x, point.y) } else { trailPath.lineTo(point.x, point.y) } invalidate() } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) // 绘制全屏遮罩 canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), maskPaint) // 擦除轨迹区域 canvas.drawPath(trailPath, erasePaint) } } // 原有定位回调修改 override fun onLocationResult(locationResult: LocationResult?) { locationResult ?: return locationResult.lastLocation.let { if (it.accuracy > 0.5) { lastLocation = it maskOverlayView.addTrailPoint(LatLng(it.latitude, it.longitude)) } } }
效果对比

内容的提问来源于stack exchange,提问作者Kes Walker
相关产品推荐
相关产品推荐

