Custom Overlays in OpenLayers 3 - javascript

Currently I am working on Openlayers 3.
I used custom overlays in Google maps Javascript api v3 to add customized markers as html div on the map. And these markers are grouped and plotted in different custom overlays.
Now I am trying to implement the same in OpenLayers 3, but I couldn't find any solution as the overlays in OpenLayers 3 takes one marker in one overlay.
Can I group overlays in OpenLayers 3 in order to group the markers? Or Is there any other options available?

You have multiple possible options.
A) If you have only one dataset, then you could use a StyleFunction. See this ol3 vector example, more specifically this section of code:
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
url: 'https://openlayers.org/en/v3.20.1/examples/data/geojson/countries.geojson',
format: new ol.format.GeoJSON()
}),
style: function(feature, resolution) {
style.getText().setText(resolution < 5000 ? feature.get('name') : '');
return style;
}
});
See the style property? It can be a ol.style.Style or a style function, like demonstrated above. The function receives the feature and current resolution of the map view as argument and is called every time the feature gets rendered (or re-rendered). Returning a ol.style.Style or array of style objects will render the feature using the/these styles.
The feature can have unique properties, i.e. feature.getProperties(). Using as many properties within the feature(s), you can return a unique array of unique style objects.
Here's a more complex ol3 example featuring style functions that you can look and have an example of dynamic styling depending on the resolution. That could give you a better idea of what you could do with the feature properties.
B) If you have multiple datasets, then you can create one vector layer per dataset and define a unique style object on the layer, which would render the features all the same.

Related

Want to merge group of tracts with esri using javascript

I am using Esri web with javascript to create a heat map of tracts.
There are groups of tracts that represent one area so I want to merge and remove the bounders between them.
How can I do this?
This is How I draw the tracts:
var featureLayer = new FeatureLayer({
url: "https://services.arcgis.com/P3ePLMYs2RVChkJx/arcgis/rest/services/USA_Census_Tract_Areas_analysis_trim/FeatureServer/0",
outFields: ["*"],
renderer: renderer,
definitionExpression: "FIPS IN (" + fips + ")"
});
Well, It seems clear that your want to create one large polygon out of too many small polygons(group of tracts).
Follow below steps to achieve this-
don't add feature layer on the map
Create an empty map with basemap and add a graphics layer on it.
query the group of tracts from the layer using esri query task and store the geometry in an array.
use esri gemetryEngine union method and pass the array to it.
union will return a big ploygon without the inner boundaries of 'group of tracts'.
create an esri graphics with new polygon symbol and union polygon geometry.
Add that graphics to the previously added graphics layer.
Feel free to shoot your further queries.
Hoping this will help you :)

Which is base layer out of two tile layers

I can't find docs about it, consider:
// base map
L.tileLayer('http://tiles.mapc.org/basemap/{z}/{x}/{y}.png',
{
attribution: 'Tiles by MAPC,
Data by MassGIS',
maxZoom: 17,
minZoom: 9
}).addTo(map);
// bike lanes
L.tileLayer('http://tiles.mapc.org/trailmap-onroad/{z}/{x}/{y}.png',
{
maxZoom: 17,
minZoom: 9
}).addTo(map);
So we added two tile layers to the map right? But which of the above two is set as a base layer now?
Can a map have multiple base layers at once? (because I read somewhere base layers normally should be mutually exclusive).
Extra: Can I change a base layer without using the layer control mechanism? (e.g. only programatically).
So we added two tile layers to the map right? But which of the above
two is set as a base layer now? Can a map have multiple base layers at
once? (because I read somewhere base layers normally should be
mutually exclusive).
Yes they are mutually exclusive in display so that means you can display only one layer at a time. It's not documented but the last layer added will become the base layer which is being displayed.
Extra: Can I change a base layer without using the layer control
mechanism? (e.g. only programatically).
Yes you can using addLayer/removeLayer method.
map.removeLayer(base map layer name here);
map.addLayer(bike lane layer name here);
So we added two tile layers to the map right?
Yes.
But which of the above two is set as a base layer now?
Leaflet has no concept of base layer, so the answer is "none".
Can a map have multiple base layers at once? (because I read somewhere base layers normally should be mutually exclusive).
Depends on what you consider to be a "base layer".
I can, for example, have a map with several sets of opaque tiles, each of them being able to function as a base layer of a map, and make one of them semitransparent.
Usually, map frameworks assume that a tilelayer (or one tilelayer in a set of tilelayers) can be the basic information for your map, and in those circumstances, such set of tilelayers should be exclusive. Hence the wording of L.Control.Layers.
Leaflet does not constrain you to have a fully-opaque exclusive L.TileLayer. You can even have a Leaflet map without a single L.TileLayer. And of course, you can control visibility of your layers with map.removeLayer(lyr), map.addLayer(lyt), layer.addTo(map) and layer.remove(). Ultimately, the logic to control layer exclusivity (and opacity) is up to you.

Setting the selected layer on a Leaflet/Mapbox L.Control.Layers

I have a map with a few base layers. Users can choose the base layer and then save the map. After saving the map, the system loads it with the new base layer. That base layer should be selected in the L.Control.Layers control. However, there's no way in the API to select a base layer.
Anyone knows a way around this, or a different plug in?
UPDATE: Here is the code I use. MapConfigs has the ids in MapBox, and can create the map that L.control.layers requires.
var map = L.mapbox.map( components.mapDivId , MapConfigs.idFor(baseLayerName) );
map.addControl( L.control.layers(
MapConfigs.toBaseLayersControlMap(map)
).setPosition("topright"));
Thanks!
Why not store references to all the base layers available in a hash, then use addLayer or removeLayer (http://leafletjs.com/reference.html#map-addlayer) as needed to programmatically select base layers?. Something like below.
var tileLayers = {light: L.tileLayer('lightUrl'),dark: L.tileLayer('darkUrl')}

Changing the style of each feature in a Leaflet GeoJSON layer

I have been studying the Leaflet Chloropleth example.
In my Leaflet application, I have a jQuery dropdown that, when selected, fires a function that takes the name of a state as an argument. I want to use that state name to update the Chloropleth map.
What is the pattern for changing the style of a Leaflet GeoJSON layer? Should I recreate the layer I created with L.geoJson() a second time? It seems as though the layers are drawing on top of each other with that approach.
I can provide a Fiddle if needed.
To expand on the answer by #tmcw, the strategy is to pass a function to geojsonLayer.eachLayer() that changes the style for each feature instance within geojsonLayer.
Here is some code that demonstrates this strategy that I lifted and simplified from the code posted on the Mapbox example page referenced by #tmcw. My code example changes the style of each of the feature instances within geojsonLayer based on the value of a specified property on each feature instance.
var geojsonLayer = L.geoJson(...); // a GeoJSON layer declared in the outer scope
function restyleLayer(propertyName) {
geojsonLayer.eachLayer(function(featureInstanceLayer) {
propertyValue = featureInstanceLayer.feature.properties[propertyName];
// Your function that determines a fill color for a particular
// property name and value.
var myFillColor = getColor(propertyName, propertyValue);
featureInstanceLayer.setStyle({
fillColor: myFillColor,
fillOpacity: 0.8,
weight: 0.5
});
});
}
restyleLayer('myProperty');
Here's an example of changing a choropleth to classify on different properties - the trick is to call setStyle again with different values.
The official documentation of Leaflet explains that:
https://leafletjs.com/examples/geojson/
The style option can be used to style features two different ways. First, we can pass a
simple object that styles all paths (polylines and polygons) the same way
...
Alternatively, we can pass a function that styles individual features based on their
properties. In the example below we check the "party" property and style our polygons
accordingly ...
L.geoJSON(states, {
style: function(feature) {
switch (feature.properties.party) {
case 'Republican': return {color: "#ff0000"};
case 'Democrat': return {color: "#0000ff"};
}
}
}).addTo(map);
Unfortunately, the names of the styles are not equal to css style names.
For example, instead of 'stroke' use 'color' and instead of 'stroke-width' use 'weight':
https://leafletjs.com/reference-1.6.0.html#path-option

Loop through Leaflet Map layers

I'm using Leaflet JS to build my maps, but I'm having a few issues selecting layers.
I'm aiming to fit my map to a polygon. Leaflet generates a Leaflet ID for each element on the map, but these IDs are random. So I want to create an array which links each Leaflet ID with a known polygon ID.
The concept comes from here How to interact with leaflet marker layer from outside the map? but I'm unsure how to implement it.
The object 'map._layers' stores all the elements including the ID of each polygon. So I'm looping through it as follows:
var idstore = [];
for (var x in map._layers) {
// here idstore[x['polyid']] = x;
}
Now I can use that array to associate my polygon IDs to Leaflet IDs. The resulting array should be as follows:
array('polygonid'=>'leafletid','155447'=>'478','748745' => 479);
My problem is the loop isn't working correctly. I can only see the first 2 records coming up which are actually overlays (map tiles). The elements are definitely in that object though.
What am I doing wrong?
A good first step would be looking through the Leaflet reference documentation and using the documented .eachLayer function instead of a for loop on a private variable.
var idstore = [];
map.eachLayer(function(layer){
// ...
});

Categories

Resources