I am trying to draw hundres of circleMarker in a Leaflet map, I am using flask and foundation.js, the same code work in different app built with bootstrap.js
This is my code:
<script src="http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.js"></script>
<script>
var map = L.map('map').setView([40,-4], 6);
L.tileLayer('https://{s}.tiles.mapbox.com/v3/examples.map-cnkhv76j/{z}/{x}/{y}.png', {
attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery CloudMade',
maxZoom: 18
}).addTo(map);
var geojsonMarkerOptions = {
radius: 100,
fillColor: "#FFF803",
color: "#DDFF03",
weight: 1,
opacity: 0.8,
fillOpacity: 0.8
};
{% for item in data['data'] %}
L.circleMarker([{{item[0]}},{{item[1]}}],geojsonMarkerOptions).addTo(map);
{% endfor %}
var marker = L.marker([41.5, -0.09]).addTo(map);
marker.bindPopup("I am a circle.");
var circle = L.circle([51.508, -0.11], 500, {color: 'red',
fillColor: '#f03',
fillOpacity: 1
}).addTo(map);
</script>
At the bottom I tried a fixed marker which appears and fixed circle which doesn´t, could it be a problem with foundation.js? Because in a previous project with other framework worked perfectly.
I tried your code, replacing 51.508 with 41.508 (so the red circle is near the marker) and adding just a single circleMarker. It works. So the problem is not in the code.
Please check that you have included leaflet.css from the same locations as leaflet.js. Also check there are no errors in a javascript console (Ctrl+Shift+J in Firefox). Check that coordinates from {{item[0/1]}} are properly formatted (decimal separator is a dot, no extra symbols). Try using more recent version of Leaflet library, 0.7.3.
Ilja, many thanks. You were right the circles were pushed behind the map by a css. In this case, I was also using d3.js for some chart, and as soon as I got rid of nvd3's css the circles showed up.
I've been having the same issue, and it turns out that it is the nv.d3.css file. I found that commenting out these lines will allow you to draw a circle:
display: block;
width: 100%;
height: 100%;'
I don't know what potential side effects this might have on your page, but I think the main issue is that d3 decides to hijack any svgs that you put on the page.
EDIT: my case was with circles, but I wouldn't be surprised if it is the same problem between circles and circle markers.
EDIT 2:
It's been a while, but someone just liked this, so I feel like I should inform you that in the end, these didn't play nice together. I didn't have the time to really tinker with it, so I was forced to remove the leaflet circles and pass on the project with a recommendation that it might just be easier to plug in Google Maps. Hope that's helpful.
That question was posted long ago.
But May my answer helps someone.
When we instanciate L.CircleMarker(...), the circle is created, but not showing.
In my case, i noticed that it wait for the window resize event in order to display.
So juste trigger that event after L.CircleMarker(...).addTo(map) and the circle will appear like a charm.
With JS
window.dispatchEvent(new Event('resize'));
With Jquery
$(window).trigger('resize');
Related
I don't know much about the front-end components of the web. Please point out if there are any deficiencies in the problem description.
I am currently working on an offline map-related business.
I use tile layers combined with Leaflet.
The entire page has many other components besides the map layer.
The ideal situation is that the map is at the bottom of the page, with only a part of the center Can operate the map.
As shown below
picsimple demo
The problem I'm having now is that the map floats on top of all components,
Neither setting z-index nor using pane has any effect.
as shown in the picture
picinitial position
Drag freely on top of all components
GIF
I hope someone can provide me with a solution, or an example, to help me solve this problem, thanks for the guidance.
My brief implementation idea is like this
initOffMap(){
var that = this
var latlng = L.latLng(30.584355, 114.298572);
that.offMap = L.map('mapContainer', {
center: [30.584355, 114.298572],
zoom: that.zoom,
minZoom: 8,
maxZoom: 11,
maxBounds: L.latLngBounds(L.latLng(34.298747907678184,108.30837249755861), L.latLng(28.31487093107572, 116.70742034912111)),
});
that.offMap.createPane('labels');
that.offMap.getPane('labels').style.zIndex = -50;
var layer = L.tileLayer('http://localhost:8082/hb/{z}/{x}/{y}.png',
{
maxZoom: 11,
minZoom: 8,
autoZIndex: false,
pane: 'labels'
// zIndex: 111,
});
layer.addTo(that.offMap);
},
<div class="mapContainer" id="mapContainer">
<div class="head"></div>
<div class="leftProgressbar"></div>
<div class="leftcirle"></div>
</div>
example
https://plnkr.co/edit/2k8mdrGDLhOQc93L?preview
You can check the above example, I set the background of the header to red, and when you drag the map down, you can clearly see that the map layer floats on the surface and covers the header
You have tagged react-leaflet however that implementation is a regular leaflet implementation. If you do in fact use react you should consider using the react-leaflet package https://react-leaflet.js.org/
It will probably solve your issue.
The examples in the documentation just show the core implementations, but you will be able to find alot of code here on stackoverflow for whatever you will need.
If you in fact do not use react, update your tags and let me know and I will remove this answer.
I'm just getting started creating a Leaflet webapp and I'm failing to draw a rectangle. When I load the page it shows for a split second, barely before the map even loads, and then it disappears (That's in Chrome, in Firefox it doesn't show at all). What am I missing here?
Below is my code:
<script>
var bounds = [[52.42, 4.78], [52.46, 4.88]];
var map = L.map('map', {
maxBounds: bounds,
minZoom: 14
}).setView([52.44, 4.83], 14);
var googleLayer = new L.Google('ROADMAP');
map.addLayer(googleLayer);
$(document).ready(function() {
L.rectangle(bounds, {color: "red", weight: 1}).addTo(map);
});
</script>
I tried drawing the rectangle at the $(document).ready() event but that didn't work.
The rectangle is hidden because the google layer gets drawn on top. Might be a bug, I would expect the layers to be in the z-order in which they get added. Quick fix (check for side effects) is to force the needed order using CSS styles such as these:
.leaflet-google-layer{
z-index: 0 !important;
}
.leaflet-map-pane{
z-index: 100;
}
I am using Leafletjs. Currently its pretty straight forward, I have a streets view from open maps.
var streets = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors'
});
I also have a WMS layer that is coming from a geoserver. It has the standard getFeatureInfo and everything shows up correctly.
L.tileLayer.wms("GEOSERVERURL", {
layers: 'layers',
format: 'image/png'
,transparent: true
}).addTo(map);
The wms layer is also clickable and I use getFeatureInfo to get the info for that layer. The issue is that the user doesn't know its clickable because the cursor never changes when they hover of the wms layer. My question is how do make the cursor change when hovering over the layer?
Has anyone implemented this feature before or have an idea to implement it? The only research I have stumbled across so far has using mouseover on the map and calling getFeatureInfo to tell if its over a layer. However, that seems like it would cause a lot of chatter just to identify cursor area.
EDIT: To clarify, I want the cursor to only change when its hovered over the wms layer that is populated. Although it technically gets applied to the whole map, it only has content on a part of it. Which kind of raises the question of 'Can I limit the wms layer to only the content area and then show a cursor?' Maybe a bounding area or something along those lines?
EDIT 2: Below is an example of what it looks like. The street map parts I want to keep the normal cursor but I want a pointer when hovering over the colored wms map parts.
Set an ID on the tileLayer's container and then use CSS to change the cursor:
Javascript:
var wms = L.tileLayer.wms("GEOSERVERURL", {
layers: 'layers',
format: 'image/png',
transparent: true
}).addTo(map);
wms.getContainer().setAttribute('id', 'wmsContainer');
Stylesheet:
#wmsContainer {
cursor: grab; /* or any other cursor: https://developer.mozilla.org/en-US/docs/Web/CSS/cursor */
}
Note: you need to do this after the layer is added to the map. Before you add it to the map the getContainer method will return undefined.
Edit after question edit and comments:
Unfortunatly that's not possible. At least not as far as i know. Because L.TileLayer.WMS is a layer of images, there is absolutely no way of deducting which tiles have features on them and which are transparent.
What you could do as a workaround is work out the boundaries of your object, use that to create a transparent polygon without stroke and put that over your WMS layer. Polygons are interactive thus you get the cursorchange included, plus as an extra bonus, you can do other fancy stuff like show the outline or something like that on mouseover. I've created a little demo from the WMS example you supplied in the comments.
http://plnkr.co/edit/1HGn6IUzdrn1N5KGazXQ?p=preview
Note that i'm using a GeoJSON layer with one feature instead of a polygon, because it was easier to find the outline of the US in GeoJSON format. But in your case a four point polygon would do the trick just as wel.
Hope that helps, let me know if something isn't clear.
Working on this application which I have broken down here.
http://jsfiddle.net/pPMqQ/81/
In this example I want to
show markers only inside the shape area
allow for zoom of the map and scaling of the shape area
here is my pseudo code
identifyMarkersInShape: function(){
//__ function is invoked every time a shape is drawn/editted
// hides all the markers
//finds the markers inside the given shape
},
bindEvents: function(){
//handle zoom of the map and scale of the path shape
}
Fully working example: http://jsfiddle.net/PDf9G/5/
Edit: Now simplifies polygon before adding it to the map. Editing the polygon works as well.
First, the css and html: I moved the div called #canvas1 after the map and gave it absolute positioning and z-index = 0. I also gave the map the same absolute positioning to ensure that they always line up with each other, and gave it a z-index of 10.
When the draw button is clicked the canvas is moved to the front. The user can use it to draw free form using d3. When they are done the shape they drew is converted to a google maps polygon.
addShapeToBaseMap: function(divCoords) {
var geoCoords = []
for (var i = 0; i < divCoords.length; i++)
geoCoords.push(overlay.getProjection().fromContainerPixelToLatLng(new google.maps.Point(Number(divCoords[i][0]), Number(divCoords[i][1]))));
poly = new google.maps.Polygon({
paths: geoCoords,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35
});
poly.setMap(map);
Then we do do the hiding/showing of the markers. Using d3 this way is really silly and defeats the purpose. You need to add the google geometry library to your url to use this (&libraries=geometry). I'm sure there are faster ways and if you're dealing with large datasets you'll want to make this better.
for (var i = 0; i < data.length; i++) {
if (!google.maps.geometry.poly.containsLocation(new google.maps.LatLng(data[i]['lat'], data[i]['lng']), poly)) {
d3.select("#" + data[i]['name']).classed({'hide': true});
} else {
d3.select("#" + data[i]['name']).classed({'hide': false});
}
}
This works because when we appended the markers we added their name as the id on the marker element. The only reason I can see to do this is because the svg gives you better control over styling. Last:
svg.select(".selection").remove()
d3.select("#canvas1").classed({'front': false});
$('.draw').removeClass('highlight');
},
We remove the shape we drew from the drawing layer. If we don't do this, if the user moves the map and then turns the drawing layer back on, the shape will be in the wrong place. Then we move the canvas to the back and turn off the highlighting on the drawing button.
The edit function was taken from your most recent code. If the edit button or polygon is clicked the editing function is turned on on the polygon.
I would also recommend taking a look at Leaflet. The integration with d3 is a bit easier and you can have multiple svg layers, which would allow you to put the drawing layer as a map overlay instead of a separate div.
geojson-utils is a node/browser javascript package that has a bunch of utilities for dealing with geojson paths.
One of the many things that it has is a very solid point in polygon algorithm designed for dealing with geojson paths.
You also might want to consider using Leaflet.js instead of Google Maps, it has a few more tools for going to and from geojson based data. It also has a lot of really useful tools already written like Leaflet.draw which has the code already needed to "draw" these paths on top of the maps.
I'm working on a map that uses leaflet and is populated by data from a file in a GeoJson format. My overarching goal is to put graphs into the leaflet popups for each marker on the map.
Getting the markers for each feature and getting the popups to open was fairly easy. However, I am finding it difficult to use D3 to add to the popup.
For the sake of simplicity my goal at the moment is to use D3 to create a svg within each leaflet popup div and draw a square.
I have found some examples where people have used D3 to create graphs inside leaflet popups, but none of them were also using geoJson and the onEachFeature function. This is one of the examples:http://jsfiddle.net/6UJQ4/
Here is the relevant part of my code:
L.geoJson( data, {
style: function (feature) {
return { opacity: 0, fillOpacity: 0.5, fillColor: "#0f0" };
},
onEachFeature: function(feature, layer){
var graph_container = '<div class="popupGraph" id="graph" style="width: 200px; height:200px;"></div>';
layer.bindPopup(feature.properties.name + '<br>' + graph_container);
var svg = d3.select("#graph").selectAll("svg").append("svg").attr("width", 50).attr("height", 200);
var rectangle = svg.append("rect").attr("width", 25).attr("height", 25);
}
}).addTo(map);
I believe I am having issues because D3 can't find the graph_container div however I am a little stumped on how to fix this.
If anyone has any experience using D3, Leaflet, and geoJson together and could explain to me how to get my square to show in the popups or if anyone knows of a source that could help me. I would appreciate it a lot.
Thanks in advance!
UPDATE: Bits has solved my problem! If anyone needs a working example of using D3 in Leaflet popups in combination with GeoJson, Bits posted it in the comments but I will post it here aswell: http://jsfiddle.net/2XfVc/132/
Its quite simple, you just need to add and svg element inside of your div. And start coding d3.
Give me a moment, I am updating your fiddle.
Update: Here you go http://jsfiddle.net/6UJQ4/6/
I took the liberty of simplifying/stripping your example to lowest common denominator to reduce confusion.
Update: http://jsfiddle.net/6UJQ4/7/
In the previous fiddle, you will come across issues where all your markers will be selected everytime giving undesired results. So use last update.