Leaflet: Pass an extra argument to L.geoJson options - javascript

I'm working on choropleth maps using Leaflet framework. I'd like to have several separate layers for several years, so i' ve written this code (note that only names of 'style2002' and 'style2010' should be passed, without any arguments):
population2002 = L.geoJson(regionData, {
style: style2002
});
population2010 = L.geoJson(regionData, {
style: style2010
});
, there "style" functions which are colouring my vector polygons depening on their attributes (which names are prefix 'Pop_' plus year) are:
function style2002(feature)
{
return {
fillColor: getColor(feature.properties.Pop_2002),
weight: 2,
opacity: 1,
color: 'white',
dashArray: '',
fillOpacity: 0.7
};
}
function style2010(feature)
{
return {
fillColor: getColor(feature.properties.Pop_2010),
weight: 2,
opacity: 1,
color: 'white',
dashArray: '',
fillOpacity: 0.7
};
};
As you can guess, i want to use one "style" function instead of separate functions for each year i need. Something like:
function styleByYear(feature, year)
{
var property = 'feature.properties.Pop_';
property += year;
return {
fillColor: getColor(property),
weight: 2,
opacity: 1,
color: 'white',
dashArray: '',
fillOpacity: 0.7
};
}
But how to pass the second argument to style function? In L.geoJson constructor i write only the name of function, without any arguments, as you can see from the first piece of code!
What should i do?
And one more question: how the first argument ('feature') is passed into layer constructor..?

What if you create a global variable:
var property = 'Pop_' + year
and the edit your function to the following(You should use brackets instead of dot notation):
function styleByYear(feature)
{
return {
fillColor: getColor(feature['properties'][property]),
weight: 2,
opacity: 1,
color: 'white',
dashArray: '',
fillOpacity: 0.7
};
}
I have done something similar to what you're asking based on choropleth tutorial like you. I have multiple buttons that changes map style for different dates.

You could try what is in the Leaflet tutorial on GeoJSON. Look for the second code section in the "Options" section. You would just add the normal styling first (i.e. the stuff that is the same for both years). Example taken from that site adding your particular code:
geojsonlayer = L.geoJson(regionData, {
style: function(feature) {
var finalStyleObject = normalStyling(feature); //return the normal style object
switch (feature.properties) { //switch through the various years
case 'Pop_2002': {finalStyleObject.fillColor: "#ff0000"};
case 'Pop_2010': {finalStyleObject.fillColor: "#0000ff"};
}
return finalStyleObject;
}
});
function normalStyling(feature){
return {
weight: 2,
opacity: 1,
color: 'white',
dashArray: '',
fillOpacity: 0.7
};
}

Related

How to add custom region names on a leaflet.js map

I have created a map using leaflet.js which takes data sets from a geojson file.
Since the map is offline, it does not show the region names or tiles. I want the names to be taken from my geojson file (feature.properties.name) and shown on each region (there are only 30 regions) permanently as simple text but not in the form of tooltip.
Any help would be highly appreciated.
var map = L.map('map').setView([65.5, 29.9], 2);
};
function style(feature) {
return {
weight: 2,
opacity: 1,
color: '#AAAAAA',
dashArray: '3',
fillOpacity: 0.7,
fillColor: getColor(feature.properties.density)
};
}
geojson = L.geoJson(statesData, {
style: style,
onEachFeature: onEachFeature
}).addTo(map);
<div id="map" class="m-auto"></div>
<?php include "../regions-map.php"; ?>

How to draw a dotted Polygon and Circle using "#react-google-maps/api"?

I am using #react-google-maps/api": "1.8.2" and wanted to draw a dotted polygon and circleBut when I pass options ({icons: [icon: lineSymbol, repeat: '10px]}) to the or . its not working.
const lineSymbol = {
path: 'M 0,-1 0,1',
scale: 2,
strokeColor: 'green',
strokeOpacity: 1,
}
const polygonProps = {
options: {
fillOpacity: 0,
icons: [{
icon: lineSymbol,
offset: '0',
repeat: '10px',
}, ],
// strokeColor: polygonData.strokeColor,
// strokeWidth: 1,
zIndex: polygonData.zIndex || 10,
},
path: polygonData.pointList.map(item => ({
lat: item[0],
lng: item[1]
})),
title: polygonData.title,
}
<
Polygon {
...polygonProps
}
/>
here I found similar task on google map here
You cannot customise the stroke of Polygons and Circles like you can with Polylines.
We customise Polylines with the following syntax:
// Define a symbol using SVG path notation, with an opacity of 1.
const lineSymbol = {
path: "M 0,-1 0,1",
strokeOpacity: 1,
scale: 4
};
From the Google Docs:
Symbols are useful when you want to use a vector-based icon on a marker, or add an image to a polyline
Here is a working example showing how to customise polylines.
Your only option (this won't work with Circles, only Polygons) is to render your Polygons as Polylines, which you can then style. Personally I would not bother.
Sorry I don't have better news for you!

Changing style of map elements dynamically

I am attempting to change the style of a number of map elements on the fly, without success. By on the fly I mean changing the color of a map element, the water mass for instance, dynamically from a computed color. Using Tangram but open to other engines if there is a better solution. Since Tangram uses a YAML file to style the various elements, I am using inline Javascript on the scene (YAML) file. In other words, instead of giving it a fixed color, I want to compute the color (from an image). Instead of this:
water:
draw:
polygons:
color: "blue"
I am doing something along these lines (further complicated because I am using Vue Router):
water:
draw:
polygons:
color: function() { return this.colors[0]; }
computedColors is computed in a mixing, then broadcasted to the appropriate route:
var colorize = {
data: function () {
return {
computedColors: []
};
},
created: function () {
this.getColors();
},
methods: {
getColors: function () {
...
self.computedColors = [
...
];
self.$broadcast('parent-colors', self.computedColors);
...
};
};
}
Here is the route:
router.map({
'/map': {
name: 'map',
component: Vue.extend({
template: '#map',
mixins: [colorize],
data: function () {
return {
colors: []
};
},
events: {
'parent-colors': function (computedColors) {
this.colors = computedColors;
}
},
ready: {
var map = L.map('map');
var layer = Tangram.leafletLayer({
scene: './tiles/scene.yaml'
});
layer.addTo(map);
map.setView([40.70531887544228, -74.00976419448853], 15);
}
});
Any hints on what I may be doing wrong appreciated.
UPDATE
I am getting an error of sorts. It is related with Tangram but not quite able to figure out what it is exactly. Seems to be an issue with the parsing of the YAML file. If I change this in my scene.yaml:
water:
draw:
polygons:
color: function() { return this.colors[0]; }
With this:
water:
draw:
polygons:
color: function() { return this.color1; }
I get no errors but unfortunately the water mass still isn't assigned any color either.
Of course, I had to change these lines in the map route instance too:
data: function () {
return {
color1: ''
};
},
...
events: {
'parent-colors': function (computedColors) {
this.color1 = computedColors[0];
}
}
The following doesn't offer a solution to the specific problem of styling a Tangram map on the fly (which Yaml doesn't seem to easily allow), but it partially answers the question of how to style map vectors dynamically. It implements the plugin Leaflet.VectorGrid and assigns properties to layers programmatically through the vectorTileLayerStyles method (accomplished in the example below with color: self.colors[6]).
L.vectorGrid.slicer(countries, {
rendererFactory: L.svg.tile,
vectorTileLayerStyles: {
sliced: function() {
return {
stroke: true,
color: self.colors[6],
weight: 0.5,
};
}
},
}).addTo(map);
The variable countries is really just a GeoJson with var countries = added to it, something along these lines:
var countries = {
"type": "FeatureCollection",
"features": [
{ "type": "Feature"
(...)
}
]
};
It's a straightforward solution and it works perfectly with small amounts of data, but since it's a client-side solution it's heavy on the browser when dealing with bigger data sets. Still, it may be useful for those who may be looking for a simple way to style a simplified world map or a limited map area on the fly.
UPDATE
A more performant solution is to use a tile server. The example below implements t-rex, with canvas renderer L.canvas.tile in the rendererFactory option instead of L.svg.tile and protobuf:
var lines = "http://127.0.0.1:6767/lines/{z}/{x}/{y}.pbf";
var multilinestrings = "http://127.0.0.1:6767/multilinestrings/{z}/{x}/{y}.pbf";
var multipolygons = "http://127.0.0.1:6767/multipolygons/{z}/{x}/{y}.pbf";
var vectorTileStyling = {
lines: {
weight: .8,
fillColor: this.colors[1],
color: this.colors[1],
fillOpacity: .8,
opacity: .8
},
multilinestrings: {
weight: .8,
fillColor: this.colors[2],
color: this.colors[2],
fillOpacity: .8,
opacity: .8
},
multipolygons: {
fill: true,
weight: .8,
fillColor: this.colors[3],
color: this.colors[3],
fillOpacity: .8,
opacity: .8,
}
};
var externalVectorTileOptions = {
rendererFactory: L.canvas.tile,
vectorTileLayerStyles: vectorTileStyling,
maxZoom: 16,
minZoom: 14
};
L.vectorGrid.protobuf(lines, externalVectorTileOptions).addTo(map);
L.vectorGrid.protobuf(multilinestrings, externalVectorTileOptions).addTo(map);
L.vectorGrid.protobuf(multipolygons, externalVectorTileOptions).addTo(map);

JVectorMap Multimap drill down has different style when drilled down, how can I change this style as well?

This question was asked here as well maybe a year ago, but no answer was provided. I'd like to know how I can make the "drilled-down" map have the same style and background as my main map.
var regionStyling9 = { // This style is set to the main map's regionStyle
initial: {
fill: '#E9E9E9',
stroke: '#505050',
"fill-opacity": 1,
"stroke-width": 1,
"stroke-opacity": 1
},
hover: { fill: "#4DB870" }
};
$(function() {
new jvm.MultiMap({
container: $('#Chart9Map'),
maxLevel: 1,
main: {
map: 'us_aea_en',
backgroundColor: '#fff',
regionStyle: regionStyling9, // Here I set the top level style to the main map
series: {
regions: [{ values: stateMapData, scale: ['#cce2ec', '#006593'], normalizeFunction: 'polynomial' }]
}
},
mapUrlByCode: function(code, multiMap) {
return '../Scripts/JVectorMap/jquery-jvectormap-data-' +
code.toLowerCase() +
'-' +
multiMap.defaultProjection +
'-en.js';
}
});
});
How can I affect the style of the secondary chart like I did for the main chart?
According to the jVectorMap MultiMap Documentation, there is only config for the main map, no other object for the drill down maps...
I know what you mean, I also could not find this info. It is very strange the library doesnt handle this. Its such a well produced package, yet seems to me missing some basics.
Assuming you arent using the free version, the license says you are allowed to modify the code.
Open up the jquery-jvectormap.js file (prettify it is needed).
At the bottom you'll see the lines:
currentMap.params.container.hide(), that.maps[name] ? that.maps[name].params.container.show() : that.addMap(name, {
map: name,
multiMapLevel: currentMap.params.multiMapLevel + 1
}), that.history.push(that.maps[name]), that.backButton.show()
Change this so settings from the main map are passed down to the children (so just add the 3 extra lines):
currentMap.params.container.hide(), that.maps[name] ? that.maps[name].params.container.show() : that.addMap(name, {
backgroundColor: that.params.main.backgroundColor,
series: that.params.main.series,
onRegionTipShow: that.params.main.onRegionTipShow,
map: name,
multiMapLevel: currentMap.params.multiMapLevel + 1

javascript config file for openlayers

I am new to OpenLayers. I am trying to figure out what is the best way to have a configuration file for the map I am creating.
For example, I am creating a map with the following style :
var defaultStyle = new OpenLayers.Style(
{
pointRadius: 10,
fillColor: "yellow",
strokeColor:"#0500bd",
strokeWidth:2,
fillOpacity:0.4,
labelXOffset: "${xOffset}",
labelYOffset: "${yOffset}",
labelAlign: "${align}"
});
I would like to have the pointRadius and fillColor in a config file so I don't have to modify my source code but just the config file.
Shall I create a JS file; config.js with the following content:
var config = {
map:{
style: {
pointRadius: 10,
fillColor: "yellow"
},
},
};
And then, in my other JS that create the style, does:
var defaultStyle = new OpenLayers.Style(
{
pointRadius: config.map.style.pointRadius,
fillColor: config.map.style.fillColor,
strokeColor:"#0500bd",
strokeWidth:2,
fillOpacity:0.4,
labelXOffset: "${xOffset}",
labelYOffset: "${yOffset}",
labelAlign: "${align}"
});
What is recommended?
I cannot say what is "recommended". However Your solution is very similar to the way we do it on our current project. We have been doing like that for over a year have had a lot of success.
We save the configuration in a database as a JSON array, and then allow JS to parse the array.
Also you can then use the OpenLayers.Util.extend function to extend your style:
var config = {
map:{
style: {
pointRadius: 10,
fillColor: "yellow"
},
},
};
var defaultStyle = new OpenLayers.Style(OpenLayers.Util.extend({
strokeColor:"#0500bd",
strokeWidth:2,
fillOpacity:0.4,
labelXOffset: "${xOffset}",
labelYOffset: "${yOffset}",
labelAlign: "${align}"
},config.map.style));
I would do something like this:
var config = {
default_map_style: {
pointRadius: 10,
fillColor: 'yellow'
}
};
And then instead of using it one by one, I would just extend the default map style object with additional properties that I want to use on the fly like so:
var defaultStyle = new OpenLayers.Style(
$.extend({}, config.default_map_style, {
strokeColor: '#0500bd'
}
);
I'm using jQuery.extend above but you can find another implementation of extend in Underscore or Lo-dash if you'd rather not use jQuery. Note that it is important we pass a new object as the first parameter of extend as we don't want to change the default_map_style object.

Categories

Resources