Skip to main content
Both Shape and Scene components support transformation properties that control positioning, rotation, and scaling.

Transform Props

All transform props are optional and have sensible defaults. See the type definitions in the source code for the complete definition.
x
number
default:"0"
X-axis translation in pixels. Moves the element horizontally.
y
number
default:"0"
Y-axis translation in pixels. Moves the element vertically.
rotation
number
default:"0"
Rotation angle in degrees. Positive values rotate clockwise.
scaleX
number
default:"1"
Horizontal scale factor. Values > 1 enlarge, values < 1 shrink.
scaleY
number
default:"1"
Vertical scale factor. Values > 1 enlarge, values < 1 shrink.

Translation (Position)

Use x and y props to position elements:
import { SwCanvas, Shape, Rect } from '@thorvg/react-fiber';

function App() {
  return (
    <SwCanvas width={400} height={300}>
      <Shape fill={[255, 100, 100, 255]} x={50} y={50}>
        <Rect x={0} y={0} width={100} height={100} />
      </Shape>
      
      <Shape fill={[100, 100, 255, 255]} x={200} y={150}>
        <Rect x={0} y={0} width={100} height={100} />
      </Shape>
    </SwCanvas>
  );
}
The x and y props on Shape are separate from the x and y props on geometry children like Rect. The Shape transform moves the entire shape, while geometry coordinates are relative to the shape’s origin.

Rotation

Rotate elements using the rotation prop (in degrees):
<Shape 
  fill={[200, 100, 255, 255]} 
  x={150} 
  y={150}
  rotation={45}
>
  <Rect x={-50} y={-50} width={100} height={100} />
</Shape>
Rotation is applied around the element’s origin (0, 0). To rotate around the center of a rectangle, position it with negative offsets equal to half its dimensions.

Rotation Example: Spinning Square

import { useState, useEffect } from 'react';
import { SwCanvas, Shape, Rect } from '@thorvg/react-fiber';

function SpinningSquare() {
  const [rotation, setRotation] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setRotation(r => (r + 2) % 360);
    }, 16); // ~60fps

    return () => clearInterval(interval);
  }, []);

  return (
    <SwCanvas width={400} height={300}>
      <Shape 
        fill={[100, 200, 255, 255]}
        x={200}
        y={150}
        rotation={rotation}
      >
        {/* Center the rect on the rotation point */}
        <Rect x={-50} y={-50} width={100} height={100} />
      </Shape>
    </SwCanvas>
  );
}

Scaling

Scale elements using scaleX and scaleY:
<Shape 
  fill={[100, 255, 100, 255]}
  x={100}
  y={100}
  scaleX={1.5}
  scaleY={0.8}
>
  <Circle x={0} y={0} radius={50} />
</Shape>

Uniform Scaling

Use the same value for both scaleX and scaleY to scale proportionally.
scaleX={2} scaleY={2}

Non-uniform Scaling

Use different values to stretch or squash in one direction.
scaleX={2} scaleY={1}

Transform Order

Transforms are applied in a specific order: Scale → Rotate → Translate. This is implemented in the matrix utility in the source code:
// Order: Scale -> Rotate -> Translate
// Matrix multiplication: T * R * S
1

Scale

The element is first scaled by scaleX and scaleY.
2

Rotate

Then rotated by rotation degrees around the origin.
3

Translate

Finally moved to position (x, y).

Combining Transforms

You can combine all transform properties:
<Shape 
  fill={[255, 150, 50, 255]}
  x={200}
  y={150}
  rotation={30}
  scaleX={1.2}
  scaleY={0.8}
>
  <Rect x={-50} y={-25} width={100} height={50} rx={5} ry={5} />
</Shape>

Transforms on Scenes

Scene components support the same transform props and apply them to all children:
import { SwCanvas, Scene, Shape, Rect, Circle } from '@thorvg/react-fiber';

function App() {
  return (
    <SwCanvas width={600} height={400}>
      <Scene x={100} y={100} rotation={15} scaleX={1.5} scaleY={1.5}>
        <Shape fill={[255, 100, 100, 255]}>
          <Rect x={0} y={0} width={50} height={50} />
        </Shape>
        <Shape fill={[100, 100, 255, 255]}>
          <Circle x={75} y={25} radius={25} />
        </Shape>
      </Scene>
    </SwCanvas>
  );
}
Transforms on a Scene apply to all its children. Each child can also have its own transforms, which are combined with the parent’s.

Nested Transforms

Transforms accumulate when nesting Scene components:
<Scene x={100} y={100} rotation={45}>
  <Scene x={50} y={0} scaleX={2}>
    <Shape fill={[200, 100, 200, 255]}>
      <Rect x={0} y={0} width={30} height={30} />
    </Shape>
  </Scene>
</Scene>
In this example:
  1. The inner Scene is positioned at (50, 0) relative to the outer Scene
  2. The inner Scene is scaled 2x
  3. The outer Scene rotates both scenes by 45 degrees
  4. The outer Scene moves everything to (100, 100)

Interactive Example: Draggable Shape

import { useState } from 'react';
import { SwCanvas, Shape, Circle } from '@thorvg/react-fiber';

function DraggableCircle() {
  const [position, setPosition] = useState({ x: 200, y: 150 });
  const [isDragging, setIsDragging] = useState(false);

  const handleMouseDown = () => setIsDragging(true);
  const handleMouseUp = () => setIsDragging(false);
  
  const handleMouseMove = (e: React.MouseEvent<HTMLCanvasElement>) => {
    if (!isDragging) return;
    
    const rect = e.currentTarget.getBoundingClientRect();
    setPosition({
      x: e.clientX - rect.left,
      y: e.clientY - rect.top
    });
  };

  return (
    <div
      onMouseDown={handleMouseDown}
      onMouseUp={handleMouseUp}
      onMouseMove={handleMouseMove}
    >
      <SwCanvas width={400} height={300}>
        <Shape 
          fill={[100, 200, 255, 255]}
          x={position.x}
          y={position.y}
        >
          <Circle x={0} y={0} radius={30} />
        </Shape>
      </SwCanvas>
    </div>
  );
}

Common Patterns

To center a rectangle, offset its geometry by half its dimensions:
<Shape x={200} y={150} fill={[255,100,100,255]}>
  <Rect x={-50} y={-50} width={100} height={100} />
</Shape>
Position geometry so (0,0) is at the desired rotation point:
<Shape x={200} y={150} rotation={45} fill={[100,255,100,255]}>
  <Rect x={-60} y={-40} width={120} height={80} />
</Shape>
Use negative scale:
<Shape scaleX={-1} x={200} y={100} fill={[100,100,255,255]}>
  <Circle x={0} y={0} radius={40} />
</Shape>
Use a Scene to transform multiple shapes as one unit:
<Scene x={150} y={100} rotation={30}>
  <Shape fill={[255,0,0,255]}>
    <Rect x={0} y={0} width={50} height={50} />
  </Shape>
  <Shape fill={[0,255,0,255]}>
    <Circle x={60} y={25} radius={25} />
  </Shape>
</Scene>
Remember that geometry coordinates (like x and y on Rect) are separate from transform props on Shape. Geometry coordinates define the shape itself, while transform props position and manipulate the entire shape.

Build docs developers (and LLMs) love