ios - 像 UBER 一样在 Google map 上移动 GMSMarker

标签 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;
}

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

最佳答案

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

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
        }
    }

github 链接:ARCarMovement

关于ios - 像 UBER 一样在 Google map 上移动 GMSMarker,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39383324/

相关文章:

ios - Swift 4 中的 UIImagePickerController 内存泄漏 Xcode 9

ios - 从 UIView 动画中获取 UIImage

android - Unity 3D Mobile 和 Windows Azure

ios - Swift-TableView中的按钮崩溃

objective-c - 单击按钮后如何显示 TableView 单元格值?

javascript - Google Maps Geocode-处理异步调用

javascript - 未处理的 promise 拒绝: TypeError: undefined is not a function evaluating 'departureloc.map' occurs when mapping for setState in react native

java - 无法启动 Activity ComponentInfo{Activity} : android. view.InflateException:二进制 XML 文件行 #12:膨胀类 fragment 时出错

objective-c - 以编程方式将菜单+项目添加到 NSPopupButton

ios - 排序 Mapbox 注释