Layout
Vex came from a layout engine. A layout has boxes, and each rule of a layout relates a box to other boxes: “this box starts where that box ends”, “these boxes do not overlap”.
Push the boxes apart
Section titled “Push the boxes apart”The program below gives each box a push. It reads the centre of the box at the origin. For each other box that it overlaps, it reads the direction from that centre to its centre. The reduction adds the directions.
Drag a box onto another box: red arrows show the pushes. Select “Relax” to move each box along its push until no boxes overlap.
| A | push (-0.7592566023652966, -0.6507913734559685) |
|---|---|
| B | push (0.7592566023652966, 0.6507913734559685) |
| C | no overlap, no push |
| D | no overlap, no push |
const centre = root.from("size")._.halve()._.add("position");
const push = centre
.others(
(e) => e._.subtract(e.from("size")._.halve()._.add("position"))._.normalize(),
{ where: overlaps },
)
.reduce("add");The test of the where option reads both boxes: origin() reads at the origin, and a bare field name reads at the target. The old Vex could not express this, because its focus was one mutable value.
Overlap, step by step
Section titled “Overlap, step by step”root.from("position")._.add("size")
.others((e) =>
e._.subtract("position")._.allPositive()._.and(
e.from("position")._.add("size")._.subtract(e.origin().from("position"))._.allPositive()))
.any()step 27 of 27
Result at A: true
| origin | A | B | C | D |
|---|---|---|---|---|
| result | true | true | false | false |