I have created animated polyline like CAShapeLayer by following code, I have added CAShapeLayer as sublayer to GMSMapiew but, if I move the map the layer won\'t moves. wher
You can create a variable for shapeLayer and use the GMSMapViewDelegate methods mapView(_ mapView: GMSMapView, willMove gesture: Bool) and mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) to add and remove the layer from the map. There are two downsides to this approach, first is that the layer doesn't animate when the map is being dragged(moved) and second downside is that the layer always sits on top of all other map elements like markers, road names, POIs etc. I couldn't find a way to add this layer as a sublayer directly to the ground overlay. You can find the full code below:
var polyLineShapeLayer:CAShapeLayer?
var layerAdded = false
var path = GMSPath()
var polyLine:GMSPolyline!
// Add regular polyline to the map
func addPolyLineWithEncodedStringInMap(_ encodedString:String) {
self.polyLine = GMSPolyline(path: self.path)
polyLine.strokeWidth = 3.8
self.polyLine.strokeColor = .black
polyLine.map = googleMapView
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
self.addPolyLineShapeLayerToMapView()
self.layerAdded = true
}
}
// Add CAshapeLayer to map
func layer(from path: GMSPath) -> CAShapeLayer {
let breizerPath = UIBezierPath()
let firstCoordinate: CLLocationCoordinate2D = path.coordinate(at: 0)
breizerPath.move(to: self.googleMapView.projection.point(for: firstCoordinate))
for i in 1 ..< Int((path.count())){
print(path.coordinate(at: UInt(i)))
let coordinate: CLLocationCoordinate2D = path.coordinate(at: UInt(i))
breizerPath.addLine(to: self.googleMapView.projection.point(for: coordinate))
}
let shapeLayer = CAShapeLayer()
shapeLayer.path = breizerPath.cgPath
shapeLayer.strokeColor = UIColor.lightGray.withAlphaComponent(0.8).cgColor
shapeLayer.lineWidth = 4.0
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineJoin = kCALineJoinRound
shapeLayer.lineCap = kCALineCapRound
shapeLayer.cornerRadius = 5
return shapeLayer
}
func animatePath(_ layer: CAShapeLayer) {
let pathAnimation = CABasicAnimation(keyPath: "strokeEnd")
pathAnimation.duration = 2
pathAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
pathAnimation.fromValue = Int(0.0)
pathAnimation.toValue = Int(1.0)
pathAnimation.repeatCount = 200
layer.add(pathAnimation, forKey: "strokeEnd")
}
func addPolyLineShapeLayerToMapView(){
polyLineShapeLayer = self.layer(from: self.path)
if let polyLineShapeLayer = polyLineShapeLayer{
self.animatePath(polyLineShapeLayer)
self.googleMapView.layer.addSublayer(polyLineShapeLayer)
polyLineShapeLayer.zPosition = 0
}
}
// Delegate methods to control the polyline
// whenever map is about to move, if layer is already added, remove the layer from superLayer
func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
if layerAdded{
DispatchQueue.main.async {
self.polyLineShapeLayer?.removeFromSuperlayer()
self.polyLineShapeLayer = nil
}
}
}
// when map is idle again(var layerAdded:bool ensures that additional layer is not added initially when the delegate method is fired) add new instance of polylineShapeLayer to the map with current projected coordinates.
func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) {
if self.layerAdded{
self.addPolyLineShapeLayerToMapView()
}
}