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.
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | — | Image URL or data URI. Required unless imageRef is provided. |
imageRef | string | — | Opaque consumer reference resolved via ImageResolverProvider at render time |
x | number | — | Required. X coordinate of the top-left corner |
y | number | — | Required. Y coordinate of the top-left corner |
width | number | — | Required. Rendered width |
height | number | — | Required. Rendered height |
preserveAspectRatio | string | 'xMidYMid meet' | SVG aspect-ratio keyword |
borderRadius | number | 0 | Corner radius for rounded images |
clipShape | 'none' | 'circle' | 'ellipse' | 'none' | Clip the image to a shape |
opacity | number | 1 | Opacity from 0 to 1 |
rotation | number | 0 | Rotation in degrees |
rotationOrigin | [number, number] | element center | Center point for rotation |
scale | number | [number, number] | 1 | Uniform 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.
Code Examples
Section titled “Code Examples”Basic image
Section titled “Basic image”elements: { photo: { id: 'photo', type: 'image', props: { type: 'image', src: '/photo.png', x: 100, y: 50, width: 300, height: 200 }, },}Circular clip
Section titled “Circular clip”props: { type: 'image', src: '/avatar.png', x: 200, y: 100, width: 100, height: 100, clipShape: 'circle' }Rounded corners
Section titled “Rounded corners”props: { type: 'image', src: '/thumbnail.jpg', x: 50, y: 50, width: 400, height: 250, borderRadius: 20 }Rotated image
Section titled “Rotated image”layout: { rotation: 15 }props: { type: 'image', src: '/diagram.svg', x: 100, y: 50, width: 200, height: 200 }Image with fade-in timeline
Section titled “Image with fade-in timeline”timelines: { intro: { id: 'intro', duration: 30, tracks: [{ target: 'hero', property: 'opacity', keyframes: [{ frame: 0, value: 0 }, { frame: 30, value: 1 }] }], },}Asset References
Section titled “Asset References”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:
imageRef+ resolver → resolved URLimageRef+ no resolver → falls back tosrc- No
imageRef→ usessrcdirectly
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.