In my previous article, I explained how to make a marker move through Google Maps. In this one, I'd like to explain how to customize the icon and make it face the direction it's going on the road.
Here's where we left:
Customizing the icon
In order to customize the icon, we need to use the icon
property, which allows us to set the url, size and anchor.
const icon = {
url: 'https://images.vexels.com/media/users/3/154573/isolated/preview/bd08e000a449288c914d851cb9dae110-hatchback-car-top-view-silhouette-by-vexels.png',
scaledSize: new window.google.maps.Size(20, 20),
anchor: { x: 10, y: 10 }
}
The url
prop is a link to the image. If it has a transparent background, much better.
The scaledSize
prop will scale the image. In this case, to 20x20 pixels (where the first parameter is the width and the second is the height). In addition, the size
prop can be used, but it won't scale the image proportionally.
The anchor
image will determine specifically where in that point the image will be displayed. Picture this as a Cardesian coordinate system, where the center is your lat/long, and you can move the marker using the x
and y
keys. Now the car appears on the road!
Orientation
Now we need to make the car face the direction where it's headed. Right now, it does move, but it still look kinda static, right?
I apologize in advance, but I'm about to show you a hack. The Google Maps SDK for Javascript doesn't have a property where you can change the rotation of the marker. Instead, you'll have to modify the image and rotate it with CSS. Not very funny, but it's not that bad!
The degrees
Before rotating, we need to calculate how much we should rotate the image in degrees. The image that I'm using already has 90 degrees of rotation, so that needs to be taken into consideration. Google has a function that does the job for us. It's window.google.maps.geometry.spherical.computeHeading
.
As a reminder, we're rendering the car, which is between two lines, so we will use those two lines to determine where it's headed.
As a second reminder, we will update the marker's CSS, so we need to use componentDidUpdate
to update the marker once its position has been set.
componentDidUpdate = () => {
const distance = this.getDistance()
if (! distance) {
return
}
let progress = this.path.filter(coordinates => coordinates.distance < distance)
const nextLine = this.path.find(coordinates => coordinates.distance > distance)
let point1, point2
if (nextLine) {
point1 = progress[progress.length -1]
point2 = nextLine
} else {
// it's the end, so use the latest 2
point1 = progress[progress.length - 2]
point2 = progress[progress.length - 1]
}
const point1LatLng = new window.google.maps.LatLng(point1.lat, point1.lng)
const point2LatLng = new window.google.maps.LatLng(point2.lat, point2.lng)
const angle = window.google.maps.geometry.spherical.computeHeading(point1LatLng, point2LatLng)
console.log(angle)
}
Now we need to find the marker's element and rotate it. Remembering that the marker already had 90 degrees of rotation.
componentDidUpdate = () => {
const distance = this.getDistance()
if (! distance) {
return
}
let progress = this.path.filter(coordinates => coordinates.distance < distance)
const nextLine = this.path.find(coordinates => coordinates.distance > distance)
let point1, point2
if (nextLine) {
point1 = progress[progress.length -1]
point2 = nextLine
} else {
// it's the end, so use the latest 2
point1 = progress[progress.length - 2]
point2 = progress[progress.length - 1]
}
const point1LatLng = new window.google.maps.LatLng(point1.lat, point1.lng)
const point2LatLng = new window.google.maps.LatLng(point2.lat, point2.lng)
const angle = window.google.maps.geometry.spherical.computeHeading(point1LatLng, point2LatLng)
const actualAngle = angle - 90
const markerUrl = 'https://images.vexels.com/media/users/3/154573/isolated/preview/bd08e000a449288c914d851cb9dae110-hatchback-car-top-view-silhouette-by-vexels.png'
const marker = document.querySelector(`[src="${markerUrl}"]`)
if (marker) { // when it hasn't loaded, it's null
marker.style.transform = `rotate(${actualAngle}deg)`
}
}
}
Thank you for reading!
Top comments (7)
Hey Luis, great content man. I have one requirement where I should be showing the journey of the person from point A to B. The thing here is I also wan't this journey to be download as a video. Any suggestions on this part
is there any github repo of this code?
Thanks for such a great article!
but how to appy this in live project..can you please give any suggestion as i want to track vehicle in realtime and facing chellenge in vehicle direction(heading)
Hi! Sorry for the late response. I'm not sure how your project is structured, but I'd try to calculate the heading for the last 2 coordinates you've received.
this code smothly not run i have try
Thank you very much man for such a valuable content