I have a Google maps page that draws various polylines based on a bunch of coordinates. They all connect two points via a great circle polyline. All lines have the same color. These lines are routes on a network
I would now like to make the polylines in a fading color to indicate the profitability of the route, showing a green color for profitable routes and red for loss making routes. As each polyline has two possible profitabilities (from both originating points) the colors should fade over to the other color gradually.
I assume, I could split the polyline into two, showing each only half of the line, but then the color would not gradually fade into the other.
Is there a way to do that?
Currently I am creating the lines as follows:
var routes = [['CJU', 'SZX', 33.5112991333, 126.49299621582, 22.6392993927, 113.81099700928, 1, 7, 3163768],
['CJU', 'PEK', 33.5112991333, 126.49299621582, 40.08010101318, 116.58499908447, 0.5, 4, 3163766],
['CJU', 'PVG', 33.5112991333, 126.49299621582, 31.14340019226, 121.80500030518, 0.5, 4, 3163767],
['CJU', 'WUH', 33.5112991333, 126.49299621582, 30.78380012512, 114.20800018311, 0.5, 4, 3163769],];
function setRoutes(map, flights) {
for (var j = 0; j < flights.length; j++) {
var route = flights[j];
var infowindow = new google.maps.InfoWindow({ content: 'From '+route[0]+' to '+route[1]+' ', position: new google.maps.LatLng(route[4], route[5]) });
var flt = new google.maps.Polyline({path: [new google.maps.LatLng(route[2], route[3]), new google.maps.LatLng(route[4], route[5])], strokeColor: "#FF0000", strokeOpacity: route[6], strokeWeight: route[7], geodesic: true, url: 'http://domain.com/page.asp?F='+route[8] });
flt.setMap(map);
google.maps.event.addListener(flt, 'click', function() { NewWindow(this.url,'name','770','490','Yes');return false; });
var apt = new google.maps.MarkerImage('http://domain.com/marker/dot.png', null, null, new google.maps.Point(8,14), new google.maps.Size(20,20));
var dep = new google.maps.LatLng(route[2], route[3]);
var marker = new google.maps.Marker({position: dep, map: map, icon: apt, title: route[0]});
var arr = new google.maps.LatLng(route[4], route[5]);
var marker = new google.maps.Marker({position: arr, map: map, icon: apt, title: route[1]});
}
}
setRoutes(map, routes);
This works just fine, but I'm not sure how I could have the color gradually fade over from a color1 to a color2.
Thanks in advance.
The google maps documentation does not have any option to fade colors.
They will appear fixed, However a little bit of customization can be done but fading from one color to another is not supported.
Try giving colors in RGBA mode.
I mean instead of Giving colors in Hex mode e.g. #FF0000, you can use it's equivalent in RGBA mode e.g. rgba(255, 0, 0, 1).
To fade your colors in RGBA mode, change the value of last digit and keep it between 0 (transparent) and 1 (visible).
You can use this link to convert your Hex colors to RGBA.
Related
I can't seem to get CircleMarkers to show their associated popups in Leaflet. Here's what I am doing:
var markerGroup;
fetch("<FILE_NAME_REMOVED>").then(function(response){
return response.text();
}).then(function(text){
var lines = text.split("\n");
var markerArray = [];
for (var i=1; i<lines.length; i++) {
var parts = lines[i].split(",");
if (typeof parts[2] !='undefined') {
marker = new L.CircleMarker([parts[3],parts[2]], {
radius: 4,
color: 'red',
opacity: 0.95,
weight: 1.2,
dashArray: "2,3",
fillOpacity: 0.2
}).bindPopup("I am at " + parts[0] + "," + parts[1]);
markerArray.push(marker);
};
}
markerGroup = L.featureGroup(markerArray).addTo(map);
map.fitBounds(markerGroup.getBounds());
}).catch(function(err){
console.log(err);
});
The popups are just not showing up - in fact when I click on the circles the map just zooms in. If I replace L.CircleMarker with just L.Marker though it works fine, but I actually need circles.
I even tried adding an on click function to the markers, still nothing.
Could someone please help? I am using leaflet 1.3.4.
EDIT:
I didn't mention (because I did't think it mattered) that the markers are added last to the map but the map has a geoJson layer as well. I've noticed (by accident) that the popups do show up just fine over the area of the map not covered by the geoJson layer. This is strange to me because the geojson layer is set to back from the beginning:
var datalayer;
$.getJSON("<FILE_NAME_REMOVED>",function(data){
datalayer = L.geoJson(data ,{
onEachFeature: function(feature, featureLayer) {
featureLayer.setStyle({fillColor: 'white'});
featureLayer.setStyle({weight:1});
featureLayer.setStyle({fillOpacity:0.1});
featureLayer.bringToBack();
}
}).addTo(map);
map.fitBounds(datalayer.getBounds());
});
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?
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.
I want to draw multiple polygons in the same google map, what i need to do is to read latlngs from a listbox, they are in this way:
lat1,lng1,1
lat2,lng2,1
lat3,lng3,1
lat1,lng1,2
lat2,lng2,2
lat3,lng3,2
and depending on the value at the right(1 or 2) I will read the corresponding latlns and draw the polygon, actually i'm doing this, in my loop the polygons are painted but there´s a line connecting them, what can I do?,I mean, HOW CAN I DRAW POLYGONS WITHOUT THIS CONNECTING LINES?, thank you very much!!!
Here's my code:
<script type="text/javascript">
var bermudaTriangle=[];
var places = [];
var geoDataSplit;
function initialize() {
var mapDiv = document.getElementById('map_canvas');
var coords = document.getElementById("selPoly");
var map = new google.maps.Map(mapDiv, {
center: new google.maps.LatLng(19.3162200000000, -99.2204930000000),
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var latlng;
for (var i = 0; i < coords.options.length; i++)
{
var geoData = coords.options[i].text;
geoDataSplit = geoData.split(",");
var counter = geoDataSplit[2];
for (geoDataSplit[2] = 1; geoDataSplit[2] <= 2; geoDataSplit[2]++)
{
if (counter == geoDataSplit[2]) {
latlng = new google.maps.LatLng(parseFloat(geoDataSplit[0]), parseFloat(geoDataSplit[1]));
places.push(latlng);
bermudaTriangle = new google.maps.Polygon({
paths: places,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35
});
}
}
}
bermudaTriangle.setMap(map);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body style="font-family: Arial; border: 0 none;">
<form id="form1" runat="server">
<div>
<asp:ListBox ID="selPoly" runat="server"></asp:ListBox>
</div>
</form>
<div id="map_canvas" style="width: 1024px; height: 768px"></div>
</body>
Drawing polygons is drawing lines between points (the subsequent points you give, and possibly the first and last point on your list). When they enclose a space - you get a polygon and the space is filled with colour. The line is always there between the two subsequent points.
If you want separate polygons, you have to CREATE separate polygons (with new google.maps.Polygon). If all you get is a list of points, it is up to you to come up with or find an algorithm to detect that the space is already enclosed, and a new Polygon should be created.
By the way, with the algoritm as is now, the new google.maps.Polygon line could (and probably should) be pushed down, outside of the loop, in line preceding bermudaTriangle.setMap(map);
OH WAIT THERE ACTUALLY IS A SOLUTION. Or a half-solution at least. You can make the lines invisible (strokeOpacity: 0). The polygons will still be visible because of their filling, more or less like this:
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);
}