New Generation of Examples

So I’m about to embark on creating a slew of D3 examples for a book project I’m working on, and I’d like to get feedback on the approach. Here’s the first example, a scatter plot.

I’d like to get feedback on:

Imports

import { select } from 'd3-selection';
import { csv } from 'd3-fetch';
import { scaleLinear } from 'd3-scale';
import { extent } from 'd3-array';
import { axisLeft, axisBottom } from 'd3-axis';

This is the way I’m doing imports. I think this is the best format, so it’s clear which packages things are coming from, and it’s compatible with downstream workflows that use popular build tools like Webpack and Rollup. It’s also compatible with import maps. The con of this approach is that it does require use of a build tool or import maps, which adds a bit of up-front complexity to explain.

Naming

I want to establish a naming convention that will make sense for a large family of examples, and I also want to make each example readable as a standalone program without the context of the others. In the history of D3 examples, I sometimes see x being the X value accessor, and sometimes x is the X scale. IMO either way is confusing, so I’m opting for the following conventions:

  • xAccessor - The value accessor. Sometimes called xValue in examples. Opting for xAccessor over xValue because I’ve found that I always refer to it as the “X accessor”, so why not name it that. The con of this is that it’s not an established pattern in the history of D3 examples.
  • xScale - The scale. Opting to use this instead of just x so it is clear that it’s a scale.
  • parseRow - The function that parses a row, the second argument to d3.csv. In the docs this is called row, but I don’t want to use that name because we might want a variable called row that refers to an individual row.

Margin handling

I’m going for now with the .range([margin.left, width - margin.right]) pattern, as opposed to the .range([0, width - margin.right - margin.left]) pattern with the extra translated bymargin.leftandmargin.top`. This is mainly because this is how most of the newer D3 examples handle it.

Thoughts on this structure? Any recommendations for change? Thanks!

3 Likes

Hi Curran,

I like the patterns you are suggesting, but what I think is more helpful is the way you have explained the conventions. I have rarely seen the conventions explained and it took me ages (as a complete noob) to work out what was going on.

In my opinion, if you have spay, it is worth explaining the common conventions (as you have for the margin) to help folk figure out how to adapt other examples.

I am now looking forward to your book. I have found your online tutorials very helpful.

If you’re looking for ideas to put into the book it would be great if you were able to do more advanced reusable charts, with d3 layouts and interactions .on(drag / brush etc. I think this was your intention for the last series - if I understood correctly.

Jim

Hi Jim,

Thank you for the input, this is very useful.

Indeed, the intention was to take the previous series further (Get it Right in Black & White) with more variety in chart types and interaction patterns. I hope to do that for this book project, to really exhaust the design space of interactive visualization.

I might do a new live stream series as well, starting in January or so, to work through the coding of all the various visualization types and interactions. I’m not sure yet, but I’m brainstorming how to structure such a series. Perhaps there could be a paid component, so it can be a sustainable thing (that’s really why the last series fizzled out - it was all donated time, which I love doing but it’s tough to make it sustainable).

Thanks for your post here! I appreciate the input.

1 Like

One other thought is that if you’re doing a set of reusable charts, it would be helpful is you use a set of non-reusable examples. For example, I have a project looking at translating the “D3 Tips and Tricks” into the reusable pattern from ProD3. - there are some examples in my VizHub profile.

I’m not really sure what you mean. Are you saying it would be good to use some sort of reusable pattern from the start? This is what I’m thinking of doing, along the lines of:

import { create } from 'd3-selection';
import { scaleLinear } from 'd3-scale';
import { extent } from 'd3-array';
import { axisLeft, axisBottom } from 'd3-axis';

export const ScatterPlot = ({
  data,
  xAccessor,
  yAccessor,
  radius,
  margin,
  width,
  height,
}) => {
  const svg = create('svg')
    .attr('width', width)
    .attr('height', height);

  const innerWidth = width - margin.right - margin.left;
  const innerHeight = height - margin.top - margin.bottom;

  const xScale = scaleLinear()
    .domain(extent(data, xAccessor))
    .range([0, innerWidth]);

  const yScale = scaleLinear()
    .domain(extent(data, yAccessor))
    .range([innerHeight, 0]);

  const g = svg
    .append('g')
    .attr(
      'transform',
      `translate(${margin.left}, ${margin.top})`
    );

  g.selectAll('circle')
    .data(data)
    .join('circle')
    .attr('cy', (d) => yScale(yAccessor(d)))
    .attr('cx', (d) => xScale(xAccessor(d)))
    .attr('r', radius);

  g.append('g').call(axisLeft(yScale));

  g.append('g')
    .attr('transform', `translate(0,${innerHeight})`)
    .call(axisBottom(xScale));

  return svg.node();
};

What pattern is that? What is “ProD3”? A Google search for ProD3 leads to vitamins. Thanks!

Hi Curran,

Sorry for not being clear.

I was meaning, that for me it would be useful to possibly use one of the existing sets of examples that has a series of different d3 charts e.g.


and show how to develop a set of reusable versions of these using a consistent reusable pattern. So that the student can understand how and what to changes with each different chart layout. And because you are using a series of charts from one author, you don’t have to work out what’s different in the pattern used between the non-reusable chart examples (e.g. when using bl.ocks from different authors your line chart may use different conventions from the pie chart example used as a starting point, for a noob this is more complication to understand and grapple with.

A project of mine is to create the charts of “d3 tips and tricks” into the Pro D3.js pattern (
https://link.springer.com/book/10.1007/978-1-4842-5203-1
(sorry mistyped the name)) . I have a few examples on VizHub e.g.


I am struggling with it and it is taking time to work out certain issues. The dispatching of events took a while and I have not still fully got, as with the update pattern. But I am learning a lot doing this and your courses have been a great help.

Hopefully that makes more sense.

But it is only a suggestion, based on my experience and struggles with d3 and js.

Jim

I would provide a preface or appendix and explain generally observed conventions and then the ones you are using and why. In the end, they are conventions, which means, use them if you like.

Separately I would like to see examples that deal with complexish data sets. Where you have a table of data and would be best creating arrays of objects (possibly multiple arrays) and then using them in selections and joins at different levels of [{},[{},{},{}],{{},[],[{},{},{}]}]. I had and still have a lot of issues on how to build and address arrays of objects (which seem to be a preferred data structure).

In my current project I was scolded by MBostock for using mutable objects, so make sure to address that…

1 Like

Great idea! I totally agree. Rather than just showing the final conclusion, show the desicion making process. Love it!

Thanks for the suggestions re: addressing data transformation and mutable vs. immutable objects.