Google maps text for circles - javascript

Drawing a circle on a map is easy:
https://developers.google.com/maps/documentation/javascript/examples/circle-simple
But if I draw a circle around a point I also want to indicate to the user how big is the radius, is there a way to add text on the circle (for example on the perimeter) that indicate what the radius is?

The simple way for addit a good stylish text to google maps is use the google maps utilty and in your case yh js-map-label
https://github.com/googlemaps/js-map-label
see this sample page view-source:https://googlemaps.github.io/js-map-label/examples/maplabel.html
var mapLabel = new MapLabel({
text: 'Test',
position: new google.maps.LatLng(34.03, -118.235),
map: map,
fontSize: 35,
align: 'right'
});
mapLabel.set('position', new google.maps.LatLng(34.03, -118.235));
var marker = new google.maps.Marker();
marker.bindTo('map', mapLabel);
marker.bindTo('position', mapLabel);
marker.setDraggable(true);

Related

layered markers don't allow click-through when using 'poly' shape

I am having an issue with layered markers in the Google Maps API when trying to open an InfoWindow on mouseover. I have created a sample fiddle using Google's Complex Items documentation example.
The beachflag marker is a complex shape and uses a 'poly' element to define the area for the mouseover. This allows the mouseover to only appear when the cursor is on the upper half of the img where the flag part actually is.
var map_marker = new google.maps.Marker({
position: new google.maps.LatLng(-33.890542, 151.274856),
map: map,
shape: {
coords: [1, 1, 1, 20, 18, 20, 18, 1],
type: 'poly'
},
zIndex: 101,
optimized: false,
icon: "https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png"
});
The circle marker is situated behind the flag and is intended to be overlapped by the flag.
var map_marker = new google.maps.Marker({
position: new google.maps.LatLng(-33.890542, 151.274856),
map: map,
zIndex: 100,
optimized: false,
icon: {
path: google.maps.SymbolPath.CIRCLE,
fillColor: "#0FF",
fillOpacity: 1,
strokeWeight: 1.5,
scale: 40
}
});
I have a mouseover event displaying an InfoWindow for both markers but the problem lies in the small area underneath the flag marker polygon, there is a void where the circle InfoWindow is expected to be show, but doesn't.
One possible resolution to this is to turn the circle marker into a straight Circle, however I need my circle to be a fixed size and not scale with my zoom level.
How can I see the lower-level marker through the upper-level marker's "empty space" outside of its defined poly shape, and correctly display the mouseover InfoWindow?

Dynamically Change Color of GoogleMap Icon/Marker

I am trying to change the color of a marker/icon with GoogleMaps API V3 based on user input. I can hard code the color or image link I want into the Javascript, but if I try to pass the color or link as a string variable from my Java program then it either does not show up or defaults to a red marker.
I've looked at all the following threads and at the google API:
Google Maps API 3 - Custom marker color for default (dot) marker
How do I change icon colour in Google Maps API V3?
Google Maps API 3 - Custom marker color for default (dot) marker
https://developers.google.com/maps/documentation/javascript/markers
All of which have either the link to the marker icon they want to use or the color HEX code already hard coded into the javascript.
My attempt, where address1 and color1 are both strings that are passed to the javascript from my Java code. color1's string, for example could be
"http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld•|4D8080":
function codeAddress(address1, color1){
var pinColor = color1;
address=address1;
document.geocoder.geocode( {'address': address1}, function(results, status) {
app.callFromJavascript(address1);
if (status == google.maps.GeocoderStatus.OK) {
document.map.setCenter(results[0].geometry.location);
document.map.setZoom(13);
var marker = new google.maps.Marker({
icon: pinColor,
position: results[0].geometry.location,
map: document.map
});
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
This results in the map centering on the location and showing the default red marker.
If I change the string passed to color1 to be "http://maps.google.com/mapfiles/ms/icons/yellow-dot.png" then no marker shows up at all.
What am I missing that I can't get these to generate from passed variables? Is it simply not possible and mandatory that the location markers be hard coded?
So if you have a hex code already with you and you have an icon obj which looks like this
let carIcon = {
path: carsvg,
scale: 0.7,
strokeColor: 'white',
strokeWeight: 0.10,
fillOpacity: 1,
fillColor: '#404040',
offset: '2%',
anchor: new google.maps.Point(10, 25) // orig 10,50 back of car, 10,0 front of car, 10,25 center of car
};
and a marker object like this
let carmarker = new google.maps.Marker({
position: carLatLng,
map: map,
title: "Car",
icon: carIcon,
setMap: map
});
and say you want to change the color of the icon. To do that, simply use
carIcon.fillColor = '#008000';
carmarker.setIcon(carIcon);
This should make it to the color hex code you have. Hope it helps. Also, the icon should be SVG in this case for the color to change to take place.
this works fine for me :
var marker = new google.maps.Marker({
icon: new google.maps.MarkerImage("http://maps.google.com/mapfiles/ms/icons/yellow-dot.png"),
position: results[0].geometry.location,
map: document.map
});
they do not have to be hard coded , but you do have to use the object type of MarkerImage to pass the url to.
You can not just pass a hex color and expect the maps API to make a new marker based on the color you just picked. What is usually done is to like to an image url that already exists for each color that you plan to use. Then use the code the way I showed you.

Simple label on a leaflet (geojson) polygon

I am attempting what I imagine to be a fairly common use-case with a leaflet multipolygon object.
I create the MultiPolygon using geojson:
var layer = L.GeoJSON(g, style_opts);
What I'd like is to put a simple text label in the center of each polygon. (For example, something like putting state name in the center of each state).
I've looked at:
https://groups.google.com/forum/?fromgroups=#!topic/leaflet-js/sA2HnU5W9Fw
Which actually overlays the text, but when I add a bunch of polygons, it appears to put the label off-center in weird ways, and I'm currently unable to track down the problem.
I've also looked at: https://github.com/jacobtoye/Leaflet.label
but that appears to only put the label on polygons when you mouse over the polygon, and does not stay statically on the polygon.
I think my best course of action is to use that first link, and track down why it's changing the location, but in the meantime, if anyone knows of a quick and easy way to lay a label on a polygon in leaflet, I'd be much obliged.
Also, if I have any faulty assumptions about the two links above, please feel free to straighten me out.
Thanks very much in advance.
The leaflet label plugin also allows static labels, see the demo.
The only reason the polyline label is not static is that it moves around as you move along the polyline.
You can probably do better than this, by overriding bindLabel() for Polygons but this is a simple way to add a static label to the center of a polygon:
label = new L.Label()
label.setContent("static label")
label.setLatLng(polygon.getBounds().getCenter())
map.showLabel(label);
http://jsfiddle.net/CrqkR/6/
You can use the onEachFeature option of L.geoJson to create a new L.divIcon for each polygon.
L.geoJson(geoJsonData, {
onEachFeature: function(feature, layer) {
var label = L.marker(layer.getBounds().getCenter(), {
icon: L.divIcon({
className: 'label',
html: feature.properties.NAME,
iconSize: [100, 40]
})
}).addTo(map);
}
);
you can use this code to show label in polygon :
var eu = L.geoJSON(euCountries, {
onEachFeature: function (feature, layer) {
// if (feature.geometry.type === "Polygon") {
var bounds = layer.getBounds();
// Get center of bounds
var center = bounds.getCenter();
//var center = layer.getBounds().getCenter();
if(feature.properties.name=="russia")
{
alert(center)
}
layer.bindTooltip(feature.properties.name, {permanent: true, direction: "center", className: "my-labels"});
layer.on("click", function (e) {
layer.bindPopup(feature.properties.name);
});
/* var marker =L.circleMarker(center, {color: '', radius:10,Title:20}).bindTooltip(feature.properties.name, {permanent: true, direction: "center", className: "my-labels"});
map.addLayer(marker);*/
// var polygonAndItsCenter = L.layerGroup([layer, marker]);
// }
},
});
eu.addTo(map);

Dynamic rectangles in Google Maps

First I'm pretty new to Javascript, so sorry if my question comes across poorly.
I'm creating an application in Flash to help users calculate their electrical costs. Then I'm taking this figure and write it to an xml file.
Now I'm looking to open a webpage and show a google map, and there is a rectangle drawn over the map which is generated dynamically from the number generated earlier and stored in the xml file.
I'm completely lost as to places to turn on how to achieve this. I've gotten my map on to my page, and it scales 100% as I want it to, but I can't figure out the dynamic rectangle part at all. Any ideas or pointers in the right direction greatly appreciated.
In this latest version, the XML file
<countries>
<country name="USA" lat="40.0" lng="-100.0" width="30.0"/>
<country name="France" lat="46.6" lng="2.7" width="10"/>
<country name="Germany" lat="51.1" lng="10.1" width="20"/>
</countries>
is loaded as soon as the map tiles finish loading. I could not get the getProjection to be called correctly if I did not wait for tile loading to finish. The docs state that getting the projection needs the map to be initialized, and recommends listening for projection_changed. Both ways work yet I still feel listening to tiles_loaded is safer and if something goes wrong with the xml loading it will get called again if the map is zoomed or panned a noticeable amount.
var map;
var xmlLoaded = false;
function initialize() {
var mapOptions = { center: new google.maps.LatLng(30.0, 0.0), zoom: 2,
mapTypeId: google.maps.MapTypeId.ROADMAP };
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
google.maps.event.addListener(map, 'tilesloaded', loadData);
}
function loadData() {
if(!xmlLoaded) {
$.ajax({
type: "GET",
url: "co2data.xml",
dataType: "xml",
success: function(xml) {
var countries = xml.documentElement.getElementsByTagName("country");
for(var i = 0, country; country = countries[i]; i++) {
var name = country.getAttribute("name");
var lat = parseFloat(country.getAttribute("lat"));
var lng = parseFloat(country.getAttribute("lng"));
var point = map.getProjection().fromLatLngToPoint(new google.maps.LatLng(lat,lng));
// width is really an arbitrary unit, relative to CO2 tonnage.
// equals the side of the drawn square.
// it is measured in google maps points units.
var width = parseFloat(country.getAttribute("width"));
makeCO2Rect(name, point, width);
}
xmlLoaded = true;
}
});
}
}
The rectangle is defined by width in points (the whole world is 256x256 points), so some conversion is needed when assigning their centers to the more conventional LatLng.
function rectParamsToBounds(point, width) {
var ctrX = point.x;
var ctrY = point.y;
var swX = ctrX - (width/2);
var swY = ctrY - (width/2);
var neX = ctrX + (width/2);
var neY = ctrY + (width/2);
return new google.maps.LatLngBounds(
map.getProjection().fromPointToLatLng(new google.maps.Point(swX, swY)),
map.getProjection().fromPointToLatLng(new google.maps.Point(neX, neY)));
}
Finally, a rectangle is created with a country name that goes into a MarkerWithLabel (using v1.1.5 here, you can hotlink to http://google-maps-utility-library-v3.googlecode.com/svn/tags/markerwithlabel/1.1.5/src/markerwithlabel_packed.js though I prefer saving a local copy)
Since dragging a rectangle appears impossible, a marker in its center works as a handle. When it's dragged, the associated rectangle moves with it.
function makeCO2Rect(name, point, width) {
var rect = new google.maps.Rectangle({
map: map,
bounds: rectParamsToBounds(point, width)
});
var marker = new MarkerWithLabel({
map: map,
position: map.getProjection().fromPointToLatLng(new google.maps.Point(point.x, point.y)),
draggable: true,
raiseOnDrag: false,
labelContent: name,
labelAnchor: new google.maps.Point(30, 0),
labelClass: "labels", // the CSS class for the label
labelStyle: {opacity: 1.0}
});
google.maps.event.addListener(marker, 'drag', function(event) {
var newLatLng = event.latLng;
var newPoint = map.getProjection().fromLatLngToPoint(newLatLng);
rect.setBounds(rectParamsToBounds(newPoint, width));
});
}
google.maps.event.addDomListener(window, 'load', initialize);
Styling the labels need to be done both in the .labels CSS class and the constructor, and rectangles have options like stroke color, thickness, opacity, and fill color.
If you just want to place a rectangular shape on the map, you can create a google.maps.Rectangleapi-doc. If you want to create a rectangular label on the map, you may be more interested in the InfoBox Utility Librarywiki-page.

How can some LatLng be used to place markers on a Google map, but not to draw a Polygon?

Roughly a week ago, I ran into a problem: on a custom google-powered map, my Polygons would not show up, while Markers for the same coordinates are totally ok. Despite my efforts with the Google Maps API, it seems I cannot find why.
Here is a link to a screenshot of the map. Purple arrows and numbers are my addition, they show:
The google.maps.Marker I could place at the edges of my "region".
The artifact generated by the google.maps.Polygon code. It is red as expected, but completely out of place and weirdly flat.
Here is the part of the code where Markers and Polygons are generated:
var regionData = tecMap.regions[r];
var regionMapMarkers = new google.maps.MVCArray();
for (c in regionData.coords) {
var point = projection.worldToMap(regionData.coords[c]);
debugRegionPoints.push(point);
var thisLatLng = projection.fromPointToLatLng(point);
debugRegionLatLngs.push(thisLatLng);
regionMapMarkers.push(thisLatLng);
}
regionMapMarkers.forEach(function(latLng, m){
var marker = new google.maps.Marker({
position: latLng,
map: map,
title: '',
optimized: false
});
regionCorners.push(marker);
});
var paths = new google.maps.MVCArray();
paths.push(regionMapMarkers);
var region = new google.maps.Polygon({
fillColor: "#FF0000",
fillOpacity: 0.35,
map: map,
paths: paths,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2
});
regionPolys.push(region);
If you're wondering about the array of arrays, it's all on par with the Google Maps Javascript API.
If you want to have a look at the map and related scripts, you can find it here.
The code snippet is in Scripts/tectonicus.js, starting at line 659.
[Edit] Some debugging information:
It seems to be a rendering problem, not a "calculating" one.
From firebug console, in the map I linked, both
regionPolys[0].getPath().getArray();
and
for (i in regionCorners) {console.log(regionCorners[i].getPosition())};
will return
P { Na=0.20123958504464223, Oa=-22.5249097921875}
P { Na=-0.21702715474330336, Oa=-32.7277467}
P { Na=0.19466306397879407, Oa=-37.51230686484375}
P { Na=0.12889785332031245, Oa=-49.04594858671875}
If I'm right, it means they have the same coordinates, which is on par with the code.
[Edit2] New advances !
It seems that vectors have rendering problems when dealing with a custom projection, such as the one used to display this isometric Minecraft map. (Generated with Tectonicus)
After the last comments, I'm adding to the live code linked above two new debug Arrays,
debugRegionLatLngs and debugRegionPoints. Above code is updated so you can see what they contain.
[Edit3] Projection and coordinates
Crossing BicycleDude's research with mine, it's now almost certain that it's the custom projection that wrecks polygons. In fact, there is a possibly related bug in Google Maps' API.
This projection is used because Minecraft maps can be virtually infinite, and yet have to use a gmap, which wraps around after 360° longitude. Also related is the fact that ingame coordinates are rendered in an isometric way, while gmaps expects something more like the Mercator projection.
I tried tweaking the projection a bit, but had no interesting results so far.
Hmm, I looked at this further and I do see that sliver polygon. If you note your latitudes, they're extremely close to 0 degrees which means virtually a flat line near the equator. I validated this myself by pasting your coordinates into a brand new Google Maps sample and they do not appear to be spatially located with your markers, so, you need to review where the coordinate information is being manipulated, sorry, I know I didn't find your problem.
I modified Google Map's Bermuda triangle sample to use your coding style. i.e. I adopted your variables and followed the spirit of your code. This example display 3 markers and the draws a polygon for the Bermuda triangle.
<!DOCTYPE html>
<html>
<head>
<title>Bermuda Hack Triangle</title>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta charset="UTF-8">
<style type="text/css">
#map_canvas {
width: 500px;
height: 500px;
}
</style>
<script type="text/javascript" scr="https://github.com/douglascrockford/JSON-js/blob/master/json2.js"></script>
<script type="text/javascript"
src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var map;
function initialize() {
var myoptions = {
zoom: 4,
center: new google.maps.LatLng(25, -70),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(
document.getElementById('map_canvas'),
myoptions
);
// Create pseudo coordinates
var regionMapMarkers = new google.maps.MVCArray();
var p1 = new google.maps.LatLng(25, -80);
var p2 = new google.maps.LatLng(18, -66);
var p3 = new google.maps.LatLng(32, -64);
//p2.Qa += 360;
//p3.Qa -= 360;
regionMapMarkers.push(p1);
regionMapMarkers.push(p2);
regionMapMarkers.push(p3);
console.log(JSON.stringify(regionMapMarkers));
// Draw Markers
regionMapMarkers.forEach(function(latLng, m){
var marker = new google.maps.Marker(
{
position: latLng,
map: map,
title: '',
optimized: false
});
});
// Draw Polygon
var region = new google.maps.Polygon({
map: map,
paths: regionMapMarkers,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map_canvas"></div>
</body>
</html>
The sample works. If you were to run it you'll get the Bermuda triangle surrounded by markers. The question then lies, what can, in practice, impact your algorithm? So far, we've speculated that the Minecraft projection does something. I still believe that to be the case.
In order to validate that theory, I tried to wreck the Bermuda triangle sample. I tried adding and subtracting 360 degrees longitude to two points by uncommenting the following lines:
p2.Qa += 360;
p3.Qa -= 360;
What this does is it will still allow it to place the markers in the same location but the polygon fill goes absolutely spacko. I believe this is what is happening in your scenario.
What I then recommend for you to do is review coordinate system in your application. If you can choose new coordinates you can avoid such edge conditions from happening.
I noticed you're passing paths as an MVCArray which contains another MVCArray. Have you tried just passing a simple single-dimension array like in Google's example in the docs?
And do you need to call setMap() or is passing in the map property enough to make it render?
Below is Google's Polygon() code example... (from here)
function initialize() {
var myLatLng = new google.maps.LatLng(24.886436490787712, -70.2685546875);
var myOptions = {
zoom: 5,
center: myLatLng,
mapTypeId: google.maps.MapTypeId.TERRAIN
};
var bermudaTriangle;
var map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
var triangleCoords = [
new google.maps.LatLng(25.774252, -80.190262),
new google.maps.LatLng(18.466465, -66.118292),
new google.maps.LatLng(32.321384, -64.75737),
new google.maps.LatLng(25.774252, -80.190262)
];
// Construct the polygon
// Note that we don't specify an array or arrays, but instead just
// a simple array of LatLngs in the paths property
bermudaTriangle = new google.maps.Polygon({
paths: triangleCoords,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35
});
bermudaTriangle.setMap(map);
}

Categories

Resources