8

I was able to display a marker for each part of geography for the USA data (using US data as an example since can't display the work data results) using below:

import dload
from shapely.geometry import shape
import geopandas as gpd
import pandas as pd
import folium

json_string = 'https://raw.githubusercontent.com/datasets/geo-admin1-us/master/data/admin1-us.geojson'

j = dload.json(json_string)

gdf_usa = gpd.GeoDataFrame.from_features(j["features"])
gdf_usa.head()

gdf_usa_new = gpd.GeoDataFrame(gdf_usa, crs="EPSG:4326", geometry='geometry')

usa_map = gdf_usa_new.explore(tiles='CartoDB  positron')
usa_map

gdf_usa_new["long"] = gdf_usa_new.to_crs(epsg='4326').centroid.map(lambda p: p.x)
gdf_usa_new["lat"] = gdf_usa_new.to_crs(epsg='4326').centroid.map(lambda p: p.y)

for i in range(0,len(gdf_usa_new)):
    folium.Marker(
      location=[gdf_usa_new.iloc[i]['lat'], gdf_usa_new.iloc[i]['long']],
      popup=gdf_usa_new.iloc[i]['name'],
      icon=folium.DivIcon(html=f"""<div style="font-family: courier new; color: white">{gdf_usa_new.iloc[i]['name']}</div>""")
   ).add_to(usa_map)

usa_map

Given the above, I get the result below. As can be seen, the markers are too close to each other and thus overlap in the Eastern part of the USA.

enter image description here

When I zoom in, the markers appear to be clearer and thus don't overlap.

enter image description here

Therefore, how can I modify the code so that the markers appear as I zoom in into the map? Therefore, when map is zoomed out, only certain markers appear and when I zoom in the rest appear.

I tried to follow the answer below, but have hard time understanding where to include the suggested answer in the above code:

https://gis.stackexchange.com/questions/216558/leaflet-resize-markers-in-layer-when-zoom-in

Update, I have added the code from the above link (see below) but the results of the map still stay the same.

usa_map.get_root().html.add_child(folium.Element("""
var ar_icon_1 = ...;
var ar_icon_2 = ...;
var ar_icon_1_double_size = ...;
var ar_icon_2_double_size = ...;


map.on('zoomend', function() {
    var currentZoom = map.getZoom();
    if (currentZoom > 5) {
        all_testptLayer.eachLayer(function(layer) {
            if (layer.feature.properties.num < 0.5)
                return layer.setIcon(ar_icon_1);
            else if (feature.properties.num < 1.0)
                return layer.setIcon(ar_icon_2);
        });
    } else {
        all_testptLayer.eachLayer(function(layer) {
            if (layer.feature.properties.num < 0.5)
                return layer.setIcon(ar_icon_1_double_size);
            else if (feature.properties.num < 1.0)
                return layer.setIcon(ar_icon_2_double_size);
        });
    }
});
""")).add_to(usa_map)

Thanks

EDIT: I know that certain tiles display the state names for the USA. However, for my line of work, I am working with the Electoral Districts of Ontario. The tiles do not display them. Therefore, I am using the for loop above to display the Electoral District names for each Electoral District in Ontario.

Isaac A
  • 543
  • 1
  • 6
  • 18
  • Hi there! can you try to build a [mre] that we can use to understand your code? many objects in your code are undefined. also, just a tip, you should never use reserved keywords, including built in functions such as `map`, as variable names. This can lead to unexpected behavior, as `map` is an important operator in python. – Michael Delgado Jun 06 '22 at 22:53
  • Hello, thank you for the response. Updated as instructed. – Isaac A Jun 06 '22 at 23:00
  • So, the idea is the following. For the sake of simplicity, lets' say ont_dataset contains the postal_code column. I was able to plot the map of ontario and highlight each postal code and marker displaying the postal code name. The issue is that the markers are way too crowded and thus overlap thus hiding the map. I would like to be able to zoom into the map and then display some of the markers so that the map itself looks clearer and not crowded. Thanks. – Isaac A Jun 06 '22 at 23:09
  • 1
    yep! that totally makes sense. it would be helpful if you could share the code that creates the original map, plus a sample dataset that creates markers. it doesn't need to be your data - you could generate points randomly or something. but being able to start from what you're working with is really helpful for us and makes it more likely we're going to be able to jump in and solve the issue :) – Michael Delgado Jun 06 '22 at 23:38
  • Hello Michael, thank you for the response. I am currently at home and will be able to further expand the post tomorrow. Please bear with me. – Isaac A Jun 07 '22 at 00:13
  • No rush on my end :) I’m just trying to give you tips that will help you get a good answer. – Michael Delgado Jun 07 '22 at 00:30
  • Hello Michael, I have updated the code using the dummy using the USA geometry data. It is quite analogous to what I am doing at work. – Isaac A Jun 07 '22 at 16:43
  • Have you tried https://github.com/MazeMap/Leaflet.LayerGroup.Collision? – ghybs Jun 08 '22 at 03:17
  • The provided github lib seems to cover exactly what I want. How would I add the code from the github link to my code though? Like, where? – Isaac A Jun 08 '22 at 03:58
  • There is not much I can advise you on, but you need to add the class name in `folium.DivIcon()`. Next would be a javascript that sets the icon size by zoom factor in the link. The code described is javascript, so you will need a script tag. This is as far as I can help you with. Here is [the page](https://nagasudhir.blogspot.com/2021/08/draw-text-on-python-folium-maps-using.html) that this comment is based on. – r-beginners Jun 08 '22 at 04:29
  • I have deleted my response as it is not the result you are looking for. I am not a javascript expert and could not help. – r-beginners Jun 08 '22 at 08:48

1 Answers1

0

Alright, since none of you know, here is what you do.

  1. Open the HTML file of the map in Notepad++.
  2. For the area of interest, find map_... and u003e... where ... is the State Name or the Electoral District ID. E.g. u003eArizona.
  3. Take note of the marker_... and div_icon_...
  4. Right before the at the bottom of the notepad, insert the following for each of the area of interest:
        var myIcon = L.divIcon({className: 'my-div-icon'});

            map_....on('zoomend', function() {  
            var currZoom = map_....getZoom();
            prevZoom = currZoom;                     
                    if (map_....getZoom() <9){                      
            marker_....setIcon(myIcon);
                    }
                    else {                        
            marker_....setIcon(div_icon_...);

                    }
                }
            );
  1. Save
  2. Refresh the opened HTML file or open the HTML file. 6.5 Note, if you are going to run python code and create a new map every time, then the above values need also be updated in the code.
  3. Profit.
Isaac A
  • 543
  • 1
  • 6
  • 18