Transform

Sometimes it can be useful to apply 2D transformations to one or more components collectively. This is where Transform comes in handy.

import { Mafs, Coordinates, Transform, useMovablePoint, Theme, Text, Polygon, Circle, vec } from "mafs"

function SimpleTransformExample() {
  const t = useMovablePoint([-4, -2])
  const s = useMovablePoint([8, 4], { color: Theme.blue })
  const r = useMovablePoint([1, 0], {
    color: Theme.green,
    constrain: (p) => vec.normalize(p),
  })
  const angle = Math.atan2(r.point[1], r.point[0])

  return (
    <Mafs viewBox={{ x: [-8, 8], y: [-3, 3] }}>
      <Coordinates.Cartesian />

      <Transform translate={t.point}>
        <Transform rotate={angle}>
          <Transform scale={s.point}>
            <HelloBox />
          </Transform>

          {s.element}
        </Transform>

        {r.element}
      </Transform>

      {t.element}
    </Mafs>
  )
}

function HelloBox() {
  return (
    <>
      <Polygon points={[[0, 0], [1, 0], [1, 1], [0, 1]]} />
      <Circle center={[0.5, 0.5]} radius={0.5} />
      <Text x={0.5} y={0.5}>
        Hello world!
      </Text>
    </>
  )
}

Props

<Transform ... />
NameDescriptionDefault
matrix
Matrix
β€”
translate
Vector2
β€”
scale
number | Vector2
β€”
rotate
number
β€”
shear
Vector2
β€”

Transformation types

Transform supports many transformation convenience props, but they all boil down to matrix multiplication.

You can pass your own matrix via the matrix prop and it will be combined with any other transformations you define. Use vec.matrixBuilder() to construct such a matrix if needed.

Nesting

Nesting is supported. Transformations will be applied inside out, so the innermost Transform will be applied first.

<Transform translate={[10, 10]}> <Transform rotate={Math.PI / 2}> {/* Things in here will be rotated, _then_ translated */} </Transform> </Transform>

Prop order matters

Though it's not typical for prop order in React to be significant, it is for Transform. Transformations will be applied in the order the props are set on the component, with the exception of matrix which always comes first.

Exceptions

Not all elements support Transform. This may change in the future.

  • Text nodes have their anchor points transformed, but not the text itself.
  • Coordinates.* cannot be transformed.
  • Function.OfX cannot be transformed.
  • VectorField cannot be transformed.