ios - rutas - trazar ruta en google maps android studio
¿Cómo obtener una ruta de polilínea animada en GMSMapView, para que se mueva junto con el mapa cuando se mueve el mapa? (6)
He creado una polilínea animada como CAShapeLayer siguiendo el código, he agregado CAShapeLayer como subcapa a GMSMapiew pero, si muevo el mapa, la capa no se moverá. ¿Dónde agregar la capa, para que se mueva junto con el mapa?
func layer(from path: GMSPath) -> CAShapeLayer {
let breizerPath = UIBezierPath()
let firstCoordinate: CLLocationCoordinate2D = path.coordinate(at: 0)
breizerPath.move(to: self.mapView.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.mapView.projection.point(for: coordinate))
}
let shapeLayer = CAShapeLayer()
shapeLayer.path = breizerPath.reversing().cgPath
shapeLayer.strokeColor = UIColor.green.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 = 6
//pathAnimation.delegate = self
pathAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
pathAnimation.fromValue = Int(0.0)
pathAnimation.toValue = Int(1.0)
pathAnimation.repeatCount = 100
layer.add(pathAnimation, forKey: "strokeEnd")
}
Añadido a GoogleMapView por
let shapelayer: CAShapeLayer = self.layer(from: path!)
self.animatePath(shapelayer)
self.mapView.layer.addSublayer(shapelayer)
Esta es una adaptación del código de Elangovan.
Los cambios que hice fueron eliminar la var de la clase para estar solo en la función y también quitar el #selector que ya no es necesario en iOS> = 10 .
var timerAnimation: Timer!
var mapView:GMSMapView?
func drawRoute(encodedString: String, animated: Bool) {
if let path = GMSMutablePath(fromEncodedPath: encodedString) {
let polyline = GMSPolyline(path: path)
polyline.strokeWidth = 3.0
polyline.strokeColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5)
polyline.map = Singleton.shared.getMapView()
if(animated){
self.animatePolylinePath(path: path)
}
}
}
func animatePolylinePath(path: GMSMutablePath) {
var pos: UInt = 0
var animationPath = GMSMutablePath()
let animationPolyline = GMSPolyline()
self.timerAnimation = Timer.scheduledTimer(withTimeInterval: 0.003, repeats: true) { timer in
pos += 1
if(pos >= path.count()){
pos = 0
animationPath = GMSMutablePath()
animationPolyline.map = nil
}
animationPath.add(path.coordinate(at: pos))
animationPolyline.path = animationPath
animationPolyline.strokeColor = UIColor.yellow
animationPolyline.strokeWidth = 3
animationPolyline.map = self.mapView
}
}
func stopAnimatePolylinePath() {
self.timerAnimation.invalidate()
}
Mueva la capa siempre que el mapa se mueva implementando el delegado mapView:didChangeCameraPosition:
Necesitas usar GMSPolyline
para esto. Cree una instancia de GMSPolyline
, configure su instancia de GMSMapView
para que sea su mapa principal.
GMSPolyline* routeOverlay = // config
routeOverlay.map = // my GMSMapView instance
Eso es todo. No necesita hacer nada adicional para que se mueva con el movimiento de la cámara del mapa. Lo hace automáticamente.
Puede crear una variable para shapeLayer y usar los métodos GMSMapViewDelegate mapView (_ mapView: GMSMapView, willMove gesto: Bool) y mapView (_ mapView: GMSMapView, idleAt position: GMSCameraPosition) para agregar y eliminar la capa del mapa. Este enfoque tiene dos inconvenientes, primero es que la capa no se anima cuando el mapa se está arrastrando (moviendo) y la segunda desventaja es que la capa siempre se encuentra encima de todos los demás elementos del mapa como marcadores, nombres de carreteras, PDI, etc. No pude encontrar una manera de agregar esta capa como subcapa directamente a la superposición del suelo. Puedes encontrar el código completo a continuación:
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()
}
}
Soy crear animación GMSPath
con coordinate
ruta.
C objetivo
interfaz
@interface MapWithTracking ()
@property (weak, nonatomic) IBOutlet GMSMapView *mapView;
@property (nonatomic,strong) GMSMutablePath *path2;
@property (nonatomic,strong)NSMutableArray *arrayPolylineGreen;
@property (nonatomic,strong) GMSPolyline *polylineBlue;
@property (nonatomic,strong) GMSPolyline *polylineGreen;
@end
implementación
-(void)viewDidLoad {
_arrayPolylineGreen = [[NSMutableArray alloc] init];
_path2 = [[GMSMutablePath alloc]init];
}
Consigue un GMSPath
y crea una polilínea azul.
-(void)createBluePolyline(GMSPath *path) {
// Here create a blue poly line
_polylineBlue = [GMSPolyline polylineWithPath:path];
_polylineBlue.strokeColor = [UIColor blueColor];
_polylineBlue.strokeWidth = 3;
_polylineBlue.map = _mapView;
// animate green path with timer
[NSTimer scheduledTimerWithTimeInterval:0.003 repeats:true block:^(NSTimer * _Nonnull timer) {
[self animate:path];
}];
}
Animar una polilínea verde
Añadiendo coordenadas a la ruta 2 y asignando al mapa
-(void)animate:(GMSPath *)path {
dispatch_async(dispatch_get_main_queue(), ^{
if (i < path.count) {
[_path2 addCoordinate:[path coordinateAtIndex:i]];
_polylineGreen = [GMSPolyline polylineWithPath:_path2];
_polylineGreen.strokeColor = [UIColor greenColor];
_polylineGreen.strokeWidth = 3;
_polylineGreen.map = _mapView;
[arrayPolylineGreen addObject:_polylineGreen];
i++;
}
else {
i = 0;
_path2 = [[GMSMutablePath alloc] init];
for (GMSPolyline *line in arrayPolylineGreen) {
line.map = nil;
}
}
});
}
RÁPIDO
Declaración
var polyline = GMSPolyline()
var animationPolyline = GMSPolyline()
var path = GMSPath()
var animationPath = GMSMutablePath()
var i: UInt = 0
var timer: Timer!
A la ruta de darw
func drawRoute(routeDict: Dictionary<String, Any>) {
let routesArray = routeDict ["routes"] as! NSArray
if (routesArray.count > 0)
{
let routeDict = routesArray[0] as! Dictionary<String, Any>
let routeOverviewPolyline = routeDict["overview_polyline"] as! Dictionary<String, Any>
let points = routeOverviewPolyline["points"]
self.path = GMSPath.init(fromEncodedPath: points as! String)!
self.polyline.path = path
self.polyline.strokeColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5)
self.polyline.strokeWidth = 3.0
self.polyline.map = self.mapView
self.timer = Timer.scheduledTimer(timeInterval: 0.003, target: self, selector: #selector(animatePolylinePath), userInfo: nil, repeats: true)
}
}
Animar camino
func animatePolylinePath() {
if (self.i < self.path.count()) {
self.animationPath.add(self.path.coordinate(at: self.i))
self.animationPolyline.path = self.animationPath
self.animationPolyline.strokeColor = UIColor.black
self.animationPolyline.strokeWidth = 3
self.animationPolyline.map = self.mapView
self.i += 1
}
else {
self.i = 0
self.animationPath = GMSMutablePath()
self.animationPolyline.map = nil
}
}
No se olvide de detener el temporizador en la vista.
self.timer.invalidate()
Salida