Flutter Google Maps 中实现 Uber 式 Polyline 折线动画的方案咨询
Flutter Uber风格Polyline路线绘制动画实现方案
现有思路梳理
目前已尝试两种实现思路,但都存在问题:
- 通过循环结合定时器逐点绘制路线的所有坐标点:性能开销较高,路线点数量多的时候会出现明显卡顿
- 通过canvas直接在两点间绘制简单曲线:可行性暂未验证
原生Android平台可通过overlays实现该效果,但Flutter目前仅支持tile overlays,无法直接复用原生实现逻辑。
效果参考:
可行实现方案
推荐使用CustomPainter搭配AnimationController的方案实现,性能远高于定时逐点绘制的方案,具体实现逻辑如下:
- 预处理坐标:在动画启动前,先将所有路线的经纬度坐标一次性转换为地图上对应的屏幕像素坐标,避免动画过程中重复计算消耗性能
- 配置动画控制器:创建取值范围为0~1的动画控制器,控制路线绘制的进度,动画时长可按需调整
- 自定义绘制逻辑:在
CustomPainter的paint方法中,根据当前动画进度截取对应比例的坐标点,用Path连接绘制路线,仅在动画进度更新时触发重绘
核心示例代码
import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; class AnimatedPolylinePainter extends CustomPainter { // 转换后的屏幕坐标点集合 final List<Offset> pathPoints; // 动画进度值 0~1 final double animationValue; // 路线画笔配置 final Paint polylinePaint = Paint() ..color = Colors.blueAccent ..strokeWidth = 5 ..style = PaintingStyle.stroke ..strokeCap = StrokeCap.round; AnimatedPolylinePainter({ required this.pathPoints, required this.animationValue }); @override void paint(Canvas canvas, Size size) { if (pathPoints.isEmpty) return; Path path = Path(); // 根据动画进度计算需要绘制的点数量 int targetPointCount = (pathPoints.length * animationValue).round(); for (int i = 0; i < targetPointCount; i++) { if (i == 0) { path.moveTo(pathPoints[i].dx, pathPoints[i].dy); } else { path.lineTo(pathPoints[i].dx, pathPoints[i].dy); } } canvas.drawPath(path, polylinePaint); } @override bool shouldRepaint(covariant AnimatedPolylinePainter oldDelegate) { return oldDelegate.animationValue != animationValue; } }
注意事项
- 经纬度转屏幕坐标可调用谷歌地图插件的
GoogleMapController.getScreenCoordinate(LatLng)方法实现,当地图视角发生缩放、拖动变化时,需要重新计算坐标点触发重绘 - 若需要平滑曲线路线效果,可使用
Path.quadraticBezierTo方法实现两点间的曲线过渡,不需要拆分大量微线段绘制 - 如需同步实现车辆/标记点沿路线移动的效果,可在动画回调中根据当前进度获取对应坐标点,更新标记点位置即可
内容的提问来源于stack exchange,提问作者Krish Bhanushali
相关产品推荐
相关产品推荐

