How to add polyline into Leaflet map - javascript

I'm using zeppelin and angular interpreter.
I have tried three different ways. None of them was successful. But simple markers showed up.
1st one
var array = [];
all_properties.forEach(item =>{
array.push(new L.LatLng(item[0], item[1]));
});
var firstpolyline = new L.polyline(array, {
color: 'red',
weight: 5,
opacity: 1,
smoothFactor: 1
});
firstpolyline.addTo(map);
2nd one
var poly = new L.polyline(all_properties, {
color: 'green',
weight: 5,
opacity: 1,
smoothFactor: 1
});
poly.addTo(map);
3rd one
var polylinePoints = [
[lat, long],
[lat1, long1]
];
var polyline = L.polyline(polylinePoints).addTo(map);
There is no error...
Any ideas? Thx
Edit: When I show points as markers, all of them showed up one the map. This set of markers should me polyline tho...
arr_markers = [];
all_properties.forEach(item =>{
arr_markers.push(L.marker([ item[0], item[1]], {icon: basicIcon}));
});
polyGroup = L.layerGroup(arr_markers).addTo(map);

Weird thing happened. I just logged off and logged in and the polygon showed up. Actually all of them. Maybe something was cached in my browser (Firefox), or in Zeppelin, or interpreter (restarting of angular interpeter did not help tho...)

Related

Leaflet: showing dynamic polylines together on a map using layers

I'm working on a task of showing all polylines(of different colours) on my map using leaflet. I'm getting all my dynamic polylines' latitudes and longitudes with their colours but when I merge it using layers, it just takes the last polyline and shows it.
I think I'm making some mistake in layering it. Can someone recommend the correct way to layer polylines in leaflets?
Here's a sample of the code where this is happening -
let newColour = this.returnMapColor(moment(startDate).day());
var layerGroups = {}
console.log("colour", newColour, startDate );
let range = this.props.history.filter((v) => { return moment(v.time).format("YYYY-MM-DD") == moment(startDate).format("YYYY-MM-DD") });
startDate = moment(startDate).add(1, 'days');
range.map((row)=> {
positions.push([row.latitude,row.longitude,row.sp] )
});
if(this.props.map){
const leafletMap = this.props.map.leafletElement;
this.hotlineLayer = L.layerGroup(L.polyline(positions, {color: newColour})).addTo(leafletMap);
}
++i;
A polyline requires at least two sets of lat, longs. Could you point out where in your code are you forming polylines?
In your code, the range.map the operation will only lead to creating an array of positions. And hence, your code is rendering a single line.
If you intend to create multiple polylines and render them using LayerGroup, I would suggest something in the lines of:
var latlngs1 = [
[45.51, -122.68,0],
[37.77, -122.43,1],
[34.04, -118.2,2]
];
var latlngs2 = [
[34.04, -118.2,2],
[32.08, -110.5,2]
];
const polyline1 = L.polyline(latlngs1, {color: 'red'})
var polyline2 = L.polyline(latlngs2, {color: 'blue'})
var hotlineLayer = L.layerGroup([polyline1, polyline2]).addTo(map);
Example Code: https://jsfiddle.net/idhruvs/n75omjbd/32/

adding layers to my Leaflet map using a loop

So here is one of my layers:
TurksAndCaicosLayer = L.geoJson(TurksAndCaicos, {
style: {
weight: 0.5,
color: 'white',
fillOpacity: 1,
fillColor: 'brown',
}})
I have 8 of these polygon layers for my Leaflet map. I am trying to construct a loop which will go through the array of my layers and add them to the map, but it doesn't seem to be working. Can anyone spot why?
let layers = [AnguillaLayer, BermudaLayer, BritishVirginIslandsLayer, GibraltarLayer, GuernseyLayer, IsleOfManLayer, JerseyLayer, TurksAndCaicosLayer]
for (let layer of layers) {
map.addLayer(layer)}
try
layers.forEach(addLayer);
function addLayer(item, index) {
map.addLayer(item);
}
An alternative approach would be to add your layers to a layerGroup and add the layerGroup to the map - saves writing an explicit loop.
let layers = [AnguillaLayer, BermudaLayer, BritishVirginIslandsLayer, GibraltarLayer, GuernseyLayer, IsleOfManLayer, JerseyLayer, TurksAndCaicosLayer];
let myLayerGroup = L.layerGroup(layers).addTo(map);

Adding Properties to Global Objects

I know this is a common question, and I'm a JS newbie, but I'm completely stumped even after searching StackOverflow for hours.
I'm using the Google Maps API, and want to keep track of my markers by association with an ID. So I have var pinArray = new Object() as a global variable, and add markers like this:
function CreateMarkers (data){
data.forEach(function(store) {
<!-- CREATE MAP MARKER -->
var mapLat = store.latitude;
var mapLong = store.longitude;
var mapLatLng = { lat: parseFloat(mapLat), lng: parseFloat(mapLong) };
var marker = new google.maps.Marker({
position: mapLatLng,
title: store.name,
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 8.5,
fillColor: 'Green',
fillOpacity: 0.8,
strokeWeight: 0.6,
},
zIndex: 0
});
cluster.addMarker(marker);
var key = store.Id;
pinArray['${key}'] = marker;
})
}
Where cluster is var cluster = new MarkerClusterer(map);.
When I try to do console.log(pinArray); back outside of the function, I get an empty object: Object {}. I've tried not using string interpolation as well, like pinArray[store.Id] = marker;, but get the same problem.
I need to keep this global associate between pins and IDs because I need to reference and update markers by their ID in other functions. Or at least, I think I do, I'm open to other ways of doing this. Help is very much appreciated; thank you in advance.
Typically when I've done something like this in the past I'll use a standard javascript array instead of an ID'd object:
var pinArray = [];
Then use push to add the markers to it as you go:
pinArray.push(Marker);
When you create the pin you can include your key in its property definition:
var marker = new google.maps.Marker({
position: mapLatLng,
title: store.name,
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 8.5,
fillColor: 'Green',
fillOpacity: 0.8,
strokeWeight: 0.6,
},
zIndex: 0,
key: store.Id
});
and you can write a simple looping lookup function to find the individual map marker if you need to pull them by ID. Something like:
function GetMarkerByKey(key) {
var i = 0;
while (pinArray[i].key != key) {i++}
return pinArray[i];
}
Also, if you're using it in a dynamic event handler for click or hover you can use the this property to identify which marker they are activating it with.
~~~Edited to fix a syntax error~~~
var pinArray assigns the variable within the scope of function it's defined. The safest way to ensure you're defining a variable as global, regardless of where you are inside a function, is to assign it to window.
window.pinArray = new Object();

Fusion Tables layer URL request limit (2048 chars)

I'm using Google Maps to highlight a bunch of countries using Fusion Tables to grab the geometry. You can see an example of this here:
http://jsfiddle.net/4mtyu/689/
var layer = new google.maps.FusionTablesLayer({
query: {
select: locationColumn,
from: tableId,
where: "ISO_2DIGIT IN ('AF','AL','DZ','AD','AO','AG','AR','AM','AU','AT','AZ','BS','BH','BD','BB','BY','BE','BZ','BJ','BT','BO','BA','BW','BR','BN','BG','BF','BI','KH','CM','CA','CV','CF','TD','CL','CN','CO','KM','CG','CD','CR','HR','CU','CY','CZ','DK','DJ','DM','DO','EC','EG','SV','GQ','ER','EE','ET','FJ','FI','FR','GA','GM','GE','DE','GH','GR','GD','GT','GN','GW','GY','HT','HN','HU','IS','IN','ID','CI','IR','IQ','IE','IL')"
},
options : {suppressInfoWindows:true},
styles: [{
polygonOptions: {
fillColor: "#000000",
strokeWeight: "0",
fillOpacity: 0.4
}
}]
});
The problems begin when I try to grab too many items from the table. Google uses a URL with all of the query values to grab the data required and with URL encoding it can grow to be quite large in length.
You can see an example of the URL here if you open up the console and check the URLs being thrown in the errors:
http://jsfiddle.net/4mtyu/690/
The URL it generates in that particular example is 3749 characters, way over the 2048 character limit.
Does anybody have any ideas on a way I could prevent the URL from getting this large but at the same time still be able to select 150+ items?
The easiest solution is to move things client-side:
http://jsfiddle.net/4mtyu/725/
Part 1 :: Initialize the map and fusion tables
You can do this how ever you prefer, just make sure the fusion tables have all countries selected. Example:
function initialize() {
//settings
var myOptions = {
zoom: 2,
center: new google.maps.LatLng(10, 0),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
//get map div
map = new google.maps.Map(document.getElementById('map_div'),
myOptions);
// Initialize padded JSON request
var script = document.createElement('script');
var url = ['https://www.googleapis.com/fusiontables/v1/query?'];
url.push('sql=');
//select all the countries!!
var query = 'SELECT name, kml_4326 FROM ' +
'1foc3xO9DyfSIF6ofvN0kp2bxSfSeKog5FbdWdQ';
var encodedQuery = encodeURIComponent(query);
//generate URL
url.push(encodedQuery);
url.push('&callback=drawMap');//Callback
url.push('&key=AIzaSyAm9yWCV7JPCTHCJut8whOjARd7pwROFDQ');//select all countries
script.src = url.join('');
//Add Script to document
var body = document.getElementsByTagName('body')[0];
body.appendChild(script);
}
Part 2 :: Sort countries and render
(a) Once you have the full list of countries, you have to sort them. A simple indexOf check should do the trick.
(b) After sorting we need turn our countries into LatLon Coordinates, this is done in the constructNewCoordinates function (see below)
(c) Then all that's left is to generate the polygon and add it to our map!
Example:
var countries = [...];
//This is the callback from the above function
function drawMap(data) {
//Get the countries
var rows = data['rows'];
for (var i in rows) {
// (a) //
//If the country matches our filled countries array
if (countries.indexOf(rows[i][0]) !== -1)
var newCoordinates = [];
// (b) //
// Generate geometries and
// Check for multi geometry countries
var geometries = rows[i][1]['geometries'];
if (geometries) {
for (var j in geometries) {
//Calls our render function, returns Polygon Coordinates (see last step);
newCoordinates.push(constructNewCoordinates(geometries[j]));
}
} else {
//Calls our render function, returns Polygon Coordinates (see last step);
newCoordinates = constructNewCoordinates(rows[i][1]['geometry']);
}
// (c) //
//Generate Polygon
var country = new google.maps.Polygon({
paths: newCoordinates,
strokeWeight: 0,
fillColor: '#000000',
fillOpacity: 0.3
});
//add polygon to map
country.setMap(map);
}
}
}
}
Part 3 :: Generating the coordinates
// (b) //
function constructNewCoordinates(polygon) {
var newCoordinates = [];
var coordinates = polygon['coordinates'][0];
for (var i in coordinates) {
newCoordinates.push(
new google.maps.LatLng(coordinates[i][1], coordinates[i][0]));
}
return newCoordinates;
}

OpenLayers, nice marker clustering

Do you know how to have a nice clustering in OpenLayers such as this google example ?
You can add label to pointStyle in above example and explain context of this label.
Your code should be something like this:
var pointStyle = new OpenLayers.Style({
// ...
'label': "${label}",
// ...
}, {
context: {
// ...
label: function(feature) {
// clustered features count or blank if feature is not a cluster
return feature.cluster ? feature.cluster.length : "";
}
// ..
}
});
var styleMap = new OpenLayers.StyleMap({
'default': pointStyle,
});
var googleLikeLayer = new OpenLayers.Layer.Vector("GoogleLikeLayer", {
// ...
styleMap : styleMap,
// ...
});
Use OpenLayers.Strategy.Cluster for clustering.
Example Code
Working Example
Custom Styling
In-depth Explanation
I have just implemented a so called AnimatedCluster strategy for OpenLayers.
You can see a bit more about it at: http://www.acuriousanimal.com/2012/08/19/animated-marker-cluster-strategy-for-openlayers.html
It is only a firts version but adds a nice animation to the clusters. There are many things to improve but it is a starting point.
There's a great clustering example available in OpenLayers 3.
I created a jsFiddle from the code so you can play with it.
Basically you have to create an ol.source.Cluster with a grouping distance from an ol.source.Vector formed by an array of ol.Feature. Each ol.Feature created from your source coordinates in the form of ol.geom.Point.
var features = [
new ol.Feature(new ol.geom.Point([lon1, lat1])),
new ol.Feature(new ol.geom.Point([lon2, lat2])),
...
];
var cluster = new ol.source.Cluster({
distance: 50,
source: new ol.source.Vector({ features: features });
});
var map = new ol.Map({
layers: [
new ol.source.MapQuest({layer: 'sat'}), // Map
new ol.layer.Vector({ source: cluster }) // Clusters
],
renderer: 'canvas',
target: 'map'
});
you can do this with as igorti has said. the soltion is using OpenLayers.Strategy.Cluster class and styling your layer with OpenLayers.Style class...
for styling :
var pointStyle = new OpenLayers.Style({
'default': new OpenLayers.Style({
'pointRadius': '${radius}',
'externalGraphic': '${getgraph}'
....
},{
context:{
radius: function(feature){
return Math.min(feature.attributes.count,7)+3;
},{
getgraph : function(feature){
return 'ol/img/googlelike.png';
}}}};
it must helps you, more power to you!
Here is the JSfiddle for clustering based on custom attributes added to the layers. I struggled a bit with this so putting it here; Also shows creating a summary pie graph image when zoomed out with the clustered data http://jsfiddle.net/alexcpn/518p59k4/
Also created a small openlayer tutorial to explain this OpenLayers Advanced Clustering
var getClusterCount = function (feature) {
var clustercount = {};
var planningcount = 0;
var onaircount = 0;
var inerrorcount = 0;
for (var i = 0; i < feature.cluster.length; i++) {
if (feature.cluster[i].attributes.cluster) {
//THE MOST IMPORTANT LINE IS THE ONE BELOW, While clustering open layers removes the orginial feature layer with its own. So to get the attributes of the feature you have added add it to the openlayer created feature layer
feature.attributes.cluster = feature.cluster[i].attributes.cluster;
switch (feature.cluster[i].attributes.cluster) {
......
return clustercount;
};

Categories