I want to rotate GMap by changing the bearing angle value, so the camera rotates around the center point (360-Degree one full round ).
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)?
Required this for all languages as it appears the easing effect is different in different language libraries. e.g. Swift, Android, PHP, JS, Node.js, React.
Swift Example (running OK in Linear Animation):
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.
//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)
CATransactionmit()
})
self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
CATransactionmit()
})
self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
CATransactionmit()
})
self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
CATransactionmit()
The Android example code (has problem):
The Android example/sample code can be found here:
Which also includes an .apk
file, an .mp4
video of sample app output. Which clearly shows jerky effects when Bearing
value changes while rotating the map in 360-Degree.
I want to rotate GMap by changing the bearing angle value, so the camera rotates around the center point (360-Degree one full round ).
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)?
Required this for all languages as it appears the easing effect is different in different language libraries. e.g. Swift, Android, PHP, JS, Node.js, React.
Swift Example (running OK in Linear Animation):
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.
//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.mit()
})
self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
CATransaction.mit()
})
self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
CATransaction.mit()
})
self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
CATransaction.mit()
The Android example code (has problem):
The Android example/sample code can be found here: https://issuetracker.google./issues/71738889
Which also includes an .apk
file, an .mp4
video of sample app output. Which clearly shows jerky effects when Bearing
value changes while rotating the map in 360-Degree.
-
From a bit of googling you might want to set your heading to change the map rotation;
map.setHeading(<current heading> + <angle of rotation>)
. Let me know if this works! – JillevdW Commented Apr 3, 2018 at 12:10 - thanks for reply, I want to rotate this map view: developers.google./maps/documentation/android-api/… and not the imagery. Will appreciate if you prepare a demo example. – Nah Commented Apr 3, 2018 at 12:27
- Thanks for showing all your upvotes, to this issue. Google has finally taken this issue into their consideration and they will add this feature, if you hit star icon in order to show your interest: issuetracker.google./u/1/issues/71738889 – Nah Commented May 18, 2018 at 10:48
- Finally, the Google team had recently released support for above feature. Check above issue tracker link for solution details on the issue. – Nah Commented May 25, 2021 at 8:32
4 Answers
Reset to default 6 +50Giving this as an answer as a ment 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.
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.
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. 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. 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). 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. Don't know if this appears in next GMap
api version.
For now, the possible solution is to change the animation logic, and instead of rotating 360-Degree we can rotate to e.g. 180-Degree with reduced animation speed (animation duration time).
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. https://issuetracker.google./u/1/issues/71738889
Here is my approach:
- tilt = 45f
- zoom = 18
- target = currentLocation
- bearing = lastKnownLocation.bearingTo(currentLocation)
- Use 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.
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.
In this way, we can show heading direction like in google maps.