Visualizations in Chartreuse are built from small components. The most important components are:
- Layouts, which define a way to layout data. For example, a layout can be a line or curve, or a scatterplot.
- Layers, which associate a layout with data, and metadata like a name and a scale.
- Plots, which consist of one or more layers, and metadata like axes and title.
So creating a plot consists of creating each of the above components and combining them together. There are some shortcuts that simplify common cases.
Here's an example, taken from the Quick Start. We start with some data, which is always needed for a visualization.
import doodle.core.Point import scala.util.Random val data = List.fill(100)(Point(Random.nextGaussian(), Random.nextGaussian()))
Now we create a
Layout, the first component described above.
import chartreuse.* import chartreuse.layout.Scatter val layout = Scatter.default[Point]
The next component is a
Layer, which associates the layout and the data.
The easiest way to create a
Layer is with the
toLayer method on
val layer = layout.toLayer(data)
If we want to set metadata we call methods on
Layer, such as
withLabel to give a name to this layer, or
withScale to use a scale different to the normal linear scale.
Now we can create a
Plot. We can convert a
Layer to a
Plot using the
val plot = layer.toPlot
Builders and Constructors
Builder methods are any method starting with
with, such as
for, such as
These methods are used to set metadata.
A method beginning with
with will accept a new value for metadata.
withLabel will allow you to change the label of a
Layer by passing it the new label.
The example below shows the effect of changing the label of the
Layer we created above.
layer.label // res0: String = "Layer Label" layer.withLabel("The New Label").label // res1: String = "The New Label"
A method beginning with
for accepts a function that is passed the current value of the metdata, and returns the updated value.
This allows you to update just the values of interest within a nested object.
The example below shows how we can modify just the
strokeColor of a
Layout's themeable values using
import doodle.core.Color layout .forThemeable(themeable => themeable.withStrokeColor(Themeable.Override(Some(Color.chartreuse))))
Builder methods always return a modified copy of the object they're called on, so it's always safe to call a builder method even if you used a component in another place. This is a core part of Chartreuse's design philosophy, as described in Core Concepts
In the example above we used
toPlot to convert types. These are convenience methods.
You can, for example, construct a
Plot by calling its constructor but it's much simpler to type
. and follow the auto-complete to turn a
Layer into a
Most types have other convenience constructors on their companion object.
For example, you usually don't construct a
Scatter layout by calling it's constructor.
Instead you call the
Scatter.default convenience constructor, and then perhaps change the few metadata settings using the builder methods.