Layouts
A layout places elements in the box. It gives each element a center, a width, a height and, for an oriented ring, a rotation. All lengths are fractions of the box side, and the box goes from 0 to 1 on both axes, with y pointing down.
Pick a layout kind and change its fields. The numbered boxes are the elements, in index order.
"layout": {"type":"row","count":3,"gap":0.05}| Layout | Fields (default) | Elements |
|---|---|---|
single | size (1), width (size), height (size), x (0.5), y (0.5) | one element centered at (x, y) |
stack | count, and the same fields as single | count elements at the same place |
row | count, gap, itemWidth, itemHeight | a horizontal row, centered vertically |
grid | columns, rows, gap | a grid that fills the box, row by row |
ring | count, itemSize, itemWidth, itemHeight, startAngle (0), orient (false) | elements on a circle, clockwise |
Counts (count, columns, rows) are rounded to the nearest integer and are at least 1. Any number can be a $param.
single
One element. Without fields, it fills the box. Use width and height for a non-square element, and x and y to move its center.
{
"$schema": "https://maitrungduc1410.github.io/loader-kit/schema/v1.json",
"schemaVersion": 1,
"name": "LayoutSingle",
"duration": 1.2,
"layout": { "type": "single", "width": 0.7, "height": 0.35 },
"shape": { "type": "rect", "cornerRadius": 0.3 },
"tracks": [
{ "property": "rotate", "keyTimes": [0, 1], "values": [0, 3.141592654], "easing": "easeInOut" }
]
}LayoutSingleOpen in playground stack
count elements on top of each other, all at the same place. A stack is useful with stagger, so each copy is at a different point of its cycle. This ripple uses negative stagger offsets, so the three circles are already spread through the cycle on the first frame instead of starting together (see Stagger).
{
"$schema": "https://maitrungduc1410.github.io/loader-kit/schema/v1.json",
"schemaVersion": 1,
"name": "LayoutStack",
"duration": 1.5,
"layout": { "type": "stack", "count": 3 },
"shape": { "type": "circle" },
"stagger": [0, -0.5, -1],
"tracks": [
{ "property": "scale", "keyTimes": [0, 1], "values": [0, 1], "easing": "easeOut" },
{ "property": "opacity", "keyTimes": [0, 0.1, 1], "values": [0, 0.8, 0] }
]
}LayoutStackOpen in playground row
count elements side by side, with gap between two elements. The vertical center is always 0.5.
- Without
itemWidth, the elements and gaps fill the width of the box: each element is(1 - gap × (count - 1)) / countwide. - With
itemWidth, the row has that element width and is centered. itemHeightdefaults to the element width, so elements are square. Set it for tall bars.
{
"$schema": "https://maitrungduc1410.github.io/loader-kit/schema/v1.json",
"schemaVersion": 1,
"name": "LayoutRow",
"duration": 1,
"layout": { "type": "row", "count": 5, "gap": 0.08, "itemHeight": 0.7 },
"shape": { "type": "line" },
"stagger": { "each": 0.1 },
"tracks": [
{ "property": "scaleY", "keyTimes": [0, 0.5, 1], "values": [1, 0.35, 1], "easing": "easeInOut" }
]
}LayoutRowOpen in playground grid
columns × rows elements that fill the box, numbered row by row from the top-left. gap is the space between two cells, both across and down.
This example uses a stagger array (one offset per element) to start the wave from the bottom-left corner.
{
"$schema": "https://maitrungduc1410.github.io/loader-kit/schema/v1.json",
"schemaVersion": 1,
"name": "LayoutGrid",
"duration": 1.2,
"layout": { "type": "grid", "columns": 3, "rows": 3, "gap": 0.1 },
"shape": { "type": "rect", "cornerRadius": 0.2 },
"stagger": [0.2, 0.3, 0.4, 0.1, 0.2, 0.3, 0, 0.1, 0.2],
"tracks": [
{ "property": "scale", "keyTimes": [0, 0.35, 0.7, 1], "values": [1, 0, 1, 1], "easing": "easeInOut" }
]
}LayoutGridOpen in playground ring
count elements on a circle, evenly spaced. Element 0 is at startAngle (0 is to the right of the center) and the others follow clockwise. The radius is 0.5 - itemSize / 2, so the outer edge of the elements touches the box.
{
"$schema": "https://maitrungduc1410.github.io/loader-kit/schema/v1.json",
"schemaVersion": 1,
"name": "LayoutRing",
"duration": 1,
"layout": { "type": "ring", "count": 8, "itemSize": 0.2 },
"shape": { "type": "circle" },
"stagger": { "each": 0.125 },
"tracks": [
{ "property": "opacity", "keyTimes": [0, 1], "values": [1, 0.15] },
{ "property": "scale", "keyTimes": [0, 1], "values": [1, 0.5] }
]
}LayoutRingOpen in playground Oriented elements
itemWidth and itemHeight change the element size but not the radius, which still comes from itemSize. With orient: true, each element is rotated so its top points away from the center. Use it with the line shape for a classic spinner.
{
"$schema": "https://maitrungduc1410.github.io/loader-kit/schema/v1.json",
"schemaVersion": 1,
"name": "LayoutRingOrient",
"duration": 1.2,
"layout": { "type": "ring", "count": 12, "itemSize": 0.26, "itemWidth": 0.07, "orient": true },
"shape": { "type": "line" },
"stagger": { "each": 0.1 },
"tracks": [
{ "property": "opacity", "keyTimes": [0, 1], "values": [1, 0.15] }
]
}LayoutRingOrientOpen in playground Element order and colors
Element indices follow the layout order: left to right for a row, row by row for a grid, clockwise from startAngle for a ring. Stagger arrays, durations and the colors setting all use these indices.
Exact formulas
The specification gives the exact formula for each layout.