I tried the Interactive Choropleth Map Example form https://leafletjs.com/examples/choropleth/
added a geocoder that places a circle.
But the circle overlays my geojson layer and therefore clicking and hover dosen't work anymore in this area.
I checked out panes tutorial an try to adapt to it. But still not clickable.
Here is a jsfriddle for demonstration https://jsfiddle.net/fhepqrnz/1/
Use the search (right corner) to search for NewYork. Then the circle is drawn. But the state in this area is not anymore highlighted.
// Search
map.createPane('searchradius');
map.getPane('searchradius').style.zIndex = 650;
map.getPane('searchradius').style.pointerEvents = 'none';
var geocoder = L.Control.geocoder({
defaultMarkGeocode: false
})
.on('markgeocode', function(e) {
console.log(e.geocode);
var center = e.geocode.center;
var circle = L.circle(center, {
color: 'red',
fillColor: '#f03',
fillOpacity: 0,
radius: 15000,
pane: 'searchradius'
}).addTo(map);
map.fitBounds(circle.getBounds());
})
.addTo(map);
Glad if someone have the answer for this.
Tanks to the hint of #IvanSanchez i figured it out.
The interactive: flase is the key
.on('markgeocode', function(e) {
console.log(e.geocode);
var center = e.geocode.center;
var circle = L.circle(center, {
color: 'red',
fillColor: '#f03',
fillOpacity: 0,
radius: 15000,
pane: 'searchradius',
interactive: false
}).addTo(map);
map.fitBounds(circle.getBounds());
})
Related
I am very excited and lot of fun playing with Leaflet.JS on gis mapping stuff. I am newbie. I also very appreciate with bro #Grzegorz T. with the kindness and helping me on introduction me to Leaflet.JS.
Now, I am plan to do Editing geometry on specific object I select only. I already think how the flow and the result but the process???(hahahaa..). I also already know regarding DrawItems function on Leaflet.JS but I will use.
Let me describe simple flow before I do it...
A. I just using jsfiddle1 #Grzegorz T.
B. I add DrawItems
...
{ 'DrawLayer': drawnItems }, { position: 'topleft', collapsed: false }).addTo(map);
...
//Add Draw Control//
map.addControl(new L.Control.Draw({
edit: {
featureGroup: drawnItems,
poly: {
allowIntersection: false
}
},
draw: {
polygon: {
allowIntersection: false,
showArea: true
}
}
}));
//Draw Objects//
map.on(L.Draw.Event.CREATED, function (event) {
var layer = event.layer;
drawnItems.addLayer(layer);
});
//Get Leaflet Object ID
drawnItems.on('click', function(event) {
console.log("from drawnItems: " + event.layer._leaflet_id);
});
//Get Geometry from Layer & ID
//Edit Only This Objects
//Save This Editing Back to Original Layer & ID
on this part I saw a Problem is:
1. I don't know how to copy original geometry I selected from layer to DrawLayer.
2. Hide only this geometry(id) on original layer until end of editing or cancel. (maybe change opacity to invisible)
3. After finish editing and while saving How I can save back to original layer and show the result to map.
I hope whos hardcore and whos already found the easy way on Leaflet.JS can help me for this dirty work....
Update 3/3/2022
I found how to restyle the object(geometry) I selecting and this was cover for:
2. Hide only this geometry(id) on original layer until end of editing or cancel. (maybe change opacity to invisible)
Code like below:-
onEachFeature: function (feature, layer) {
//restyle the geom when display
layer.setStyle({
fillColor: "white",
weight: 2,
color: "#eb4034",
fillOpacity: 0.7,
});
layer.on("mouseover", function (e) {
// style
this.setStyle({
fillColor: "#eb4034",
weight: 2,
color: "#eb4034",
fillOpacity: 0.7,
});
});
layer.on("mouseout", function () {
// style
this.setStyle({
fillColor: "#3388ff",
weight: 2,
color: "#3388ff",
fillOpacity: 0.1,
});
});
layer.on("click", function () {
this.setStyle({
fillColor: "transparent",
weight: 0,
color: "transparent",
fillOpacity: 0,
});
});
},
Update 4/3/2022
Anyone can help me how to passing geometry to drawnitems programmatically with editing mode? Let say I have whatever geometry like this below:-
......
{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[16.3716,54.4414],[16.3946,54.4477],[16.4315,54.487],[16.4797,54.5164],[16.4968,54.5231],[16.5299,54.5407],[16.6145,54.5598],[16.6887,54.5696],[16.6991,54.5692],[16.7126,54.5542],[16.7392,54.5384],[16.7481,54.5276],[16.7392,54.5177],[16.7566,54.4946],[16.764,54.4861],[16.7933,54.4874],[16.8275,54.4648],[16.8211,54.4563],......
........
,"properties":{"id":4,"nazwa":"zachodniopomorskie"},"id":3}
How I can pass this polygon (geometry) into drawnItems layer programmatically?
Please help me and thanks you on advance for read this message.
After struggling a few days finally I found solutions to accomplish my task. It's not pretty but at least I fill ok and all I need are there.
I using
layer.on("click", function(e) {
to get the geometry and id from original layer. The original geometry I pass to drawnItems by using
geojsonLayer = L.geoJson(oriGeom);
geojsonLayer.getLayers()[0].addTo(drawnItems);
to draw back on drawing layer to do editing. On mean while I adjust the style on original geometry to invisible. The editable geometry only can see on this stage where user 'think' this is original geometry he/she do editing right now.
onEachFeature: function (feature, layer) {
//restyle the geom when display
layer.setStyle({
fillColor: "white",
weight: 2,
color: "#eb4034",
fillOpacity: 0.7,
});
layer.on("mouseover", function (e) {
// style
this.setStyle({
fillColor: "#eb4034",
weight: 2,
color: "#eb4034",
fillOpacity: 0.7,
});
});
layer.on("mouseout", function () {
// style
this.setStyle({
fillColor: "#3388ff",
weight: 2,
color: "#3388ff",
fillOpacity: 0.1,
});
});
layer.on("click", function () {
this.setStyle({
fillColor: "transparent",
weight: 0,
color: "transparent",
fillOpacity: 0,
});
After finish the editing I save back to original layer by using Python class by search ID and replace the original coordinates to new coordinates (editGeom) only. :)
Then I delete all object inside drawnItems layer by this trick
document.querySelector(".leaflet-draw-edit-remove").click(); //fake click Delete
document.querySelector("ul li:last-child a").click(); //fake click Save All
That's all.
I'm trying to draw a circle on my Leaflet Map that should be always visible and centered even when user move or zoom in the map.
The following code works well when user move the map, but when the user zoom in or zoom out, the size of the circle is not updated. I would like to keep always the same dimension for the circle.
HTML
<div id="map" class="map" style="height:75vh;"></div>
JS
// Init Leaflet Map basically
this.map = L.map("map").setView([38.63, -90.23], 12);
window.map = this.map;
this.tileLayer = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
maxZoom: 20,
maxNativeZoom: 18,
attribution: '© OpenStreetMap, © CARTO'
});
this.tileLayer.addTo(this.map);
// Create circle that will be always visible and will have alwaus the same width.
this.circle = L.circle([38.63, -90.23], 3000, {
color: '#5d78ff',
fillOpacity: 0
}).addTo(this.map);
// Set circle always centered when map is moved.
this.map.on("moveend", (s) => {
this.circle.setLatLng(this.map.getCenter());
});
// todo: Set circle always centered when map is zoom in/out
this.map.on("zoomend", (s) => {
this.circle.setLatLng(this.map.getCenter());
console.log('test');
});
JSFIDDLE
https://jsfiddle.net/4uorasdn/
You can use CircleMarker instead of using Circle.
The relevant part of your code that needs to be changed should look something like this.
this.circle = L.circleMarker([38.63, -90.23], {
radius: 200,
color: '#5d78ff',
fillColor: '#f03',
fillOpacity: 0.2,
opacity: 1,
title: "test"
}).addTo(this.map);
And you can find a working jsfiddle here.
I am getting stuck when trying to set google map's polyline icon on the center of a line.
I am using a custom car icon which is not getting set properly on the polyline that I am drawing on the map. Please see the screenshot:
If I use the icon provided by the Google API by using path (path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW) it shows on the center of the line.
Please see the below image:
How can we set the car icon on the middle of the line? Please check the sample code here.
For the car icon I am using the below code, is anything needed to be modified here?
var iconsetngs = {
path: 'M25.395,0H17.636c-3.117,0-5.643,3.467-5.643,6.584v34.804c0,3.116,2.526,5.644,5.643,5.644h11.759' +
'c3.116,0,5.644-2.527,5.644-5.644V6.584C35.037,3.467,32.511,0,29.395,0z M34.05,14.188v11.665l-2.729,0.351v-4.806L34.05,14.188z' +
'M32.618,10.773c-1.016,3.9-2.219,8.51-2.219,8.51H16.631l-2.222-8.51C14.41,10.773,23.293,7.755,32.618,10.773z M15.741,21.713' +
'v4.492l-2.73-0.349V14.502L15.741,21.713z M13.011,37.938V27.579l2.73,0.343v8.196L13.011,37.938z M14.568,40.882l2.218-3.336' +
'h13.771l2.219,3.336H14.568z M31.321,35.805v-7.872l2.729-0.355v10.048L31.321,35.805z',
fillColor: 'blue',
fillOpacity: 1,
scale: 0.4,
strokeColor: 'gray',
strokeWeight: 0.4,
offset: '50%'
};
var polyOptions = new google.maps.Polyline({
path: path,
strokeColor: '#0c0bbb',
strokeWeight: 1.5,
map: this.map,
icons: [{
icon: iconsetngs,
repeat: '70px',
}]
});
polyOptions.setMap(this.map);
You will need to modify the anchor point of the icon. In the fork of your example I have added anchor: new google.maps.Point(23, 0), there are some details of the extra poperties available under Complex icons in the Google Maps documentation.
I have a problem with google maps on mobile browsers.
The project I'm working on requires about 500 markers to be shown on a map, but when adding them, the ui freezes.
I'm using markerclusterer to add markers, and performance is fine once the markers are on the page. Is there a way to add the markers asynchronously, or to pause adding markers once the user starts scrolling?
This is the code we're using:
var mcOptions = { gridSize: 50, maxZoom: 15, zoomOnClick: false };
var mc = new MarkerClusterer(context.map, [], mcOptions);
getMarkerLocations().then(function(branches){
branches.forEach(function(branch) => {
var marker = new google.maps.Marker({
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 2,
strokeColor: 'red',
fillColor: 'red',
strokeWeight: 2,
fillOpacity: 1
},
position: new google.maps.LatLng(branch.Latitude, branch.Longitude),
visible: true
});
mc.addMarker(marker);
});
});
Thank you geocodezip, that worked like a charm! For anyone else with the same problem, here's how I fixed it:
.then(function(branches){
var loopFunction = function(branchesToAdd) => {
if (branchesToAdd.length === 0) return;
var item = branchesToAdd.pop();
var marker = new google.maps.Marker({
....
});
mc.addMarker(marker);
setTimeout(function(){loopFunction(branchesToAdd)}, 30);
};
loopFunction(branchesToShow);
});
Add the markers asynchronously, use setTimeout to schedule the addition of each marker, which will give the browser some time to render and respond to the UI.
I am currently trying to implement semantic zooming similar to the way shown in Mike Bostock demonstrates in this d3 example with the circle markers in the javascript google maps api. I cannot figure out how to change styles (radius, opacity) of these markers after they have already been created on the zoom action. Is there a way to do this without removing them and then recreating them with a different size?
// Overlay for eruptions
for (var eruption in eruptions) {
var coordinates = new google.maps.LatLng(eruptions[eruption].Latitude, eruptions[eruption].Longitude);
var eruptionCircle = new google.maps.Circle({
class: 'marker eruption',
strokeColor: ERUPTION_COLOR,
strokeOpacity: marker_border_opacity(),
strokeWeight: 2,
fillColor: ERUPTION_COLOR,
fillOpacity: marker_opacity(),
map: map,
center: coordinates,
radius: eruption_size(eruptions[eruption].VEI),
});
ERUPTIONS.push(eruptionCircle);
}
map.addListener('zoom_changed', function() {
var zoomLevel = map.getZoom();
// TODO - need to find a way of semantically zooming on these markers
});
You can use setOption
eruptionCircle.setOptions({radius: eruption_size(yourNewRadius)});
You have a mistake too (remove the last , form option this way
var eruptionCircle = new google.maps.Circle({
class: 'marker eruption',
strokeColor: ERUPTION_COLOR,
strokeOpacity: marker_border_opacity(),
strokeWeight: 2,
fillColor: ERUPTION_COLOR,
fillOpacity: marker_opacity(),
map: map,
center: coordinates,
radius: eruption_size(eruptions[eruption].VEI)
});