简体   繁体   English

平滑运动的 GMap 轴承旋转(在更改轴承值时避免抖动效应)

[英]GMap Bearing rotation in smooth motion (avoid jerky effect when changing bearing values)

I want to rotate GMap by changing the bearing angle value, so the camera rotates around the center point (360-Degree one full round ).我想通过改变方位角值来旋转 GMap,所以相机围绕中心点旋转(360 度一整圈)。 When we change the bearing, there is a easing effect at camera start and end points.当我们改变方位时,在相机起点和终点会有一个缓动效果。 How can I control/change that in order to make the rotation smooth when change Bearing values (in order to rotate map in 360 Degree, smooth animation)?我如何控制/更改它以便在更改Bearing值时使旋转平滑(以便以 360 度旋转地图,平滑动画)?

Required this for all languages as it appears the easing effect is different in different language libraries.所有语言都需要这样做,因为不同语言库中的缓动效果似乎不同。 eg Swift, Android, PHP, JS, Node.js, React.例如 Swift、Android、PHP、JS、Node.js、React。

Swift Example (running OK in Linear Animation): Swift 示例(在线性动画中运行正常):

Note that initially the animation did had jerks in iOS as well, but when we make use of CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear along its CATransaction properties then the GMap animation turned into smooth animation. so now if you see the code below, the change in Bearing value does not create jerky effect (due to the easing effect in GMap animation). I am looking for appropriate solution for Android and Web as well.请注意,最初动画在 iOS 中也确实有CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear ,但是当我们使用CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear沿其CATransaction属性时,GMap 动画变成了平滑动画。所以现在如果你看到下面的代码, Bearing的变化value 不会产生生涩的效果(由于 GMap 动画中的缓动效果)。我也在为AndroidWeb寻找合适的解决方案。

//Move the map around current location, first loop
let timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
CATransaction.begin()
CATransaction.setValue(3.0, forKey: kCATransactionAnimationDuration)
CATransaction.setAnimationTimingFunction(timingFunction)
CATransaction.setCompletionBlock({
    //Move the map around current location, second loop
    let timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
    CATransaction.begin()
    CATransaction.setValue(3.0, forKey: kCATransactionAnimationDuration)
    CATransaction.setAnimationTimingFunction(timingFunction)
    CATransaction.setCompletionBlock({
        //Move the map around current location, third loop
        let timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
        CATransaction.begin()
        CATransaction.setValue(3.0, forKey: kCATransactionAnimationDuration)
        CATransaction.setAnimationTimingFunction(timingFunction)
        CATransaction.setCompletionBlock({
            UIView.animate(withDuration: 0.5, animations: {
                self.findingYourLocation.alpha = 0.0
            })
            //TODO: Set nearest branch
            // Zoom in one zoom level
            let zoomCamera = GMSCameraUpdate.zoomIn()
            self.mapView.animate(with: zoomCamera)

            // Center the camera on UBL Branch when animation finished
            //let nearestBranch = CLLocationCoordinate2D(latitude: 24.850751, longitude: 67.016589)
            let nearestBranch = CLLocationCoordinate2D.init(latitude: 24.806849, longitude: 67.038734)
            let nearestBranchCam = GMSCameraUpdate.setTarget(nearestBranch)



            CATransaction.begin()

            let timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
            CATransaction.setValue(3.0, forKey: kCATransactionAnimationDuration)
            CATransaction.setAnimationTimingFunction(timingFunction)
            CATransaction.setCompletionBlock({
                self.nextButton.alpha = 1.0
            })
            self.mapView.animate(with: nearestBranchCam)
            self.mapView.animate(toZoom: 15)
            self.mapView.animate(toBearing: 0)
            self.mapView.animate(toViewingAngle: 0)

            CATransaction.commit()

        })
        self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
        CATransaction.commit()

    })
    self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
    CATransaction.commit()

})
self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
CATransaction.commit()

The Android example code (has problem): Android 示例代码(有问题):

The Android example/sample code can be found here: https://issuetracker.google.com/issues/71738889可以在此处找到 Android 示例/示例代码: https : //issuetracker.google.com/issues/71738889

Which also includes an .apk file, an .mp4 video of sample app output.其中还包括一个.apk文件,一个示例应用程序输出的.mp4视频。 Which clearly shows jerky effects when Bearing value changes while rotating the map in 360-Degree.这清楚地显示了在 360 度旋转地图时Bearing值发生变化时的抖动效果。

Giving this as an answer as a comment would be rather hard to read;将其作为评论的答案将很难阅读; this is taken from the google documentation .这是从谷歌文档中获取的

Consider this code:考虑这个代码:

CameraPosition cameraPosition = new CameraPosition.Builder()
    .target(MOUNTAIN_VIEW)      // Sets the center of the map to Mountain View
    .zoom(17)                   // Sets the zoom
    .bearing(90)                // Sets the orientation of the camera to east
    .tilt(30)                   // Sets the tilt of the camera to 30 degrees
    .build();                   // Creates a CameraPosition from the builder
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

This code creates a new camera position, and that's exactly what you're trying to mutate: the bearing of the camera.这段代码创建了一个新的相机位置,这正是您想要改变的:相机的方位。 So if you create a new camera position like this:因此,如果您像这样创建一个新的相机位置:

CameraPosition cameraPosition = new CameraPosition.Builder()
    .bearing(50)
    .build();

and then animate the camera to that position:然后将相机动画到该位置:

map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

That should do the trick.那应该可以解决问题。 To give some more information on what you will need to use as bearing:要提供有关您需要用作轴承的更多信息:

a bearing of 90 degrees results in a map where the upwards direction points due east. 90 度的方位角导致地图向上指向正东。

Good luck.祝你好运。

I'm going to write this as another answer as I'd like to take the time to write a wall of text, whereas I'd like to keep the other answer as short as possible since it might still help other people with a similar problem.我将把它写成另一个答案,因为我想花时间写一堵文字墙,而我想保持另一个答案尽可能短,因为它可能仍然帮助其他有类似情况的人问题。

The problem问题

So if I understand correctly, what you're trying to do is build an application with Google maps for different platforms.因此,如果我理解正确的话,您要做的是为不同平台构建一个带有谷歌地图的应用程序。 You're running into an issue with Google maps (the jerky movement) and you're trying to find a fix for all the platforms.您遇到了 Google 地图的问题(生涩的运动),并且您正在尝试为所有平台找到修复程序。

My proposed solutions我提出的解决方案

I'll divide this into a few sections, because I see different ways to go forward.我将把它分成几个部分,因为我看到了不同的前进方式。

  • Find a solution for all the platforms.找到适用于所有平台的解决方案。

This one seems like the most straightforward, but it could be akin to the XY problem.这似乎是最直接的,但它可能类似于 XY 问题。 I've tried to introduce you to some ways of animating views, and you've solved the problem in your iOS app, but at the core what you're dealing with is a flaw in the Google maps animation when changing the bearing.我试图向您介绍一些动画视图的方法,并且您已经解决了 iOS 应用程序中的问题,但您处理的核心问题是更改方位时 Google 地图动画中的缺陷。 I am not sure if there is a way to tackle this problem on every platform, as I haven't tried.我不确定是否有办法在每个平台上解决这个问题,因为我还没有尝试过。

  • Use a different map使用不同的地图

This sounds like a big step, and depending on your usage something you don't want to do.这听起来像是迈出了一大步,根据您的使用情况,您不想做一些事情。 However, I've successfully used Leaflet (a JS map) with a WKWebView on iOS and Android and that all worked pretty well (this obviously also works fine in the browser).但是,我已经在 iOS 和 Android 上成功地将 Leaflet(一个 JS 地图)与 WKWebView 一起使用,并且一切都运行良好(这显然在浏览器中也可以正常工作)。 Keep in mind that some other maps might also have the jerky animation.请记住,其他一些地图也可能有生涩的动画。

Wrapping it up包起来

I hope I've given some insight.我希望我已经给出了一些见解。 I'll add to this answer as we find out new things about the problem.当我们发现有关该问题的新事物时,我将添加到此答案中。 Could you try to provide a minimal reproducible example?您能否尝试提供一个最小的可重复示例? That way I can give it a better try.这样我才能更好地尝试。 Good luck!祝你好运!

After going through all possible cases, I came to know that GMap is not built with required feature of Rotating map in 360-Degree in one go with custom animation.在经历了所有可能的情况后,我开始知道GMap没有使用自定义动画一次性 360 度旋转地图所需的功能构建。 Don't know if this appears in next GMap api version.不知道这是否会出现在下一个GMap api 版本中。

For now, the possible solution is to change the animation logic, and instead of rotating 360-Degree we can rotate to eg 180-Degree with reduced animation speed (animation duration time).目前,可能的解决方案是更改动画逻辑,而不是旋转 360 度,我们可以旋转到例如 180 度并降低动画速度(动画持续时间)。

This allows us to bring required map surrounding search experience to the user.这使我们能够为用户带来所需的地图周边搜索体验。

(For now I am posting this temporary answer, and allow others to update or post latest answer in future). (现在我发布这个临时答案,并允许其他人在未来更新或发布最新答案)。


I have submitted this animation control issue on GMap issue tracker, please START this issue in order to show your interest and feedback, so Google team can take this feature into their final consideration.我已在 GMap 问题跟踪器上提交了此动画控制问题,请开始此问题以显示您的兴趣和反馈,以便 Google 团队可以将此功能纳入最终考虑。 https://issuetracker.google.com/u/1/issues/71738889 https://issuetracker.google.com/u/1/issues/71738889

Here is my approach:这是我的方法:

  • tilt = 45f倾斜 = 45f
  • zoom = 18缩放 = 18
  • target = currentLocation目标 = 当前位置
  • bearing = lastKnownLocation.bearingTo(currentLocation)轴承 = lastKnownLocation.bearingTo(currentLocation)
  1. Use map.animateCamera();使用 map.animateCamera(); // instead of move camera // 而不是移动相机
CameraPosition cameraPosition;
        if (currentLocation.distanceTo(lastKnownLocation) > 50) {
            cameraPosition = new CameraPosition.Builder()
                    .target(currentLatLng).zoom(20).tilt(45f).bearing(bearingValue).build();
        } else {
            cameraPosition = new CameraPosition.Builder()
                    .target(currentLatLng).zoom(20).tilt(45f).build();
        }

        map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

What else you have to do?你还需要做什么? You must call this method from LocationCallback (where you are getting location updates) and then we can have a smooth experience.您必须从 LocationCallback(获取位置更新的位置)调用此方法,然后我们才能获得流畅的体验。

So if the user moved (walked or driving) and the distance between lastKnownLocation and currentLocation is greater than 50 meters then only we will set bearing otherwise we keep changing the targetLocation only.因此,如果用户移动(步行或开车)并且 lastKnownLocation 和 currentLocation 之间的距离大于 50 米,那么我们只会设置方位,否则我们只会继续更改 targetLocation。

In this way, we can show heading direction like in google maps.通过这种方式,我们可以像谷歌地图一样显示航向方向。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM