GMap 轴承旋转平稳运动(改变轴承值时避免抖动效果)
GMap Bearing rotation in smooth motion (avoid jerky effect when changing bearing values)
我想通过改变方位角值来旋转GMap,所以相机围绕中心点旋转(360度一整圈)。
当我们改变方位时,在相机的起点和终点会有缓和效果。我怎样才能 control/change 在更改 Bearing
值时使旋转平滑(以便 360 度旋转地图,平滑动画)?
所有语言都需要这个,因为在不同的语言库中缓动效果是不同的。例如Swift、Android、PHP、JS、Node.js、React.
Swift示例(运行线性动画中OK):
请注意,最初动画在 iOS 中也有抖动,但是当我们使用 CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear
及其 CATransaction
属性时,GMap 动画变成了流畅的动画。所以现在如果您看到下面的代码,Bearing
值的变化不会产生抖动效果(由于 GMap 动画中的缓动效果)。我也在为 Android
和 Web
寻找合适的解决方案。
//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()
Android示例代码(有问题):
Androidexample/sample代码可以在这里找到:https://issuetracker.google.com/issues/71738889
其中还包括一个 .apk
文件,一个示例应用程序输出的 .mp4
视频。当 360 度旋转地图时 Bearing
值发生变化时,这清楚地显示了抖动效果。
将此作为评论作为答案将很难阅读;这是取自 google documentation.
考虑这段代码:
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));
这段代码创建了一个新的相机位置,而这正是您要改变的:相机的方位。因此,如果您像这样创建一个新的相机位置:
CameraPosition cameraPosition = new CameraPosition.Builder()
.bearing(50)
.build();
然后将相机设置为该位置的动画:
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
这应该可以解决问题。要提供有关您需要用作轴承的更多信息:
a bearing of 90 degrees results in a map where the upwards direction points due east.
祝你好运。
我打算把这个作为另一个答案写下来,因为我想花时间写一整面文字,而我希望另一个答案尽可能简短,因为它可能仍然有帮助其他有类似问题的人。
问题
因此,如果我理解正确的话,您要做的是为不同平台构建一个具有 Google 地图的应用程序。您 运行 遇到了 Google 地图(不稳定的运动)的问题,并且您正在尝试为所有平台找到解决方案。
我提出的解决方案
我将把它分成几个部分,因为我看到了不同的前进方式。
- 找到适用于所有平台的解决方案。
这个看起来最简单,但它可能类似于 XY 问题。我已经尝试向您介绍一些动画视图的方法,并且您已经解决了 iOS 应用程序中的问题,但您要处理的核心问题是 Google改变方位时映射动画。我不确定是否有办法在每个平台上解决这个问题,因为我还没有尝试过。
- 使用不同的地图
这听起来像是一大步,并且根据您的使用情况,您可能不想做某些事情。但是,我已经成功地在 iOS 和 Android 上使用带有 WKWebView 的 Leaflet(JS 地图)并且一切正常(这显然在浏览器中也可以正常工作)。请记住,其他一些地图也可能有不稳定的动画。
总结
我希望我提供了一些见解。当我们发现有关该问题的新内容时,我将添加到此答案中。您能否尝试提供一个最小的可重现示例?这样我就可以更好地尝试一下。祝你好运!
在经历了所有可能的情况后,我才知道 GMap
没有使用自定义动画一次性 360 度旋转地图所需的功能构建。不知道下一个 GMap
api 版本会不会出现。
目前,可能的解决方案是更改动画逻辑,而不是旋转 360 度,我们可以旋转到例如180 度,动画速度降低(动画持续时间)。
这使我们能够为用户带来所需的地图周边搜索体验。
(目前我正在post这个临时答案,并允许其他人在将来更新或post最新答案)。
我已经在 GMap 问题跟踪器上提交了这个动画控制问题,请启动这个问题以表达您的兴趣和反馈,这样 Google 团队可以将这个功能纳入他们的最终考虑。
https://issuetracker.google.com/u/1/issues/71738889
这是我的方法:
- 倾斜 = 45f
- 缩放 = 18
- 目标=当前位置
- 轴承 = lastKnownLocation.bearingTo(当前位置)
- 使用map.animateCamera(); // 而不是移动相机
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));
您还需要做什么?
您必须从 LocationCallback(您正在获取位置更新的位置)调用此方法,然后我们才能获得流畅的体验。
因此,如果用户移动(步行或驾驶)并且 lastKnownLocation 和 currentLocation 之间的距离大于 50 米,那么我们将只设置方位角,否则我们只会继续更改 targetLocation。
这样,我们就可以像 google 地图一样显示航向。
我想通过改变方位角值来旋转GMap,所以相机围绕中心点旋转(360度一整圈)。
当我们改变方位时,在相机的起点和终点会有缓和效果。我怎样才能 control/change 在更改 Bearing
值时使旋转平滑(以便 360 度旋转地图,平滑动画)?
所有语言都需要这个,因为在不同的语言库中缓动效果是不同的。例如Swift、Android、PHP、JS、Node.js、React.
Swift示例(运行线性动画中OK):
请注意,最初动画在 iOS 中也有抖动,但是当我们使用 CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear
及其 CATransaction
属性时,GMap 动画变成了流畅的动画。所以现在如果您看到下面的代码,Bearing
值的变化不会产生抖动效果(由于 GMap 动画中的缓动效果)。我也在为 Android
和 Web
寻找合适的解决方案。
//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()
Android示例代码(有问题):
Androidexample/sample代码可以在这里找到:https://issuetracker.google.com/issues/71738889
其中还包括一个 .apk
文件,一个示例应用程序输出的 .mp4
视频。当 360 度旋转地图时 Bearing
值发生变化时,这清楚地显示了抖动效果。
将此作为评论作为答案将很难阅读;这是取自 google documentation.
考虑这段代码:
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));
这段代码创建了一个新的相机位置,而这正是您要改变的:相机的方位。因此,如果您像这样创建一个新的相机位置:
CameraPosition cameraPosition = new CameraPosition.Builder()
.bearing(50)
.build();
然后将相机设置为该位置的动画:
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
这应该可以解决问题。要提供有关您需要用作轴承的更多信息:
a bearing of 90 degrees results in a map where the upwards direction points due east.
祝你好运。
我打算把这个作为另一个答案写下来,因为我想花时间写一整面文字,而我希望另一个答案尽可能简短,因为它可能仍然有帮助其他有类似问题的人。
问题
因此,如果我理解正确的话,您要做的是为不同平台构建一个具有 Google 地图的应用程序。您 运行 遇到了 Google 地图(不稳定的运动)的问题,并且您正在尝试为所有平台找到解决方案。
我提出的解决方案
我将把它分成几个部分,因为我看到了不同的前进方式。
- 找到适用于所有平台的解决方案。
这个看起来最简单,但它可能类似于 XY 问题。我已经尝试向您介绍一些动画视图的方法,并且您已经解决了 iOS 应用程序中的问题,但您要处理的核心问题是 Google改变方位时映射动画。我不确定是否有办法在每个平台上解决这个问题,因为我还没有尝试过。
- 使用不同的地图
这听起来像是一大步,并且根据您的使用情况,您可能不想做某些事情。但是,我已经成功地在 iOS 和 Android 上使用带有 WKWebView 的 Leaflet(JS 地图)并且一切正常(这显然在浏览器中也可以正常工作)。请记住,其他一些地图也可能有不稳定的动画。
总结
我希望我提供了一些见解。当我们发现有关该问题的新内容时,我将添加到此答案中。您能否尝试提供一个最小的可重现示例?这样我就可以更好地尝试一下。祝你好运!
在经历了所有可能的情况后,我才知道 GMap
没有使用自定义动画一次性 360 度旋转地图所需的功能构建。不知道下一个 GMap
api 版本会不会出现。
目前,可能的解决方案是更改动画逻辑,而不是旋转 360 度,我们可以旋转到例如180 度,动画速度降低(动画持续时间)。
这使我们能够为用户带来所需的地图周边搜索体验。
(目前我正在post这个临时答案,并允许其他人在将来更新或post最新答案)。
我已经在 GMap 问题跟踪器上提交了这个动画控制问题,请启动这个问题以表达您的兴趣和反馈,这样 Google 团队可以将这个功能纳入他们的最终考虑。 https://issuetracker.google.com/u/1/issues/71738889
这是我的方法:
- 倾斜 = 45f
- 缩放 = 18
- 目标=当前位置
- 轴承 = lastKnownLocation.bearingTo(当前位置)
- 使用map.animateCamera(); // 而不是移动相机
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));
您还需要做什么? 您必须从 LocationCallback(您正在获取位置更新的位置)调用此方法,然后我们才能获得流畅的体验。
因此,如果用户移动(步行或驾驶)并且 lastKnownLocation 和 currentLocation 之间的距离大于 50 米,那么我们将只设置方位角,否则我们只会继续更改 targetLocation。
这样,我们就可以像 google 地图一样显示航向。