Is there any possible way to show the properties of geojson without feature in leaflet? - leaflet

In leaflet, I can visualize the geojson layers using following script;
L.geoJSON('district.json', {
style: myStyle,
onEachFeature: function(feature, layer) {
layer.bindPopup(feature.properties.name);
}
}).addTo(map);
The above code shows the features on the map and also show the name properties when clicked on map. But what I want is different. I want to hide the feature of the district.json on map, but It should be appear the popup content when I clicked on the feature position. I tried following style;
var myStyle = {
fillColor: rgb(0,0,0,0),
opacity: 0,
strokeOpacity: 0,
}
This will hide the layers, but when I clicked on the map, nothing will popup. Is there any possible styles for this conditions?

You can simply change the value of opacity to 0.01 so that the layer will disappear from the map but there still remaining the popup content.
For this change your myStyle variable in following way;
var myStyle = {
fillColor: rgb(0,0,0,0.01),
opacity: 0.01,
strokeOpacity: 0.01,
}

You could use circle markers as following:
L.geoJSON('district.json', {
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, {color: 'transparent', fillColor: 'transparent', radius: 20});
},
onEachFeature: function(feature, layer) {
layer.bindPopup(feature.properties.name);
}
}).addTo(map);
This way, you add a transparent, non-visible circle marker for each feature. You can also try different radius values that will lead to larger or smaller clickable areas.

Related

leaflet.js (using geojson data) country labels incorrect

I'm using leaflet.js (with geojson) to display a map. [Removing some of the code code to make it more concise].
$.getJSON('./api/map/data', function(data){
let minZoom = 2.25
let defaultZoom = 2.25
let map = L.map('map', {
minZoom: minZoom,
zoomSnap: 0.1
}).setView([43, 0], defaultZoom);
let onEachFeature = (feature, layer) => {
var label = L.marker(layer.getBounds().getCenter(), {
icon: L.divIcon({
className: 'countryLabel',
html: feature.properties.name,
iconSize: [0, 0]
})
}).addTo(map);
};
L.geoJson(data, {
clickable: false,
style: {},
onEachFeature: onEachFeature,
}).addTo(map);
I used this website to download vector maps. Some of the labels are clearly incorrect (and some of them are almost correct). On inspection it seems like some of the lat/longs are not correctly set (or so it seems). Any feedback on how i could make this show up correctly? It would be great if i could come up with labels such that they fit the country borders (meaning maybe add country code wherever necessary).
The problem is connected with your label options. At this moment, your icon position pointing to left top corner of your label and you need to set offset to move label to the center of coordinates. Property that might help you is iconAnchor (see leaflet docs)

In Leaflet, how to make a style the default style from now on

I have geoJson map regions rendered on a map with an initial opacity. I have a slider to change that opacity on the fly.
Here is the bit where I set the opacity on the fly (typescript), which I perform on the input change event within my custom leaflet control:
this.layers.forEach((r: L.GeoJSON<any>) => {
r.eachLayer((layer: any) => {
layer.setStyle({ fillOpacity: vm.mapOptions.heatmapOpacity });
});
});
setTimeout(() => this.map.invalidateSize());
I also have the ability to hover over the regions, in which case I lower the opacity and put a border on the active region when they hover.
When they leave the region, it currently uses resetStyles on that region to reset it back to the previous style. I set this up in the options onFeature callback. The region is highlighted in the mouseover event, and reset in the mouseout event, as seen below.
options = {
style: { stroke: false,
fillColor: regionColor,
fillOpacity: mapOptions.heatmapOpacity },
onEachFeature: (feature, layer) => {
layer.on({
mouseover: (e)=> {
const lr = e.target;
lr.setStyle({
weight: 5,
color: "#666",
dashArray: "",
fillOpacity: 0.7,
stroke: true
});
if (!L.Browser.ie && !L.Browser.opera12 && !L.Browser.edge) {
lr.bringToFront();
}
},
mouseout: (e) => {
prop.featureGeoJson.resetStyle(e.target);
}
});
}
};
The problem is, if I have used setStyle to set the opacity to a different value, then I go into a region, then I leave the region again, calling resetStyle resets the style back to the original default style, before the change to the opacity was made.
Is it possible to set the default style on the layer, so that calling resetStyle will set the styles to my value with the new opacity, and not to the original opacity set when the region was created? How would I do that?
The resetStyle method of a Leaflet GeoJSON Layer Group re-applies the style that was applied at the time of creation of that group, or the default one if you did not provide style:
Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events.
If you later change the style of one or all of the vector layers in that group, it will be therefore overridden when you use resetStyle, and the initial style will be applied.
An easy workaround is simply to modify the GeoJSON Layer Group's style option as well. However, it will affect all its child layers:
group.options.style = newStyle;
(that is what is suggested in #GabyakaGPetrioli's answer, but you have to apply it on the group, not on individual features)
Another solution would be to record the new style of each vector layer, and use that recorded value when you want to restore the previous state, instead of using the group's resetStyle method.
var map = L.map("map").setView([48.85, 2.35], 12);
var geojson = {
type: "Feature",
geometry: {
type: "Point",
coordinates: [2.35, 48.85]
}
};
var point;
var startStyle = {
color: "red"
};
var newStyle = {
color: 'green'
};
var group = L.geoJSON(geojson, {
style: startStyle,
pointToLayer: function(feature, latlng) {
point = L.circleMarker(latlng);
assignStyle(point, startStyle);
return point;
}
}).addTo(map);
// Record the style to the individual vector layer if necessary.
function assignStyle(leafletLayer, newStyle) {
leafletLayer.setStyle(newStyle);
leafletLayer._recordedStyle = newStyle;
}
// When desired, apply the style that has been previously recorded.
function reassignStyle(leafletLayer) {
leafletLayer.setStyle(leafletLayer._recordedStyle);
}
document.getElementById('button').addEventListener('click', function(event) {
event.preventDefault();
// Either use the wrapper function that records the new style…
//assignStyle(point, newStyle);
// Or simply modify the group's style option, if it is acceptable affecting all child layers.
point.setStyle(newStyle);
group.options.style = newStyle;
});
group.on({
mouseover: function(e) {
e.target.setStyle({
color: 'blue'
});
},
mouseout: function(e) {
//reassignStyle(e.layer);
group.resetStyle(e.layer);
}
});
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.0.3/dist/leaflet.css">
<script src="https://unpkg.com/leaflet#1.0.3/dist/leaflet-src.js"></script>
<div id="map" style="height: 100px"></div>
<button id="button">Change color to Green…</button>
<p>…then mouseover and mouseout</p>
Use L.Util.setOptions
so instead of
layer.setStyle({ fillOpacity: vm.mapOptions.heatmapOpacity });
use
L.Util.setOptions(layer, { style: { fillOpacity: vm.mapOptions.heatmapOpacity } });

Leaflet: how to change map center and zoom level clicking on circleMarker?

I'm working on a map with a few circleMarkers. When a user is clickin on one of this circleMarker, I would like to center the map on this circleMarker and to zoom in. It works when I try this on multipolygon layers, but I didn't succeed on circleMarkers. Does anyone can help me?
Here is the code for my circleMarkers:
<script>
var map = L.map('map', {
center: [41.8, 12.5],
zoom: 5,
zoomControl:true, maxZoom:15, minZoom:4,
});
var feature_group = new L.featureGroup([]);
var raster_group = new L.LayerGroup([]);
var basemap = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer/tile/{z}/{y}/{x}', {
attribution: 'Tiles © Esri — Source: Esri',
});
basemap.addTo(map);
function style1(feature) {
return {
weight: 2,
radius: 10,
opacity: 1,
color: 'black',
weight: 1,
fillOpacity: 1,
fillColor: 'red'
};
}
L.geoJson(villes, {
style: style1,
pointToLayer: function (feature, latlng)
{
return L.circleMarker(latlng).bindLabel( feature.properties.Name, {className: "ville", noHide: true });
}
}
)
.addTo(map)
.showLabel;
</script>.
Here is a link to the complete map.
Thank you.
This can be achieved really simply.
Let's assume marker points to your leaflet marker and map to your leaflet map.
Quick way (recommended)
marker.on("click", function(event) {
map.setView(marker.getLatLng(), 16);
}, marker);
Here, I don't even compute the needed zoom level, because I assume leaflet will have to zoom to its max level anyway.
I could also have added my marker to a L.LayerGroup, even if the main point of a LayerGroup is to group multiple markers.
Anyhow, the more precise way
marker.on("click", function(event) {
map.setView(marker.getLatLng(), map.getBoundsZoom(layerGroup.getBounds());
}, marker);
Note that the quick way will do it nicely too. The second solution might seem more precise but it also slower, and implies a use of LayerGroup which is not the way it has been designed to work (create a new layergroup for each marker).
Don't forget to take yout time reading the docs, it's well-designed and pretty easy to understand.
I find the solution:
function onClick(e) {map.setView(this.getLatLng(),15);}
L.geoJson(villes, {
style: style1,
pointToLayer: function (feature, latlng)
{
return L.circleMarker(latlng).bindLabel( feature.properties.Name, {className: "ville", noHide: true }).on('click', onClick);
}
}
)
.addTo(zoom1)
.showLabel;
Thanks Stranded Kid for your help.

How to apply css on polylines : leaflet

I am working with the application which uses leaflet api.
Introduction
I needed to draw different types of fences, using decorators i can somewhat apply good visuals to the polylines but not much.
Problem
I was willing to show twisted wires instead of dashes, dots or plain lines and I know the twisted wire line will be an image but can't find help about applying custom css to polylines.
Script Example
var fence2Icon = L.icon({
iconUrl: 'xxxx.png',
iconSize: [5, 20]
iconAnchor: [5, 18]
});
// Add coordinate to the polyline
var polylineFence2 = new L.Polyline([], { color: 'red' });
function fencePlace2(e) {
// New marker on coordinate, add it to the map
new L.Marker(e.latlng, { icon: fence2Icon, draggable: false }).addTo(curr);
// Add coordinate to the polyline
polylineFence2.addLatLng(e.latlng).addTo(curr);
var decorator = L.polylineDecorator(polylineFence2, {
patterns:[{offset:5,repeat:'20px',symbol:new L.Symbol.Dash({pixelSize:5})
}]
}).addTo(curr);
}
L.easyButton('fa-flash', function () {
$('.leaflet-container').css('cursor', 'crosshair');
map.on('click', fencePlace2);
polylineFence2 = new L.Polyline([], { color: 'red' });
}).addTo(map);
If someone know anything about polyline or another way please do help.
Thanks for your time:-)
You can add a class in the options of your polyline ...
var polyline = L.polyline(latlngs, { className: 'my_polyline' }).addTo(map);
and add your own settings in the CSS ...
.my_polyline {
stroke: green;
fill: none;
stroke-dasharray: 10,10;
stroke-width: 5;
}
Here is an example: http://jsfiddle.net/FranceImage/9dggfhnc/
You can also access some options directly ...
var polyline = L.polyline(latlngs, { dashArray: '10,10' }).addTo(map);
See Path Options
If you create a polyline you're in fact adding an element to the SVG element which Leaflet uses to draw it's overlays. Styling SVG path elements is different from styling regular HTML elements. There's no such thing as border and background-color etc. It has different properties, if you're interested here's a nice read on the matter:
https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Fills_and_Strokes
You can style Leaflet's path elements when you instanciate them via options or via CSS using the properties (related to styling) described in the documentation here:
http://leafletjs.com/reference.html#path
Via options:
new L.Polyline([...], {
weight: 3,
color: 'red',
opacity: 0.5
}).addTo(map);
Via CSS:
new L.Polyline([...], {
className: 'polyline'
}).addTo(map);
.polyline {
weight: 3,
color: red,
opacity: 0.5
}
However, what you want, using an image simply isn't possible. You can use images as fill for SVG paths, but it would be impossible for your usecase. You'de need to add a pattern definition to the SVG Leaflet is using and then you could use that id as the fill property as outlined in this answer:
https://stackoverflow.com/a/3798797/2019281 but will always fill/tile the image horizontally which won't work if your polyline is vertical.

How to update related layer style in featuregroup in leaflet API

I am trying to set style for related layers in a featureGroup using Leaflet API, here is my code:
var highlightStyle = {
color: '#9b1d41',
weight: 3,
opacity: 0.6,
fillOpacity: 0.65,
fillColor: '#9b1d41'
};
$wnd.mapareas.eachLayer(function(layerOnMap) {
layerOnMap.setStyle(highlightStyle);
console.log(layerOnMap);
});
I could see in the log that layer has new set style , but its not visible on map, like color is not changed.
For GeoJSON layers (which are FeatureGroups) you could do like this
new L.GeoJSON(mp, {
style: highlightStyle
});
For standard FeatureGroup
new L.FeatureGroup([mp1, mp2]).setStyle(highlightStyle);