d3js: waiting before rendering

Hello to all. Is there a simple way to wait for the svg rendering generated by d3 to be ready? For example, to load some big geometries. I didn’t find any notebooks on this…

Interesting question! Assuming you’re talking about SVGs, one way to do it would be to create the DOM iteratively via requestAnimationFrame.

Do you have a concrete example that we can tweak?

This notebook of example. But this applies to all the maps I make with d3js. France Divided Equally in Terms of Population / neocarto / Observable

In your mind, how would an ideal solution behave?

In my mind, I would like a minimal example code to understand it. Display a light svg content until the heavy svg content is ready.

In this specific case, the simplest thing would be to change

communes = FileAttachment("communes.csv").csv({ typed: true })

to

communes = {
  yield [];
  yield await FileAttachment("communes.csv").csv({ typed: true })
}

Another thing to try is to rearchitect your data processing to functions that can act on individual items. Then, instead of always handling each stage for the entire dataset, you can process a smaller number of items as batches, and yield intermediate results (or otherwise give the browser a chance to update).

Speaking of updates: Right now every change to “Cut by” causes the entire map to rerender, which is costly. The only things that change are the fills and the title, so we can use more efficient means to listen to updates, namely via Generators.input().

Furthermore I’d recommend to always put shared attributes onto the group instead of the individual elements.

I’ve incorporated some of my suggestions here:
https://observablehq.com/compare/cca809d7ef81fd63...5418fe7328a12c91

1 Like

By the way, it’s really great to see a notebook with multiple translations! To make that effort more sustainable for you, you might want to look into gettext based solutions that let you manage placeholders more easily, or even let you add the translations as .po files (e.g. maybe gettext.js).

1 Like

Thank you for your help. If I understand correctly what you have done, the svg is drawn as the data is loaded. But is it possible to wait until the svg is ready before displaying it and have a loading image in the meantime? Not example here : Test / neocarto / Observable

Really depends on your data pipeline.

In this case e.g. you could check if you have any data available at the start of your cell:

{
  if(!LAU2?.features) return 'nope';
  // [...]
}

Note that you’ll also want to maintain the data type. So instead of

  yield [];

you’d write

  yield {features: []};

or, if your pipeline can handle undefined,

  yield;

If the server supports range requests, you may also want to look into streaming your geojson instead of loading it all at once. You don’t have to render every chunk while it arrives, but streaming will allow you to display a progress bar, e.g. like it’s been done here: