Swift 4中如何在Google Maps实现相机沿Polyline动画?
实现Google Maps相机沿折线的动画效果(Swift 4)
嘿,我来帮你搞定这个需求!你已经有了折线编码字符串(示例:s_~fGwyptMSkFnBK),并且写好了基础的折线加载代码:
let polyline = GMSPolyline(path: GMSPath(fromEncodedPath:polylineString)) polyline.map = self.mapView
下面给你两种实用的实现方案,从基础到进阶,按需选择:
方案一:逐顶点跳转的基础动画
这个方案简单直接,让相机沿着折线的每个顶点依次移动,适合快速实现需求:
- 首先从编码路径中提取所有的坐标点
- 用定时器逐个更新相机位置,控制每个点的移动时长
// 1. 提取折线的所有坐标点 guard let path = GMSPath(fromEncodedPath: polylineString) else { print("Invalid polyline string") return } var coordinateArray = [CLLocationCoordinate2D]() for index in 0..<path.count() { coordinateArray.append(path.coordinate(at: index)) } // 2. 设置动画参数并启动定时器 let moveDuration: TimeInterval = 0.6 // 每个顶点间的动画时长 var currentPointIndex = 0 let animationTimer = Timer.scheduledTimer(withTimeInterval: moveDuration, repeats: true) { timer in guard currentPointIndex < coordinateArray.count else { timer.invalidate() // 动画结束,停止定时器 return } // 更新相机位置 let targetCoord = coordinateArray[currentPointIndex] let targetCamera = GMSCameraPosition.camera(withTarget: targetCoord, zoom: 15) self.mapView.animate(to: targetCamera) currentPointIndex += 1 } // 记得在合适的时机(比如页面销毁)销毁定时器,避免内存泄漏 // animationTimer.invalidate()
方案二:流畅的连续路径动画
如果想要更自然的平滑移动(不是跳点,而是沿着路径连续滑动),可以结合CATransaction来控制动画曲线和完成回调:
guard let path = GMSPath(fromEncodedPath: polylineString) else { return } let totalAnimationDuration: TimeInterval = 12.0 // 整个动画的总时长 let totalSteps = path.count() - 1 if totalSteps <= 0 { return } var currentStep = 0 let stepDuration = totalAnimationDuration / Double(totalSteps) // 递归实现连续动画 func animateToNextSegment() { guard currentStep < totalSteps else { return } let startCoord = path.coordinate(at: currentStep) let endCoord = path.coordinate(at: currentStep + 1) // 使用CATransaction自定义动画属性 CATransaction.begin() CATransaction.setAnimationDuration(stepDuration) // 用缓动函数让动画更自然 CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .easeInEaseOut)) // 更新相机到下一个点 let targetCamera = GMSCameraPosition.camera(withTarget: endCoord, zoom: 15, bearing: 0, viewingAngle: 0) self.mapView.animate(to: targetCamera) // 当前段动画完成后,启动下一段 CATransaction.setCompletionBlock { currentStep += 1 self.animateToNextSegment() } CATransaction.commit() } // 启动动画 animateToNextSegment()
额外优化小技巧
- 动态时长:可以根据折线的实际长度(计算所有点的距离总和)来动态设置总时长,避免长折线动画太快或短折线动画太慢
- 朝向跟随:如果需要相机始终朝向前进方向,可以计算相邻两点的方位角,设置
GMSCameraPosition的bearing参数 - 性能优化:对于超长折线,可以每隔几个点取一个关键节点,减少动画步数,提升流畅度
内容的提问来源于stack exchange,提问作者Dima Nizanov
相关产品推荐
相关产品推荐

