像UBER一样在谷歌地图上移动GMSMarker

时间:2016-09-08 05:41:46

标签: ios objective-c google-maps google-maps-markers

我正在谷歌地图上开发一些导航任务。我必须移动标记,因为车辆在他们的应用中像转向一样转动。我尝试了@SO上提供的不同解决方案,但它不能正常工作。

我正在使用当前纬度/经度与之前的纬度/经度成角度并使用该旋转动画mapwithBearing

这是代码

[CATransaction begin];
[CATransaction setAnimationDuration:2.0];
NSDictionary *data = [[result objectForKey:@"returnData"] objectForKey:@"data"];
if (![data isEqual: [NSNull null]]) {
    driverLocationCoordinate = CLLocationCoordinate2DMake([[data objectForKey:@"lat"] doubleValue], [[data objectForKey:@"lng"] doubleValue]);
    driverMarker.position = driverLocationCoordinate;

    GMSCameraPosition * camera = [GMSCameraPosition cameraWithLatitude:driverLocationCoordinate.latitude
                                                                     longitude:driverLocationCoordinate.longitude
                                                                          zoom:16];

    mapHomeView.camera = camera;


    if ([data objectForKey:@"preLat"] != [NSNull null] && [data objectForKey:@"preLng"] !=[NSNull null]){
        if ([[data objectForKey:@"preLat"] floatValue] != 0.0f && [[data objectForKey:@"preLng"] floatValue] != 0.0f) {
            NSLog(@"pre_lat = %f and pre_lng = %f", [[data objectForKey:@"preLat"] floatValue], [[data objectForKey:@"preLng"] floatValue]);
            CLLocationCoordinate2D previousCoordinates = CLLocationCoordinate2DMake([[data objectForKey:@"preLat"] floatValue], [[data objectForKey:@"preLng"] floatValue]);

        driverMarker.rotation = [self DegreeBearing:previousCoordinates locationB:driverMarker.position];
        [mapHomeView animateToBearing:driverMarker.rotation];
        }
    }

    [CATransaction commit];

我刚刚从另一个@SO帖子中获取了学位代码,当我在直路上但是当汽车静止或转弯时它起作用,它会闪烁

以下是从另一个SO帖子获取角度的代码。

-(double) DegreeBearing:(CLLocationCoordinate2D) A locationB: (CLLocationCoordinate2D)B{
    double dlon = [self ToRad:(B.longitude - A.longitude) ];
    double dPhi = log(tan([self ToRad:(B.latitude)] / 2 + M_PI / 4) / tan([self ToRad:(A.latitude)] / 2 + M_PI / 4));
    if  (fabs(dlon) > M_PI){
        dlon = (dlon > 0) ? (dlon - 2*M_PI) : (2*M_PI + dlon);
    }
    return [self ToBearing:(atan2(dlon, dPhi))];
}

-(double) ToRad: (double)degrees{
    return degrees*(M_PI/180);
}

-(double) ToBearing:(double)radians{
    return [self ToDegrees:radians] + 360 % 360;
}

-(double) ToDegrees: (double)radians{
    return radians * 180 / M_PI;
}

任何人都可以提供帮助或提出任何其他解决方案吗?

1 个答案:

答案 0 :(得分:9)

如何使用此代码。您可以尝试使用此代码进行一些逻辑更改。但是,它会正常工作。

CLLocationCoordinate2D oldCoodinate = CLLocationCoordinate2DMake([[data valueForKey:@"lat"]doubleValue],[[data valueForKey:@"lng"]doubleValue]);
CLLocationCoordinate2D newCoodinate = CLLocationCoordinate2DMake([[data valueForKey:@"lat"]doubleValue],[[data valueForKey:@"lng"]doubleValue]);

driverMarker.groundAnchor = CGPointMake(0.5, 0.5);
driverMarker.rotation = [self getHeadingForDirectionFromCoordinate:oldCoodinate toCoordinate:newCoodinate]; //found bearing value by calculation when marker add
driverMarker.position = oldCoodinate; //this can be old position to make car movement to new position
driverMarker.map = mapView_;

//marker movement animation
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:2.0] forKey:kCATransactionAnimationDuration];
[CATransaction setCompletionBlock:^{
    driverMarker.groundAnchor = CGPointMake(0.5, 0.5);
    driverMarker.rotation = [[data valueForKey:@"bearing"] doubleValue]; //New bearing value from backend after car movement is done
}];

driverMarker.position = newCoodinate; //this can be new position after car moved from old position to new position with animation
driverMarker.map = mapView_;
driverMarker.groundAnchor = CGPointMake(0.5, 0.5);
driverMarker.rotation = [self getHeadingForDirectionFromCoordinate:oldCoodinate toCoordinate:newCoodinate]; //found bearing value by calculation
[CATransaction commit];

在.h文件中定义这两个

#define degreesToRadians(x) (M_PI * x / 180.0)
#define radiansToDegrees(x) (x * 180.0 / M_PI)

从旧坐标和新坐标获取方位值的方法

- (float)getHeadingForDirectionFromCoordinate:(CLLocationCoordinate2D)fromLoc toCoordinate:(CLLocationCoordinate2D)toLoc
{
    float fLat = degreesToRadians(fromLoc.latitude);
    float fLng = degreesToRadians(fromLoc.longitude);
    float tLat = degreesToRadians(toLoc.latitude);
    float tLng = degreesToRadians(toLoc.longitude);

    float degree = radiansToDegrees(atan2(sin(tLng-fLng)*cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(tLng-fLng)));

    if (degree >= 0) {
        return degree;
    } else {
        return 360+degree;
    }
}

Swift 3.1

     var oldCoodinate: CLLocationCoordinate2D? = CLLocationCoordinate2DMake(CDouble((data.value(forKey: "lat") as? CLLocationCoordinate2D)), CDouble((data.value(forKey: "lng") as? CLLocationCoordinate2D)))
        var newCoodinate: CLLocationCoordinate2D? = CLLocationCoordinate2DMake(CDouble((data.value(forKey: "lat") as? CLLocationCoordinate2D)), CDouble((data.value(forKey: "lng") as? CLLocationCoordinate2D)))
        driverMarker.groundAnchor = CGPoint(x: CGFloat(0.5), y: CGFloat(0.5))
        driverMarker.rotation = getHeadingForDirection(fromCoordinate: oldCoodinate, toCoordinate: newCoodinate)
        //found bearing value by calculation when marker add
        driverMarker.position = oldCoodinate
        //this can be old position to make car movement to new position
        driverMarker.map = mapView_
        //marker movement animation
        CATransaction.begin()
        CATransaction.setValue(Int(2.0), forKey: kCATransactionAnimationDuration)
        CATransaction.setCompletionBlock({() -> Void in
            driverMarker.groundAnchor = CGPoint(x: CGFloat(0.5), y: CGFloat(0.5))
            driverMarker.rotation = CDouble(data.value(forKey: "bearing"))
            //New bearing value from backend after car movement is done
        })
        driverMarker.position = newCoodinate
        //this can be new position after car moved from old position to new position with animation
        driverMarker.map = mapView_
        driverMarker.groundAnchor = CGPoint(x: CGFloat(0.5), y: CGFloat(0.5))
        driverMarker.rotation = getHeadingForDirection(fromCoordinate: oldCoodinate, toCoordinate: newCoodinate)
        //found bearing value by calculation
        CATransaction.commit()
extension Int {
    var degreesToRadians: Double { return Double(self) * .pi / 180 }
}
extension FloatingPoint {
    var degreesToRadians: Self { return self * .pi / 180 }
    var radiansToDegrees: Self { return self * 180 / .pi }
}
func getHeadingForDirection(fromCoordinate fromLoc: CLLocationCoordinate2D, toCoordinate toLoc: CLLocationCoordinate2D) -> Float {

        let fLat: Float = Float((fromLoc.latitude).degreesToRadians)
        let fLng: Float = Float((fromLoc.longitude).degreesToRadians)
        let tLat: Float = Float((toLoc.latitude).degreesToRadians)
        let tLng: Float = Float((toLoc.longitude).degreesToRadians)
        let degree: Float = (atan2(sin(tLng - fLng) * cos(tLat), cos(fLat) * sin(tLat) - sin(fLat) * cos(tLat) * cos(tLng - fLng))).radiansToDegrees
        if degree >= 0 {
            return degree
        }
        else {
            return 360 + degree
        }
    }

for github link:ARCarMovement