🏠 back to Observable

Remove/re-add element based on data

I have a number of lines drawn with D3.js on a Leaflet map representing pipes. What’s the best way of making some of them show/disappear based on zoom level and pipe diameter? I have tried going through documentation and examples using enter() and exit() but wasn’t successful—I’m using map.getZoom() to get the zoom.

Here is how I’m drawing the lines:

const lines_bound = g.selectAll('path').data(data.features).join('path')
// draPipeSelection is a somewhat long function draw the paths (.attr("p", pathCreator)) and formats the lines.
drawPipeSelection(lines_bound)

Here’s how I’m redrawing them when I zoom and pan (I know, it’s pretty stupid to draw elements just to remove them right then):

// criteria do whether or not pipe is to be shown
let diameter = 'diameter';
        // Function to place svg based on zoom
        function isDistributionMain(d) {
            return d.properties[diameter] >= 12;
        }

        function onZoom() {
            console.log(map.map.getZoom());
            let isZommed = map.map.getZoom() >= 15;
            lines_bound.data(data.features.filter(d => isDistributionMain(d) || isZommed))
                .join(
                    enter => drawPipeSelection(enter),
                    update => drawPipeSelection(update),
                    exit => exit.remove()
                )
        }

// initialize positioning
onZoom();

// // reset whenever map is moved
map.map.on('zoomend', onZoom);
map.map.on('moveend', onZoom);

[EDIT] Is this an appropriate place to ask questions about D3.js?

1 Like

Hi @bernardoct, and welcome to the community!

Absolutely this is the right place!

Regrettably I am not a D3.js expert by any means. Since your question has been up for a day or so, however, I figured I’d bump the topic and also ask whether the behavior you want can be achieved using Leaflet zoom levels, as demonstrated in this gis.stackexchange discussion.

This is clearly not a d3.js approach and also not one that would differentiate between the size of any pipes, but it does allow you some fine grained control of when elements appear.

Does this help at all?

Hi @aaronkyle, thanks for looking into this and for suggesting the GIS link. Unfortunately I’m not using Leaflet layers and am instead using D3.js to plot the lines on the map because of the extra flexibility (tell me if my evaluation is mistaken), so the recommendation in the link doesn’t apply to me.

I have modified my code a bit and got a better idea of what the error is, but I can’t edit my post to reflect that. I’ll instead try to create a notebook with my code and some altered data because mine is confidential.

Thanks again!

Hi @bernardoct,

Could you share your notebook, or an abstraction of your notebook built on public and non-controversial information? I can sometimes help even where not an expert, but code snippets are a bit abstract to me.

Also: Apologies, since you will likely find I post code snippets in my help requests. :man_shrugging:

Bumping this again b/c I am also interested to learn more about using D3.js to control maps.
@bernardoct - Did you manage to solve your problem? Again, apologies that I am not much of a help. In case you haven’t seen them, here is a result from the Internet that may be insightful:

https://github.com/Asymmetrik/leaflet-d3/issues/54 (last post there’s a similar problem w/ answer)

Thanks, @aaronkyle. The GitHub link actually provides a really good solution for me to try that I hadn’t thought about before, namely adding a separate layer on Leaflet for the stuff I want to hide. Thanks a lot for the suggestion and I’ll try that now.

Still, given I’ll be pulling data in and out the map and charts in other parts of my application soon, it would still be useful for me to figure out why my original idea wasn’t working. I created a notebook, as you suggested, but couldn’t test it because I couldn’t figure out how to get the GeoJSON data there despite my best Googling efforts. Here’s the link to it. Do you know what the problem is why how I’m trying to load the data into Observable?

Thanks and happy new year.

Happy New Year @bernardoct!

Your JSON had some minor syntax errors. Here’s a suggestion to correct for those:

I’ll read over your notebook in the morning and see if I can understand your problem a bit better. I have a feeling you know more than me though… :wink:

@aaronkyle, thanks again for giving my issue attention. I finally got the map to show with the error I’m having. I also fixed the title, so here’s the new link. https://observablehq.com/@bernardoct/leaftlet-d3-js-map-zoom--and-data-dependent-map-display