Plot.text() with facets

Notebook here:

https://observablehq.com/d/149c10e66e8189b4

Simple state Plot.geo, works very nice. I want to add some text or annotated but from another data object (text_data) which is different than the main data source.

-Do I need 2 separate plot.text() calls or can I get a ‘\n’ to work somewhere in one line as I want to display 2 lines of text (Year: 2000, Slope: 0.02)
-Obviously if I facet by year, I only want the text to display the filtered year. Is there a ‘currentFacet’ type object I can use to filter down the text_data object?

Thank you; great to be back in d3 :slight_smile:

Because the text uses a different data than the facets, you’ll need to add an explicit fy channel. Also, yes, newlines work fine to make two lines. Combined this looks like

Plot.text(text_data, {
  x: -100,
  y: 45,
  text: (d) => `Year: ${d.year}\nSlope: ${d3.format(".2f")(d.b0)}`,
  dy: 10,
  fy: "year",
  fill: "black",
  stroke: "white"
}),

I also set a combination of black fill and white stroke, which I find improves the readability quite a bit.

I’ve made a fork of your notebook with that change applied: Testing Mapping Work / Michael Cooper | Observable.

Didn’t even know about fy so that was helpful, Thank you.

Maybe a clarification because faceting is now controlled within the plot.text() and the higher level facet: {y: “Year”}. I’ll eventually like to toggle between faceting on/off and would like the text to auto wrap. I thought using dy: (d,i) => -(i+1)*10 would accomplish that, but no. Also adding \n after the last ${} doesn’t help either.

Unfortunately, auto wrapping isn’t available from the browser or Plot. Edit: See mbostock’s post below.

The reason passing a function to dy didn’t work is that dy can only use constants. I’m not sure why that is (Though I’m imagining Fil is going to swoop in with a perfect answer for why sometime later).

Plot supports automatic wrapping using the lineWidth option which was added in the latest release 0.6.4 release 0.4.1. It can also truncate text that is too long using the textOverflow option.

The reason that dy is a constant option—instead of a channel allowing varying values across instances—is partly a practical consideration: it’s a lot easier to implement Plot that way. But more philosophically, Plot channels are intended for visualizing data, and making fine adjustments to layout via dy is more about presentation.

You can workaround this limitation by adding multiple marks with separate values for dy. Feel free to add to the discussion in issue #175 if you are interested in this topic.

2 Likes

So I think I can just write a helper function within marks that will iterate through my text_data objects and return the same number of Plot.Text() calls as there are objects in my text_data

At least I don’t see any obvious reason I can’t do that.