Android打车应用MapView路线动画叠加多段线不对齐问题求助
问题原因
- 端点样式未统一:Google Maps Polyline 默认端点为
ButtCap(平切端点),你没有显式配置前景、背景多段线的端点样式,截断后的前景多段线两端的平切边缘,和背景多段线连续线段的圆角关节渲染效果不一致,产生视觉偏移。 - 点集截断丢失关节信息:按点数截断点集时,如果刚好切到曲线拐点位置,前景多段线会丢失拐点前后的过渡点,
JointType.ROUND圆角关节的渲染逻辑和完整背景多段线的同位置关节渲染产生差异,导致偏移。 - 点集来源不稳定性:你直接从
backgroundPolyline.points获取点集,部分版本的Google Maps SDK会对返回的点做轻微的坐标归一化处理,和原始传入的坐标存在极小误差,叠加后就会出现可见偏移。
解决方案
方案1:优先推荐 采用Pattern动态填充实现动画(完全避免对齐问题)
不需要动态截断点集,两条多段线使用完全相同的完整坐标点,通过动态修改前景多段线的填充 pattern 实现动画效果,从根源上消除对齐问题:
// 初始化阶段 自己存储原始坐标点集合,所有点操作优先用这个集合 val originalPoints: List<LatLng> = // 你生成的曲线点集 val polylineOptions = PolylineOptions() .color(backgroundColor) .width(POLYLINE_WIDTH) .geodesic(false) .jointType(JointType.ROUND) .startCap(RoundCap()) .endCap(RoundCap()) .zIndex(0f) .addAll(originalPoints) backgroundPolyline = map.addPolyline(polylineOptions) val foregroundPolylineOptions = PolylineOptions() .color(foregroundColor) .width(FOREGROUND_POLYLINE_WIDTH) .jointType(JointType.ROUND) .geodesic(false) .startCap(RoundCap()) .endCap(RoundCap()) .zIndex(1f) .addAll(originalPoints) // 和背景完全一致的完整点集 foregroundPolyline = map.addPolyline(foregroundPolylineOptions) // 动画更新逻辑 override fun onAnimationUpdate(animation: ValueAnimator) { val fraction = animation.animatedFraction // pattern单位为屏幕像素,你也可以用地图投影换算成实际地理长度匹配行程 val totalPatternLength = 1000f // 自定义总长度,按视觉效果调整即可 val gapLength = totalPatternLength * (1 - fraction) val foregroundLength = totalPatternLength * 0.1f // 10%长度的前景滑块 foregroundPolyline.pattern = listOf( Gap(gapLength), Stroke(foregroundLength), Gap(totalPatternLength - gapLength - foregroundLength) ) }
方案2:修复原有截断逻辑
如果你要保留现有截断点的实现,修改以下几点即可:
- 不要从已渲染的polyline实例中读取点集,统一使用你自己存储的原始坐标点集合
originalPoints - 显式给两条多段线添加相同的
startCap和endCap配置 - 截断点前后各多保留1个点,避免丢失拐点信息:
override fun onAnimationUpdate(animation: ValueAnimator) { val totalSize = originalPoints.size val foregroundEnd = ceil(animation.animatedFraction * totalSize).toInt() val foregroundPointCounts = (totalSize * 0.1).toInt() val start = max(0, foregroundEnd - foregroundPointCounts - 1) // 多保留前1个点 val end = min(totalSize, foregroundEnd + 1) // 多保留后1个点 // 转成新列表避免subList视图特性导致的异常 foregroundPolyline.points = ArrayList(originalPoints.subList(start, end)) }
内容的提问来源于stack exchange,提问作者itsalex
相关产品推荐
相关产品推荐

