I'd like to know if it possible to change the marker orientation according the path drawn on the map. Here is a example:
As you can see the marker is a car (with front bumper and tail lights). I'd like to orientate the car in the direction the path is going (in this exemple orientate the car around 45 degrees to the right).
I'm using DirectionsService
to draw the path and I have a random number of point. Sometime only one, sometime 10 points. I'm adding the markers before drawing the paths. Here is how I'm drawing the path:
// Intialize the Path Array var path = new google.maps.MVCArray(); // Intialise the Direction Service var service = new google.maps.DirectionsService(); // Set the Path Stroke Color var poly = new google.maps.Polyline({ map: gmap, strokeColor: '#dd0000' }); // #4986E7 // Draw the path for this vehicle for (var i = 0; i < pathPoints.length; i++) { if ((i + 1) < pathPoints.length) { var src = pathPoints[i]; var des = pathPoints[i + 1]; path.push(src); poly.setPath(path); service.route({ origin: src, destination: des, travelMode: google.maps.DirectionsTravelMode.DRIVING }, function (result, status) { if (status == google.maps.DirectionsStatus.OK) { for (var i = 0, len = result.routes[0].overview_path.length; i < len; i++){ path.push(result.routes[0].overview_path[i]); } } }); } }
Is it possible to do that?
The Google Maps voice will start telling you where to go. Place two fingers down anywhere on the navigational screen and rotate. Place two fingers down on the screen anywhere and then turn them. Your map will rotate according to the direction of your multi-touch inputs.
You have to set the anchor to the point you want to rotate around, and it's also the point you want to be at the position you set to the marker. (0.5, 0.5) is the center of the image. Here are some posts which might also help: Change Google map marker orientation according path direction.
Call the changeMarkerPosition() function and pass the marker object in it. The setPosition() will change the marker position on google map based on the specified latitude and longitude.
Open Google Maps and swipe from left to right to open the side menu. Next scroll down and select settings. Inside settings scroll down again near the bottom to “Navigation Settings”. Now just turn on the option (flip the switch) labeled “Keep map north up”.
One option is to translate your icon to SVG then use the Symbol rotation
property to align it with the road (you can do the same with a PNG image by either making a large number of copies of the icon rotated by a degree or two, or by making a custom icon that allows you to rotate the PNG icon arbitrarily)
marker.setPosition(p); var heading = google.maps.geometry.spherical.computeHeading(lastPosn,p); icon.rotation = heading; marker.setIcon(icon);
proof of concept fiddle
code snippet:
var map; var directionDisplay; var directionsService; var stepDisplay; var markerArray = []; var position; var marker = null; var polyline = null; var poly2 = null; var speed = 0.000005, wait = 1; var infowindow = null; var timerHandle = null; function createMarker(latlng, label, html) { var contentString = '<b>' + label + '</b><br>' + html; var marker = new google.maps.Marker({ position: latlng, map: map, title: label, zIndex: Math.round(latlng.lat() * -100000) << 5 }); marker.myname = label; google.maps.event.addListener(marker, 'click', function() { infowindow.setContent(contentString); infowindow.open(map, marker); }); return marker; } function initialize() { infowindow = new google.maps.InfoWindow({ size: new google.maps.Size(150, 50) }); // Instantiate a directions service. directionsService = new google.maps.DirectionsService(); // Create a map and center it on Manhattan. var myOptions = { zoom: 13, mapTypeId: google.maps.MapTypeId.ROADMAP }; map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); address = 'new york'; geocoder = new google.maps.Geocoder(); geocoder.geocode({ 'address': address }, function(results, status) { map.setCenter(results[0].geometry.location); }); // Create a renderer for directions and bind it to the map. var rendererOptions = { map: map }; directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions); // Instantiate an info window to hold step text. stepDisplay = new google.maps.InfoWindow(); polyline = new google.maps.Polyline({ path: [], strokeColor: '#FF0000', strokeWeight: 3 }); poly2 = new google.maps.Polyline({ path: [], strokeColor: '#FF0000', strokeWeight: 3 }); } var steps = []; function calcRoute() { if (timerHandle) { clearTimeout(timerHandle); } if (marker) { marker.setMap(null); } polyline.setMap(null); poly2.setMap(null); directionsDisplay.setMap(null); polyline = new google.maps.Polyline({ path: [], strokeColor: '#FF0000', strokeWeight: 3 }); poly2 = new google.maps.Polyline({ path: [], strokeColor: '#FF0000', strokeWeight: 3 }); // Create a renderer for directions and bind it to the map. var rendererOptions = { map: map }; directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions); var start = document.getElementById("start").value; var end = document.getElementById("end").value; var travelMode = google.maps.DirectionsTravelMode.DRIVING; var request = { origin: start, destination: end, travelMode: travelMode }; // Route the directions and pass the response to a // function to create markers for each step. directionsService.route(request, function(response, status) { if (status == google.maps.DirectionsStatus.OK) { directionsDisplay.setDirections(response); var bounds = new google.maps.LatLngBounds(); var route = response.routes[0]; startLocation = new Object(); endLocation = new Object(); // For each route, display summary information. var path = response.routes[0].overview_path; var legs = response.routes[0].legs; for (i = 0; i < legs.length; i++) { if (i === 0) { startLocation.latlng = legs[i].start_location; startLocation.address = legs[i].start_address; // marker = createMarker(legs[i].start_location, "start", legs[i].start_address, "green"); } endLocation.latlng = legs[i].end_location; endLocation.address = legs[i].end_address; var steps = legs[i].steps; for (j = 0; j < steps.length; j++) { var nextSegment = steps[j].path; for (k = 0; k < nextSegment.length; k++) { polyline.getPath().push(nextSegment[k]); bounds.extend(nextSegment[k]); } } } polyline.setMap(map); map.fitBounds(bounds); map.setZoom(18); startAnimation(); } }); } var step = 50; // 5; // metres var tick = 100; // milliseconds var eol; var k = 0; var stepnum = 0; var speed = ""; var lastVertex = 1; //=============== animation functions ====================== function updatePoly(d) { // Spawn a new polyline every 20 vertices, because updating a 100-vertex poly is too slow if (poly2.getPath().getLength() > 20) { poly2 = new google.maps.Polyline([polyline.getPath().getAt(lastVertex - 1)]); // map.addOverlay(poly2) } if (polyline.GetIndexAtDistance(d) < lastVertex + 2) { if (poly2.getPath().getLength() > 1) { poly2.getPath().removeAt(poly2.getPath().getLength() - 1); } poly2.getPath().insertAt(poly2.getPath().getLength(), polyline.GetPointAtDistance(d)); } else { poly2.getPath().insertAt(poly2.getPath().getLength(), endLocation.latlng); } } function animate(d) { if (d > eol) { map.panTo(endLocation.latlng); marker.setPosition(endLocation.latlng); return; } var p = polyline.GetPointAtDistance(d); map.panTo(p); var lastPosn = marker.getPosition(); marker.setPosition(p); var heading = google.maps.geometry.spherical.computeHeading(lastPosn, p); icon.rotation = heading; marker.setIcon(icon); updatePoly(d); timerHandle = setTimeout("animate(" + (d + step) + ")", tick); } function startAnimation() { eol = polyline.Distance(); map.setCenter(polyline.getPath().getAt(0)); marker = new google.maps.Marker({ position: polyline.getPath().getAt(0), map: map, icon: icon }); poly2 = new google.maps.Polyline({ path: [polyline.getPath().getAt(0)], strokeColor: "#0000FF", strokeWeight: 10 }); // map.addOverlay(poly2); setTimeout("animate(50)", 2000); // Allow time for the initial map display } google.maps.event.addDomListener(window, 'load', initialize); //=============== ~animation funcitons ===================== var car = "M17.402,0H5.643C2.526,0,0,3.467,0,6.584v34.804c0,3.116,2.526,5.644,5.643,5.644h11.759c3.116,0,5.644-2.527,5.644-5.644 V6.584C23.044,3.467,20.518,0,17.402,0z M22.057,14.188v11.665l-2.729,0.351v-4.806L22.057,14.188z M20.625,10.773 c-1.016,3.9-2.219,8.51-2.219,8.51H4.638l-2.222-8.51C2.417,10.773,11.3,7.755,20.625,10.773z M3.748,21.713v4.492l-2.73-0.349 V14.502L3.748,21.713z M1.018,37.938V27.579l2.73,0.343v8.196L1.018,37.938z M2.575,40.882l2.218-3.336h13.771l2.219,3.336H2.575z M19.328,35.805v-7.872l2.729-0.355v10.048L19.328,35.805z"; var icon = { path: car, scale: .7, strokeColor: 'white', strokeWeight: .10, fillOpacity: 1, fillColor: '#404040', offset: '5%', // rotation: parseInt(heading[i]), anchor: new google.maps.Point(10, 25) // orig 10,50 back of car, 10,0 front of car, 10,25 center of car }; /*********************************************************************\ * * * epolys.js by Mike Williams * * updated to API v3 by Larry Ross * * * * A Google Maps API Extension * * * * Adds various Methods to google.maps.Polygon and google.maps.Polyline * * * * .Contains(latlng) returns true is the poly contains the specified * * GLatLng * * * * .Area() returns the approximate area of a poly that is * * not self-intersecting * * * * .Distance() returns the length of the poly path * * * * .Bounds() returns a GLatLngBounds that bounds the poly * * * * .GetPointAtDistance() returns a GLatLng at the specified distance * * along the path. * * The distance is specified in metres * * Reurns null if the path is shorter than that * * * * .GetPointsAtDistance() returns an array of GLatLngs at the * * specified interval along the path. * * The distance is specified in metres * * * * .GetIndexAtDistance() returns the vertex number at the specified * * distance along the path. * * The distance is specified in metres * * Returns null if the path is shorter than that * * * * .Bearing(v1?,v2?) returns the bearing between two vertices * * if v1 is null, returns bearing from first to last * * if v2 is null, returns bearing from v1 to next * * * * * *********************************************************************** * * * This Javascript is provided by Mike Williams * * Blackpool Community Church Javascript Team * * http://www.blackpoolchurch.org/ * * http://econym.org.uk/gmap/ * * * * This work is licenced under a Creative Commons Licence * * http://creativecommons.org/licenses/by/2.0/uk/ * * * *********************************************************************** * * * Version 1.1 6-Jun-2007 * * Version 1.2 1-Jul-2007 - fix: Bounds was omitting vertex zero * * add: Bearing * * Version 1.3 28-Nov-2008 add: GetPointsAtDistance() * * Version 1.4 12-Jan-2009 fix: GetPointsAtDistance() * * Version 3.0 11-Aug-2010 update to v3 * * * \*********************************************************************/ // === first support methods that don't (yet) exist in v3 google.maps.LatLng.prototype.distanceFrom = function(newLatLng) { var EarthRadiusMeters = 6378137.0; // meters var lat1 = this.lat(); var lon1 = this.lng(); var lat2 = newLatLng.lat(); var lon2 = newLatLng.lng(); var dLat = (lat2 - lat1) * Math.PI / 180; var dLon = (lon2 - lon1) * Math.PI / 180; var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); var d = EarthRadiusMeters * c; return d; } google.maps.LatLng.prototype.latRadians = function() { return this.lat() * Math.PI / 180; } google.maps.LatLng.prototype.lngRadians = function() { return this.lng() * Math.PI / 180; } // === A method which returns the length of a path in metres === google.maps.Polygon.prototype.Distance = function() { var dist = 0; for (var i = 1; i < this.getPath().getLength(); i++) { dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1)); } return dist; } // === A method which returns a GLatLng of a point a given distance along the path === // === Returns null if the path is shorter than the specified distance === google.maps.Polygon.prototype.GetPointAtDistance = function(metres) { // some awkward special cases if (metres == 0) return this.getPath().getAt(0); if (metres < 0) return null; if (this.getPath().getLength() < 2) return null; var dist = 0; var olddist = 0; for (var i = 1; (i < this.getPath().getLength() && dist < metres); i++) { olddist = dist; dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1)); } if (dist < metres) { return null; } var p1 = this.getPath().getAt(i - 2); var p2 = this.getPath().getAt(i - 1); var m = (metres - olddist) / (dist - olddist); return new google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) * m); } // === A method which returns an array of GLatLngs of points a given interval along the path === google.maps.Polygon.prototype.GetPointsAtDistance = function(metres) { var next = metres; var points = []; // some awkward special cases if (metres <= 0) return points; var dist = 0; var olddist = 0; for (var i = 1; (i < this.getPath().getLength()); i++) { olddist = dist; dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1)); while (dist > next) { var p1 = this.getPath().getAt(i - 1); var p2 = this.getPath().getAt(i); var m = (next - olddist) / (dist - olddist); points.push(new google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) * m)); next += metres; } } return points; } // === A method which returns the Vertex number at a given distance along the path === // === Returns null if the path is shorter than the specified distance === google.maps.Polygon.prototype.GetIndexAtDistance = function(metres) { // some awkward special cases if (metres == 0) return this.getPath().getAt(0); if (metres < 0) return null; var dist = 0; var olddist = 0; for (var i = 1; (i < this.getPath().getLength() && dist < metres); i++) { olddist = dist; dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i - 1)); } if (dist < metres) { return null; } return i; } // === Copy all the above functions to GPolyline === google.maps.Polyline.prototype.Distance = google.maps.Polygon.prototype.Distance; google.maps.Polyline.prototype.GetPointAtDistance = google.maps.Polygon.prototype.GetPointAtDistance; google.maps.Polyline.prototype.GetPointsAtDistance = google.maps.Polygon.prototype.GetPointsAtDistance; google.maps.Polyline.prototype.GetIndexAtDistance = google.maps.Polygon.prototype.GetIndexAtDistance;
html { height: 100%; } body { height: 100%; margin: 0px; font-family: Helvetica, Arial; }
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script> <div id="tools">start: <input type="text" name="start" id="start" value="union square, NY" />end: <input type="text" name="end" id="end" value="times square, NY" /> <input type="submit" onclick="calcRoute();" /> </div> <div id="map_canvas" style="width:100%;height:90%;"></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With