Transform and Matrix4

Transform controls where a layer is placed, how it rotates and scales, and which local point acts as its pivot. Every layer has a required transform object, and the same model works for flat 2D motion and 3D motion.

The transform model

{
  "frame": { "width": 480, "height": 270 },
  "transform": {
    "translate": { "x": 320, "y": 180, "z": 0 },
    "rotate": { "x": 0, "y": 0, "z": 8 },
    "scale": { "x": 1, "y": 1, "z": 1 },
    "anchor": { "x": 240, "y": 135, "z": 0 },
    "skew": { "x": 0, "y": 0 }
  }
}
FieldMeaningTypical default
translatePosition in the parent/world coordinate system{ x: 0, y: 0, z: 0 }
rotateRotation around X, Y and Z axes, in degrees{ x: 0, y: 0, z: 0 }
scaleScale along X, Y and Z axes{ x: 1, y: 1, z: 1 }
anchorLocal pivot point used by rotation and scale{ x: 0, y: 0, z: 0 }
skew2D shear angles for X and Y{ x: 0, y: 0 }

All values must be finite numbers. The transform does not change the layer frame itself; it changes how that frame is placed and projected.

Frame versus transform

The frame is local geometry. The transform is placement:

frame:     480 × 270 local rectangle
anchor:    (240, 135) center of that rectangle
translate: (320, 180) position in the parent/world space
rotate.z:  8 degrees around the anchor
scale:     (1, 1, 1) unchanged size

Changing frame.width or frame.height changes the layer's local geometry. Changing translate, rotate, scale or anchor keeps the geometry but changes its placement or appearance.

Translate

translate moves the layer in its parent coordinate system. X and Y use composition/world units. Z is used when the composition view or a parent group uses depth.

"translate": { "x": 320, "y": 180, "z": 0 }

For a child layer, the translation is evaluated relative to its parent group. For a root layer, it is evaluated relative to the composition world.

Scale

scale multiplies the local geometry around the anchor:

  • 1 leaves an axis unchanged.
  • A value between 0 and 1 shrinks that axis.
  • A value greater than 1 enlarges that axis.
  • A negative value mirrors the layer across that axis.
  • 0 collapses an axis and should be used deliberately.
"scale": { "x": 1.2, "y": 0.8, "z": 1 }

Rotation

Rotation values are degrees. Z rotation is the usual flat 2D rotation; X and Y rotation are useful with perspective projection or 3D layers.

"rotate": { "x": 0, "y": 0, "z": -12 }

Rotation happens around the local anchor. If the anchor is at the top-left, the layer swings around that corner. If the anchor is at the center, it rotates around its center.

Anchor and pivot

anchor.x and anchor.y are local units, not normalized 0–1 percentages. For a 480×270 frame, the center anchor is { x: 240, y: 135, z: 0 }. The pivot may be outside the frame for orbit-style motion.

{
  "frame": { "width": 480, "height": 270 },
  "transform": {
    "translate": { "x": 540, "y": 405, "z": 0 },
    "rotate": { "x": 0, "y": 0, "z": 20 },
    "scale": { "x": 1, "y": 1, "z": 1 },
    "anchor": { "x": 240, "y": 135, "z": 0 },
    "skew": { "x": 0, "y": 0 }
  }
}

To place the frame's center at a world position, use the frame center as the anchor and set translate to that world position. To rotate around a corner, use { x: 0, y: 0, z: 0 }.

Skew

skew.x and skew.y are 2D shear angles in degrees. They are useful for slanted cards, italic-style geometric motion and simple projection accents. Use an ordered operations list when the exact SVG transform sequence matters.

From CSS to Neonix JSON V2

HTML/CSS authors normally start with a CSS transform. The compiler converts the same intent into explicit JSON fields:

.card {
  width: 480px;
  height: 270px;
  transform: translate(320px, 180px) rotate(8deg) scale(1.1, 0.9);
  transform-origin: 50% 50%;
}
{
  "frame": { "width": 480, "height": 270 },
  "transform": {
    "translate": { "x": 320, "y": 180, "z": 0 },
    "rotate": { "x": 0, "y": 0, "z": 8 },
    "scale": { "x": 1.1, "y": 0.9, "z": 1 },
    "anchor": { "x": 240, "y": 135, "z": 0 },
    "skew": { "x": 0, "y": 0 }
  }
}

transform-origin becomes a local-unit anchor; percentages are resolved against the layer frame. translateX/Y/Z, scaleX/Y/Z, rotateX/Y/Z, skewX/Y and matrix/matrix3d become named fields or ordered operations.

Ordered operations

The component fields above provide the simple layer transform contract. An optional operations array preserves an explicit ordered transform list; its order is semantic and must not be rearranged.

"operations": [
  { "type": "translate", "x": 320, "y": 180 },
  { "type": "rotate", "angle": 8, "center": { "x": 240, "y": 135 } },
  { "type": "scale", "x": 1.1, "y": 1.1 },
  { "type": "skewX", "angle": 4 }
]

Supported 2D operations are translate, scale, rotate, skewX, skewY and six-value SVG matrix. Motion extensions add motion.translate3d, motion.scale3d, motion.rotateX, motion.rotateY, motion.rotateZ, motion.perspective and motion.matrix4.

When operations is present, it is the authored operation sequence. The transform anchor wraps that sequence as a pivot, and the layer translation places the result.

Matrix4

Neonix uses a canonical 4×4 matrix for the final 2D/3D transform. Most authors should use the named fields or ordered operations. Use motion.matrix4 only when importing an already-composed matrix or when a tool needs direct matrix control.

{
  "type": "extension",
  "name": "motion.matrix4",
  "value": [
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    320, 180, 0, 1
  ]
}

Do not mix a pre-composed matrix with equivalent translate, rotate and scale values unless the duplication is intentional. Otherwise the same motion can be applied twice.

Which transform form should I use?

FormUse it whenImportant rule
Named fieldsYou are authoring ordinary 2D or 3D motionEasiest to read and animate with tracks
operationsYou need to preserve the exact CSS/SVG transform orderArray order is semantic
motion.matrix4You import a composed 4×4 matrix from another toolDo not duplicate equivalent named transforms

For animation, target one scalar or vector property such as transform.translate.x, transform.rotate.z, transform.scale.x or transform.anchor.y. Do not animate the whole matrix unless the source tool already owns matrix composition.

Composition order

With the named fields, the conceptual local transform is:

translate → pivot to anchor → rotate → skew → scale → pivot back

The exact matrix is evaluated consistently for preview and export. With operations, the listed operations replace the implicit ordered list; their order is not interchangeable. For example, scale-then-translate does not generally produce the same result as translate-then-scale.

Parent and child layers

A group transform affects its descendants. A child transform is evaluated in the coordinate system established by its parent, then the child is painted according to sibling order. To understand a misplaced layer, inspect the chain from the root composition through each parent group before changing the child values.

See Layers and hierarchy for parent relationships and Composition and view for the global view projection.

Animate a transform

Animation tracks target individual transform properties with dot-separated paths:

{
  "path": "transform.translate.x",
  "keyframes": [
    { "time": 0, "value": { "type": "number", "value": 120 } },
    { "time": 1000, "value": { "type": "number", "value": 520 } }
  ]
}

Other supported paths include transform.translate.y, transform.translate.z, transform.scale.x, transform.rotate.z, transform.skew.x and transform.anchor.x. Track times are milliseconds and each keyframe value must keep the property's type.

Common mistakes

  • Using normalized anchor values such as 0.5 instead of local units such as frame.width / 2.
  • Changing the layer frame when the intent is only to move or rotate the layer.
  • Reordering operations and expecting the same result.
  • Applying both a pre-composed motion.matrix4 and equivalent named transform values.
  • Using X/Y rotation without a perspective view and expecting visible depth scaling.
  • Forgetting that a parent group transform affects every descendant.

For the global camera, read Composition and view. For time-based changes, read Animation and timing.