Using D3 outside of Observable

Hi,

I have been using d3 to create data visualizations for my research and i love it! I was quite happy when Observablehq came out, lots of examples, but its workings doesn’t suit me for a few reasons:

  • the data i use is not only quite heavy but also “private”, so I cannot publish the whole dataset publicly --> that means I can’t have public notebooks for my visualizations
  • I am creating an atlas and I need to host my visualizations (they are to interact with one another)
    So in the end, I really need to use d3 in the classic “html, css, js” trio.

However, I find it very hard to “translate” from Observable notebooks to my local code. The notebook system is so different, with the cells etc, that,though I keep trying, I can’t quite understand how to tweak it into working locally. Also, I can’t figure out how to use some this for example:


Is there a way for me to: " import {legend} from “@d3/color-legend” " ?
I have tried downloading the code, I find it hard to read and not very convenient to try and incorporate into my personal code.

Is there any way this could become easier for those of us who would like to keep using d3 outside of observable? Maybe more documentation, or a perhaps an intro to the differences between notebooks and “traditional” code (not sure what to call it) so that we can better switch from one to the other?

Thank you very much,
Lena

1 Like

Even if you could ‘import’ the code to your local application, it has syntax specific to Observable; like the ‘DOM’ method.

So it’s best to cut-and-paste into your code.

Here’s an example with Mike’s legend: https://codepen.io/ubermario/pen/MWKpyJd?editors=1100

This is another design pattern, but it’s dependent on the Observable notebook architecture: https://observablehq.com/@observablehq/downloading-and-embedding-notebooks

1 Like

I’ve put together an example that will import d3 and require from the mentioned notebook and render the first example:

<script type="module">
  import {Runtime} from "https://cdn.jsdelivr.net/npm/@observablehq/runtime@4/dist/runtime.js";
 
  // Basic loader example. Doesn't support aliasing/redefining.
  async function load(slug, names) { 
    const url = `https://api.observablehq.com/${slug}.js?v=3`;
    const module = (new Runtime).module((await import(url)).default);
    const values = names.map(n => module.value(n).then(v => [n, v]));
    return Object.fromEntries(await Promise.all(values)); 
  }
  
  // Wrap in a function (an "IEFE") so we can use await and avoid .then()
  (async function run() {
    // Load d3 and legend from the notebook.
    const {d3, legend} = await load('@d3/color-legend', ['d3', 'legend']);

    const myLegend = legend({
      color: d3.scaleSequential([0, 100], d3.interpolateViridis),
      title: "Temperature (°F)"
    });

    document.body.appendChild(myLegend);
    
  }());
</script>

You can drop the code into a Codepen or .html file to play with it.

2 Likes