Skip to content

Image

The image primitive embeds an external image (PNG, JPEG, SVG, WebP, or GIF) into your scene. It supports rounded corners, circular/elliptical clipping, and standard spatial layout fields.

0.00s / 3.97s · F0
PropTypeDefaultDescription
srcstringImage URL or data URI. Required unless imageRef is provided.
imageRefstringOpaque consumer reference resolved via ImageResolverProvider at render time
xnumberRequired. X coordinate of the top-left corner
ynumberRequired. Y coordinate of the top-left corner
widthnumberRequired. Rendered width
heightnumberRequired. Rendered height
preserveAspectRatiostring'xMidYMid meet'SVG aspect-ratio keyword
borderRadiusnumber0Corner radius for rounded images
clipShape'none' | 'circle' | 'ellipse''none'Clip the image to a shape
opacitynumber1Opacity from 0 to 1
rotationnumber0Rotation in degrees
rotationOrigin[number, number]element centerCenter point for rotation
scalenumber | [number, number]1Uniform or per-axis scale
translate[number, number][0, 0]Translation offset [dx, dy]

Images stack by sibling order in scene.children or their parent group’s children array. Later siblings paint on top.

elements: {
photo: {
id: 'photo',
type: 'image',
props: { type: 'image', src: '/photo.png', x: 100, y: 50, width: 300, height: 200 },
},
}
props: { type: 'image', src: '/avatar.png', x: 200, y: 100, width: 100, height: 100, clipShape: 'circle' }
props: { type: 'image', src: '/thumbnail.jpg', x: 50, y: 50, width: 400, height: 250, borderRadius: 20 }
layout: { rotation: 15 }
props: { type: 'image', src: '/diagram.svg', x: 100, y: 50, width: 200, height: 200 }
timelines: {
intro: {
id: 'intro',
duration: 30,
tracks: [{ target: 'hero', property: 'opacity', keyframes: [{ frame: 0, value: 0 }, { frame: 30, value: 1 }] }],
},
}

Instead of hardcoding URLs, you can use opaque asset references via the imageRef prop. At render time, an ImageResolverProvider resolves the reference to a URL.

This is useful when your app manages images through a CMS, asset library, or API — the document stores an ID, and the resolver provides the actual URL at runtime.

import { DslRenderer, ImageResolverProvider, type ElucimDocument } from '@elucim/dsl';
const resolver = (ref) => `https://cdn.example.com/assets/${ref}`;
const doc: ElucimDocument = {
version: '2.0',
scene: { type: 'player', width: 500, height: 300, children: ['hero'] },
elements: {
hero: {
id: 'hero',
type: 'image',
props: { type: 'image', imageRef: 'hero-banner', x: 0, y: 0, width: 500, height: 300 },
},
},
};
<ImageResolverProvider resolver={resolver}>
<DslRenderer dsl={doc} />
</ImageResolverProvider>

Resolution rules:

  1. imageRef + resolver → resolved URL
  2. imageRef + no resolver → falls back to src
  3. No imageRef → uses src directly

Async resolvers are also supported — return a Promise<string> for signed URLs or token-gated assets.

See the Image Assets guide for the full workflow including the editor’s image picker.