Flourish legend component
Introduction
The legend component adds legends to a Flourish template. There are currently three types:
- discrete (color) (displays as a series of swatches)
- continuous (color) (displays as a color band)
- continuous (size) (displays as a small and large circle)
Multiple instances of a legend may be added to a template.
The legends are added to a main legend container. The legend container controls generic styling such as font size, aligment and orientation.
Installation and initialization
Install using
npm install --save @flourish/legend
Then initialize the legends like this in the template (make sure this is executed before draw()
is called):
import { createLegendContainer, createDiscreteColorLegend, createContinuousColorLegend, createContinuousSizeLegend } from "@flourish/legend";
const legend_container = createLegendContainer(state.legend_container);
const legend_categorical = createDiscreteColorLegend(state.legend_categorical);
const legend_continuous = createContinuousColorLegend(state.legend_continuous);
const legend_size = createContinuousSizeLegend(state.legend_size);
legend_container
.appendTo(layout.getSection("legend"))
.add([
legend_categorical,
legend_continuous,
legend_size
]);
Then update the legends like this:
legend_container.update()
Add legend settings to template
In your template.yml, first add settings for the legend container:
- property: legend_container
import: "@flourish/legend/container"
And add the legend container settings to the state:
state: {
"legend_container": {}
}
Add settings for specific legends
Discrete color legend
- property: legend_categorical
import: "@flourish/legend/discrete-color"
state: {
"legend_categorical": {}
}
Continuous color legend
- property: legend_continuous
import: "@flourish/legend/continuous-color"
state: {
"legend_continuous": {}
}
Continuous size legend
- property: legend_size
import: "@flourish/legend/continuous-size"
state: {
"legend_size": {}
}
Legend container
Setting up the legend container
The legend container is used to set generic styles (including settings) that apply to all the legend instances inside the container, such as font size, alignment. The legend container has 3 methods:
.add([legend_instances])
- takes an (array of) legend instances that will be appended to the legend container.appendTo(target_element)
- takes a target node element and will append the container to target element.update()
- updates the legend container and all the containing legends
Using the legend without a legend container
The legend container is completely optional. So if you are working in a template and want to control the container and generic sizes in a different way, you can skip the legend container, and use the appendTo()
and update()
function of each individual legend instance.
Discrete / Categorical (color) legend
Add legend items to the legend and customise it
legend_categorical
.data(array, color_function(optional))
.filtered(["Brazil"])
.on("click", function(d) {
console.log(this, d, i);
});
Adding data to the legend
You need to pass the data method an array of strings as its first argument. This will be a list of all the labels for the legend items. The second argument is the color scale.
const getColor = initializeColors(state.color).getColor
const legend_items = ["Brazil", "Argentina"]
legend_categorical.data(legend_items, getColor)
Alternative way of giving data to the categorical legend.
Alternatively you can do it in a more manual way where you create an array of objects that has a label and a color property. The label will be the label displayed for that legend item, and the color will be the color of the swatch.
const legend_items = [
{
label: "Brazil",
color: "#ff0000"
},
{
label: "Argentina",
color: "#000000"
}
]
legend_categorical.data(legend_items);
Continuous (color) legend
legend_continuous
.data(domain, colorScale)
.markerValue(500);
domain
is a 2-element array (e.g. [0, 1000]
) that specifies the values at the lower and upper end of the color scale. color_scale
is a color scale function (e.g. from the colors component). The markerValue
method adds a black and white marker centred on its argument's value. Pass in a value of null
to remove.
Continuous (size) legend
legend_size
.scale(sizeScale);
size_scale
is a scale function that maps the domain to a size. For example, if the legend is representing circle size, this would typically be a D3 scaleSqrt
.
It's assumed that the domain and range minima (e.g. size_scale.domain()[0]
) are zero to keep things simple and because this is good practice. (It's the equivalent of starting bar charts at zero.)
If size_scale
depends on the container size (which in turn depends on the size of the legend) then .update()
will need to be called twice. The first call to set the height of the legend and the second call to update the legend content.
For example:
legend_size
.visible(true)
.update();
legend_size
.scale(sizeScale)
.update();
Additional methods/options
legend.getContainer()
Gets the legend node element
legend.visible(true|false)
Sets the visibility of the legend.
legend.format(formatFunction)
Adds a formatter function to format the labels
legend.autoTitle(string)
Sets the automatic title for the legend. This could be a column name for example.
Multiple legend instances
A typical implementation of multiple legends might look something like:
template.yml
- Discrete color legend
- property: legend_categorical
import: "@flourish/legend/discrete-color"
- Continuous color legend
- property: legend_continuous
import: "@flourish/legend/continuous-color"
state.js
legend_categorical: {
title_mode: "custom"
},
legend_continuous: {
title_mode: "custom"
}
legend.js
const discrete_color_legend, continuous_color_legend;
function initLegends() {
discrete_color_legend = createDiscreteColorLegend(state.legend_categorical);
continuous_color_legend = createContinuousColorLegend(state.legend_continuous);
const legend_container = layout.getSection("legend");
discrete_color_legend.appendTo(legend_container);
continuous_color_legend.appendTo(legend_container);
}
function updateLegends() {
discrete_color_legend
.data(...)
.update();
continuous_color_legend
.data(...)
.update();
}
If a legend needs to change type, add a legend for each type and use .visible()
to hide/show such that one is showing at a time.