Tutorial Part 2: The Power of Relations
In the last tutorial, we got a brief introduction to Bluefish: its marks, relations, and declarative references. In this tutorial, we'll see just how expressive relations can be. We'll progressively modify the label in the last tutorial until we've gone from this:
import "./styles.css"; document.getElementById("app").innerHTML = ` <h1>Hello world</h1> `;
to this:
import "./styles.css"; document.getElementById("app").innerHTML = ` <h1>Hello world</h1> `;
Along the way we'll encounter some other Bluefish relations: Arrow
, Align
, and Distribute
. We'll also gain some more experience using name
and Ref
.
Flip label direction
One thing we can do without changing our spec very much is move the label below the planet by simply reversing the order of StackV
's children:
// ...
Background({ padding: 40, fill: "#859fc9", stroke: "none" }, [
StackV({ spacing: 30 }, [
Text("Mercury"),
Ref({ select: "mercury" }),
Ref({ select: "mercury" }),
Text("Mercury"),
]),
]);
// ...
2
3
4
5
6
7
8
9
10
Change Background
to Arrow
We can also change how we connect the label to the planet.
First, we'll denest the Background
relation from the StackV
.
// ...
Background({ padding: 40, fill: "#859fc9", stroke: "none" }, [
StackV({ spacing: 30 }, [
Ref({ select: "mercury" }),
Text("Mercury"),
Text({ name: "label" }, "Mercury"),
]),
Background({ padding: 40, fill: "#859fc9", stroke: "none" }, [
Ref({ select: "label" }),
Ref({ select: "mercury" }),
])
// ...
2
3
4
5
6
7
8
9
10
11
12
Notice that this doesn't change our diagram! It just changes our spec so that we can make other kinds of edits.
Now, instead of using a Background
, we can use an Arrow
relation:
// ...
StackV({ spacing: 30 }, [Ref({ select: "mercury" }), Text({ name: "label" }, "Mercury")]),
Background({ padding: 40, fill: "#859fc9", stroke: "none" }, [
Arrow([
Ref({ select: "label" }),
Ref({ select: "mercury" }),
]);
// ...
2
3
4
5
6
7
8
Distribute the label from the planets
Right now the label is inside the planets Background
, but what if we want to place it outside? We could change the StackV
spacing until it's large enough, but we would have to manually update it whenever we changed the Background
or the sizes of the planets. Instead, we'll offset the label from the planets Background
directly.
To do this, we first have to split StackV
into its two constituent parts: vertical Distribute
and horizontal Align
:
StackV({ spacing: 30 },
Distribution({ direction: "vertical", spacing: 30 },
[Ref({ select: "mercury" }), Text({ name: "label"}, "Mercury")]),
Align({ alignment: "centerX" }, [ Ref({ select: "mercury"}), Ref({ select: "label"})])
2
3
4
This refactor doesn't change the diagram at all, but it does let us retarget the Distribute
so we n offset it from the Background
instead of the Mercury Circle
. To do this, we'll first label the planets Background
:
Background({ padding: 40, fill: "#859fc9", stroke: "none" },
Background({ name: "planets", padding: 40, fill: "#859fc9", stroke: "none" },
2
Then we'll change the selection in the Distribute
:
Distribution({ direction: "vertical", spacing: 30 }, [
Ref({ select: "mercury" }),
Ref({ select: "planets" }),
Text({ name: "label" }, "Mercury"),
]);
2
3
4
5
Wrapping up
Huzzah! We modified the label in our planets diagram. Along the way we used Arrow
, Align
, and Distribute
, three important Bluefish relations. We've also gained more experience naming elements and selecting them with Ref
. Your final code should look like this:
import "./styles.css"; document.getElementById("app").innerHTML = ` <h1>Hello world</h1> `;