Is possible to draw a curve line (like a geodesic line) between 2 near points in google maps, for example with these coordinates:
p1 = (23.634501, -102.552783)
p2 = (17.987557, -92.929147)
Is there a javascript library to do it? and is possible to control the curvature of the line?
Thanks.
In a map the curve of the earth is represented on a flat surface. This makes the longitude lines appear straight. In reality the earth is curved so the longitude lines must also curve. this is way the longitude lines can not be straight.
Our locator maps use the Mercator projection. This works well for zoomed-in maps, but if you're showing entire continents the map will be distorted a lot. And because of this distortion, the straight line on a globe becomes an arc on a Mercator map.
Click on the map and create a popup marker to select the point. From there, opt for the “Draw Radius.” Choose the proximity distance from the given address found within the radius options in the software.
I figured out another solution just recently which does not need polylines but rather uses the path value for marker icons which can be calculated on the fly.
In a nutshell: you simply create an SVG path string for a quadratic bezier curve from 0 to p2 - p1 and attach it as a marker icon to p1.
Long version:
The pixel coordinates within the container can be obtained invoking google.maps.Projection.fromLatLngToContainerPixel()
.
The string for a quadratic bezier curve looks like this:
M [startX] [startY] q [controlX] [controlY] [endX] [endY]
We’ll choose (0,0)
for the start point, since the marker will by later placed at that point. The relative position of p2
is now e = (p2.x - p1.x, p2.y - p1.y)
, and the relative position
of the point half way between them is m = (e.x/2, e.y/2)
. An orthogonal vector to e
is o = s * norm(-e.x / e.y, 1)
, where s
is some scaling factor with s = |e|/4
beeing a good starting point. We now have
the control point with c = (m.x + o.x, m.y + o.y)
and the path is:
path = „M 0 0 q c.x c.y e.x e.y“
Now that we have that path, we can simply declare an icon:
var icon = {
path : path,
fillOpacity : 0,//important
scale : 1,
strokeOpacity: //yours,
strokeColor : //yours,
strokeWeight : //yours,
clickable : false //important
};
Setting clickable
to false is essential, because otherwise the area enclosed by the curve becomes clickable and the underlying map won’t recieve the mouse events. Now we can add a marker to the map with
the path icon as a parameter and the position of p1:
var marker = new google.maps.Marker({
position : p1,
icon : icon,
map : map,
clickable : false,
zIndex : -100 //make the line appear behind ‚real’ markers
});
A few things to note:
marker.icon.scale = 1 / 2^(initialZoom -
currentZoom)
there is no need to recalculate the path.Sample:
jsfiddle with hardcoded example using original question's points
relevant code:
var p1 = new google.maps.LatLng(23.634501, -102.552783);
var p2 = new google.maps.LatLng(17.987557, -92.929147);
var markerP1 = new google.maps.Marker({
position: p1,
map: map
});
var markerP2 = new google.maps.Marker({
position: p2,
map: map
});
google.maps.event.addListener(map, 'projection_changed', function () {
var p1 = map.getProjection().fromLatLngToPoint(markerP1.getPosition());
var p2 = map.getProjection().fromLatLngToPoint(markerP2.getPosition());
var e = new google.maps.Point(p1.x - p2.x, p1.y - p2.y);
var m = new google.maps.Point(e.x / 2, e.y / 2);
var o = new google.maps.Point(0, 7);
var c = new google.maps.Point(m.x + o.x, m.y + o.y);
var curveMarker2 = new google.maps.Marker({
position: markerP1.getPosition(),
icon: {
path: "M 0 0 q " + c.x + " " + c.y + " " + e.x + " " + e.y,
scale: 24,
strokeWeight: 2,
fillColor: '#009933',
fillOpacity: 0,
rotation: 180,
anchor: new google.maps.Point(0, 0)
}
});
curveMarker2.setMap(map);
google.maps.event.addListener(map, 'zoom_changed', function () {
var zoom = map.getZoom();
var scale = 1 / (Math.pow(2, -zoom));
var icon = {
path: "M 0 0 q " + c.x + " " + c.y + " " + e.x + " " + e.y,
scale: scale,
strokeWeight: 2,
fillColor: '#009933',
fillOpacity: 0,
rotation: 180,
anchor: new google.maps.Point(0, 0)
};
curveMarker2.setIcon(icon);
});
});
Here are the Libraries I found
http://curved_lines.overfx.net/ Dead link
http://www.geocodezip.com/v3_polyline_example_rhumb.html
http://www.geocodezip.com/v3_polyline_example_arc.html
Actually I just found that Google map Polyline takes in a list of point to construct. So u can pass in multiple points to make the line looks curved.
PS: u can use the draw arc function in the 2 links below to get the list of points for drawing
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