Skip to main content

Basic Scene

Use the Scene component to group multiple shapes together.
import { SwCanvas, Scene, Shape, Circle, Rect } from 'react-thorvg-fiber';

<SwCanvas width={200} height={200}>
  <Scene>
    <Shape fill={[59, 130, 246, 255]}>
      <Rect x={40} y={40} width={50} height={50} />
    </Shape>
    <Shape fill={[234, 88, 12, 255]}>
      <Circle x={130} y={130} radius={30} />
    </Shape>
  </Scene>
</SwCanvas>
Scenes act as containers for shapes, allowing you to organize and transform groups of elements.

Nested Scenes

Scenes can contain other scenes for hierarchical composition.
import { SwCanvas, Scene, Shape, Circle, Rect } from 'react-thorvg-fiber';

<SwCanvas width={200} height={200}>
  <Scene x={50} y={50}>
    <Shape fill={[59, 130, 246, 255]}>
      <Rect x={0} y={0} width={40} height={40} />
    </Shape>
    <Scene x={20} y={20}>
      <Shape fill={[234, 88, 12, 255]}>
        <Circle x={20} y={20} radius={15} />
      </Shape>
    </Scene>
  </Scene>
</SwCanvas>
The inner scene’s position is relative to its parent scene. The circle appears at (90, 90) in canvas coordinates: 50 (parent x) + 20 (child scene x) + 20 (circle x).

Scene Transforms

Transform entire groups of shapes by transforming the scene.
import { SwCanvas, Scene, Shape, Rect, Circle } from 'react-thorvg-fiber';

<SwCanvas width={200} height={200}>
  <Scene x={60} y={60}>
    <Shape fill={[59, 130, 246, 255]}>
      <Rect x={0} y={0} width={30} height={30} />
    </Shape>
    <Shape fill={[234, 88, 12, 255]}>
      <Circle x={50} y={25} radius={15} />
    </Shape>
  </Scene>
</SwCanvas>
Moves the entire group to (60, 60).

Scene Opacity

Control the opacity of all shapes in a scene at once.
import { SwCanvas, Scene, Shape, Circle, Rect } from 'react-thorvg-fiber';

<SwCanvas width={200} height={200}>
  <Scene opacity={128}>
    <Shape fill={[59, 130, 246, 255]}>
      <Rect x={40} y={40} width={60} height={60} />
    </Shape>
    <Shape fill={[234, 88, 12, 255]}>
      <Circle x={120} y={120} radius={40} />
    </Shape>
  </Scene>
</SwCanvas>
All shapes in the scene become semi-transparent (opacity 128 out of 255).

Multi-Level Nesting

Create complex hierarchies with multiple levels of nesting.
import { SwCanvas, Scene, Shape, Circle, Rect } from 'react-thorvg-fiber';

<SwCanvas width={200} height={200}>
  <Scene x={50} y={50}>
    <Shape fill={[59, 130, 246, 255]}>
      <Rect x={0} y={0} width={60} height={60} />
    </Shape>
    
    <Scene x={30} y={30} rotation={15}>
      <Shape fill={[234, 88, 12, 255]}>
        <Circle x={0} y={0} radius={20} />
      </Shape>
      
      <Scene x={0} y={0} scaleX={0.6} scaleY={0.6}>
        <Shape fill={[34, 197, 94, 255]}>
          <Circle x={0} y={0} radius={15} />
        </Shape>
      </Scene>
    </Scene>
  </Scene>
</SwCanvas>
This creates three levels:
  1. Outer scene translated to (50, 50)
  2. Middle scene translated and rotated
  3. Inner scene scaled down
Transforms accumulate through the hierarchy.

Organized Composition

Use scenes to organize complex drawings logically.
import { SwCanvas, Scene, Shape, Circle, Rect, Path, PathCommand } from 'react-thorvg-fiber';

function ComplexDrawing() {
  return (
    <SwCanvas width={200} height={200}>
      {/* Background layer */}
      <Scene>
        <Shape fill={[226, 232, 240, 255]}>
          <Rect x={0} y={0} width={200} height={200} />
        </Shape>
      </Scene>
      
      {/* Buildings */}
      <Scene x={0} y={100}>
        <Shape fill={[71, 85, 105, 255]}>
          <Rect x={20} y={0} width={40} height={100} />
        </Shape>
        <Shape fill={[51, 65, 85, 255]}>
          <Rect x={80} y={20} width={50} height={80} />
        </Shape>
        <Shape fill={[71, 85, 105, 255]}>
          <Rect x={150} y={10} width={30} height={90} />
        </Shape>
      </Scene>
      
      {/* Sun */}
      <Scene x={170} y={30}>
        <Shape fill={[250, 204, 21, 255]}>
          <Circle x={0} y={0} radius={15} />
        </Shape>
      </Scene>
    </SwCanvas>
  );
}

Dynamic Scenes

Create scenes dynamically based on data.
import { SwCanvas, Scene, Shape, Circle } from 'react-thorvg-fiber';

function DynamicGrid() {
  const rows = 3;
  const cols = 3;
  const size = 20;
  const spacing = 30;
  
  return (
    <SwCanvas width={200} height={200}>
      <Scene x={40} y={40}>
        {Array.from({ length: rows }, (_, row) =>
          Array.from({ length: cols }, (_, col) => (
            <Scene key={`${row}-${col}`} x={col * spacing} y={row * spacing}>
              <Shape fill={[
                59 + row * 60,
                130 + col * 40,
                246 - row * 50,
                255
              ]}>
                <Circle x={0} y={0} radius={size / 2} />
              </Shape>
            </Scene>
          ))
        )}
      </Scene>
    </SwCanvas>
  );
}
This creates a 3x3 grid of circles with varying colors.

Animated Scene Hierarchies

Animate entire scene hierarchies for coordinated motion.
import { SwCanvas, Scene, Shape, Rect, Circle } from 'react-thorvg-fiber';
import { useState, useEffect } from 'react';

function AnimatedRobot() {
  const [rotation, setRotation] = useState(0);
  const [armAngle, setArmAngle] = useState(0);
  
  useEffect(() => {
    const interval = setInterval(() => {
      setRotation(r => (r + 1) % 360);
      setArmAngle(a => Math.sin(Date.now() / 300) * 30);
    }, 16);
    return () => clearInterval(interval);
  }, []);
  
  return (
    <SwCanvas width={200} height={200}>
      {/* Robot body - rotates */}
      <Scene x={100} y={100} rotation={rotation}>
        {/* Head */}
        <Shape fill={[71, 85, 105, 255]}>
          <Rect x={-20} y={-50} width={40} height={30} rx={5} ry={5} />
        </Shape>
        
        {/* Body */}
        <Shape fill={[71, 85, 105, 255]}>
          <Rect x={-25} y={-15} width={50} height={40} rx={5} ry={5} />
        </Shape>
        
        {/* Left arm - waves */}
        <Scene x={-25} y={-10} rotation={armAngle}>
          <Shape fill={[100, 116, 139, 255]}>
            <Rect x={-15} y={0} width={15} height={30} rx={3} ry={3} />
          </Shape>
        </Scene>
        
        {/* Right arm - waves opposite */}
        <Scene x={25} y={-10} rotation={-armAngle}>
          <Shape fill={[100, 116, 139, 255]}>
            <Rect x={0} y={0} width={15} height={30} rx={3} ry={3} />
          </Shape>
        </Scene>
      </Scene>
    </SwCanvas>
  );
}
This creates a robot that rotates while its arms wave independently.

Scene Reusability

Create reusable scene components for repeated elements.
import { SwCanvas, Scene, Shape, Rect, Circle } from 'react-thorvg-fiber';

function Tree({ x, y, scale = 1 }: { x: number; y: number; scale?: number }) {
  return (
    <Scene x={x} y={y} scaleX={scale} scaleY={scale}>
      {/* Trunk */}
      <Shape fill={[120, 53, 15, 255]}>
        <Rect x={-5} y={0} width={10} height={30} />
      </Shape>
      
      {/* Leaves */}
      <Shape fill={[34, 197, 94, 255]}>
        <Circle x={0} y={-10} radius={20} />
      </Shape>
    </Scene>
  );
}

function Forest() {
  return (
    <SwCanvas width={200} height={200}>
      <Tree x={40} y={150} scale={0.8} />
      <Tree x={100} y={140} scale={1.2} />
      <Tree x={160} y={145} scale={1.0} />
    </SwCanvas>
  );
}

Performance Optimization

Group related shapes in scenes for better performance when updating.
import { SwCanvas, Scene, Shape, Rect } from 'react-thorvg-fiber';
import { memo } from 'react';

// Memoize static background
const Background = memo(() => (
  <Scene>
    <Shape fill={[226, 232, 240, 255]}>
      <Rect x={0} y={0} width={200} height={200} />
    </Shape>
  </Scene>
));

// Memoize static decorations
const Decorations = memo(() => (
  <Scene opacity={180}>
    <Shape fill={[203, 213, 225, 255]}>
      <Rect x={10} y={10} width={30} height={30} rx={5} ry={5} />
    </Shape>
    <Shape fill={[203, 213, 225, 255]}>
      <Rect x={160} y={10} width={30} height={30} rx={5} ry={5} />
    </Shape>
  </Scene>
));

function App({ playerX }: { playerX: number }) {
  return (
    <SwCanvas width={200} height={200}>
      <Background />
      <Decorations />
      
      {/* Only this scene updates when playerX changes */}
      <Scene x={playerX} y={100}>
        <Shape fill={[59, 130, 246, 255]}>
          <Rect x={0} y={0} width={20} height={20} />
        </Shape>
      </Scene>
    </SwCanvas>
  );
}
By memoizing static scenes, React avoids re-rendering them when only the player position changes.

Build docs developers (and LLMs) love