Draws SVG into the 3D scene as a real, depth-tested texture — an annotation that is part of the rendered image, so geometry in front of it truly covers it.
Declarative element:
<sk-rasterized-annotation>
Global: available as sk.RasterizedAnnotationNode inside a scene <script>.
This is the rasterized member of the AbstractDomAnnotationNode annotation
family: like every annotation its content is the element's own body and it tracks a
world position. What distinguishes it from the live and overlay annotations is that
its SVG body is rasterized to a GPU texture and composited inside the scene, so it
is genuinely depth-tested — occluded by geometry in front of it as a true 3D surface,
not a DOM layer over the canvas. This is the annotation to use when a label must sit
in the scene's depth (behind a passing object, on a surface) rather than on a plane
above everything.
With RenderableNode.overlay
enabled, the annotation instead renders on top of the composited scene with
depth-aware translucency: fragments occluded by scene geometry are dimmed
to RenderableNode.overlayOccludedOpacity rather than hidden — the
same node-level overlay semantics shared by all renderable nodes.
Rasterized annotations ARE interactive: the light-DOM body is retained as
an invisible hit-target, so pointer and drag events work exactly as they
do for live annotations (only the visible pixels come from the GPU
texture). What the rasterized pixels cannot do is animate via CSS — the
texture is a static snapshot until markSvgDirty schedules a
re-rasterization.
The body content lives in the host's light DOM. It is invisible (the host
is opacity: 0) but kept around for measurement and hit-testing — the
visible pixels come from the rasterized GPU texture.
Like live and overlay annotations, a rasterized annotation owns a shadow
projection wrapper (it extends AbstractWebAnnotationNode): the
light-DOM body slots through it, and the wrapper carries the framework's
anti-flash visibility and the pointer-events suppression gate. The host
stays opacity: 0 (DOM plumbing invisible, GPU texture visible); the
rasterizer still reads the light-DOM body markup via rasterizationContent,
so slotting does not change what gets rasterized.
After construction, mutate the content via standard DOM APIs
(annotation.innerHTML = ..., annotation.firstElementChild.querySelector(...))
and then call markSvgDirty to schedule re-rasterization.
Related. For live, CSS-animated, interactive HTML content layered over the canvas
(occludable), use sk-live-annotation; for content that must always stay on top
and never be hidden by geometry, use sk-overlay-annotation.
## Rasterization Limitations
The body content is handed to the platform unchanged — loaded as the
source of an <img> element (a blob URL with type image/svg+xml) and
drawn to a canvas. The platform is the sole decider of what renders.
Skenra does not inspect, validate, or rewrite the content. In practice
this means only valid, self-contained SVG rasterizes:
- Non-SVG content (HTML, e.g. <div>…</div>) loads but renders blank
with no error. Use LiveAnnotationNode for HTML.
- External references (<image href="https://…">, external fonts/CSS,
<use href> to other documents) render a broken-image glyph or blank
— the blob URL has no document base, so relative/cross-origin refs fail.
- **<foreignObject> and cross-origin images** taint the canvas; the
rasterizer then throws and the annotation logs a console.warn and
renders an empty quad (the scene continues).
- **<script>** is inert inside an <img>-loaded SVG (never executes).
- Markdown (md = true) is not yet rasterizable — the body is
Markdown source, not SVG, so it renders blank. (The md flag is
accepted for API uniformity across annotation types; a future
Markdown→SVG renderer would make it work.)
Malformed markup and canvas-tainting content surface as a console.warn
(naming the annotation id) plus an empty quad. Silently-blank cases
(HTML, external refs) are the platform's documented behavior and are not
warned. For best results: inline all styles, use rgb()/rgba() or named
colors, set explicit width/height and xmlns, and avoid external
references.
Security Warning: Content is NOT sanitized by this class. If accepting user-provided or untrusted content, you MUST sanitize it first to prevent XSS attacks.
constructor(config?: { castShadow?: boolean; content?: string; md?: boolean; anchor?: AnchorAlignment; scaleWithDistance?: boolean; class?: string; style?: string; overlay?: boolean; overlayOccludedOpacity?: number; id?: string; x?: number; y?: number; z?: number; h?: number; p?: number; b?: number; quaternion?: Quaternion; sx?: number; sy?: number; sz?: number; s?: number })
Inherited from: AbstractDomAnnotationNode, RenderableNode, SceneNode, SkenraAnimatable
— see those pages for inherited members.
| Property | Type | Default | Description | Declared by |
|---|---|---|---|---|
castShadow |
boolean |
— | Gets whether this annotation casts shadows. | RasterizedAnnotationNode |
contentconfig-only |
string |
— | The annotation body content as an inline markup string. | AbstractDomAnnotationConfig |
md |
boolean |
false |
Whether this annotation's light-DOM body is Markdown source. | AbstractDomAnnotationNode |
anchor |
AnchorAlignment |
"center" |
Gets the anchor alignment for this annotation. | AbstractDomAnnotationNode |
scaleWithDistance |
boolean |
false |
Gets whether this annotation scales with camera distance. | AbstractDomAnnotationNode |
classconfig-only |
string |
— | Standard HTML class for the annotation host element. |
AbstractDomAnnotationConfig |
styleconfig-only |
string |
— | Standard inline style for the annotation host element. |
AbstractDomAnnotationConfig |
overlay |
boolean |
false |
Whether this node renders as an overlay with depth-aware translucency. | RenderableNode |
overlayOccludedOpacity |
number |
0.3 |
Alpha multiplier for overlay fragments occluded by scene geometry. | RenderableNode |
idconfig-only |
string |
— | Unique identifier for the node, reflected to the host id attribute. |
SceneNodeConfig |
xanimatable |
number |
0 |
Gets the X position component. | SceneNode |
yanimatable |
number |
0 |
Gets the Y position component. | SceneNode |
zanimatable |
number |
0 |
Gets the Z position component. | SceneNode |
hanimatable |
number |
0 |
Gets the heading (Y-axis) rotation in radians. | SceneNode |
panimatable |
number |
0 |
Gets the pitch (X-axis) rotation in radians. | SceneNode |
banimatable |
number |
0 |
Gets the bank (Z-axis) rotation in radians. | SceneNode |
quaternionanimatable |
Quaternion |
— | Gets the rotation as a quaternion. | SceneNode |
sxanimatable |
number |
1 |
Gets the X-axis scale factor. | SceneNode |
syanimatable |
number |
1 |
Gets the Y-axis scale factor. | SceneNode |
szanimatable |
number |
1 |
Gets the Z-axis scale factor. | SceneNode |
sconfig-only |
number |
— | Uniform scale factor for all axes (overrides sx, sy, sz if provided) | SceneNodeConfig |
| Property | Type | Default | Description | Declared by |
|---|---|---|---|---|
hRad |
number |
0 |
Gets the heading (Y-axis) rotation in radians. | SceneNode |
pRad |
number |
0 |
Gets the pitch (X-axis) rotation in radians. | SceneNode |
bRad |
number |
0 |
Gets the bank (Z-axis) rotation in radians. | SceneNode |
hDeg |
number |
0 |
Gets the heading (Y-axis) rotation in degrees. | SceneNode |
pDeg |
number |
0 |
Gets the pitch (X-axis) rotation in degrees. | SceneNode |
bDeg |
number |
0 |
Gets the bank (Z-axis) rotation in degrees. | SceneNode |
xBasebase value |
number |
— | Gets the base (non-animated) value of X position. | SceneNode |
yBasebase value |
number |
— | Gets the base (non-animated) value of Y position. | SceneNode |
zBasebase value |
number |
— | Gets the base (non-animated) value of Z position. | SceneNode |
hBasebase value |
number |
0 |
Gets the base (non-animated) value of heading (Y-axis rotation). | SceneNode |
pBasebase value |
number |
0 |
Gets the base (non-animated) value of pitch (X-axis rotation). | SceneNode |
bBasebase value |
number |
0 |
Gets the base (non-animated) value of bank (Z-axis rotation). | SceneNode |
quaternionBasebase value |
Quaternion |
— | Gets the base (non-animated) quaternion rotation. | SceneNode |
sxBasebase value |
number |
— | Gets the base (non-animated) value of X-axis scale. | SceneNode |
syBasebase value |
number |
— | Gets the base (non-animated) value of Y-axis scale. | SceneNode |
szBasebase value |
number |
— | Gets the base (non-animated) value of Z-axis scale. | SceneNode |
draggable |
boolean |
false |
Gets whether this node can be dragged. | SceneNode |
parentread-only |
SceneNode | null |
— | The parent node in the scene graph, or null at the root. |
SceneNode |
sceneread-only |
any |
— | Gets the Scene this node belongs to, if any. | SceneNode |
posread-only |
Point3D |
— | Gets the world-space position of this node. | SceneNode |
matrixread-only |
Float32Array<ArrayBufferLike> |
— | Gets the computed 4x4 transformation matrix. | SceneNode |
animationsread-only |
SkenraAnimation[] |
— | Public getter for the animations affecting this target. | SkenraAnimatable |
| Method | Description | Declared by |
|---|---|---|
getBoundsInSpace(targetSpaceMatrix: Float32Array): { minX: number; maxX: number; minY: number; maxY: number; minZ: number; maxZ: number; } | null |
Computes the bounding box of this annotation in the specified target space. | AbstractDomAnnotationNode |
addMaterialPaint(material: Material, paintTarget: PaintTarget, options?: any): Paint |
Applies a material to this node for a specific paint target. | SceneNode |
getPaints(): ReadonlyMap<PaintTarget, Paint> |
— | SceneNode |
getOwnPaints(): readonly Paint[] |
Gets only the paints directly applied to this node (not inherited). | SceneNode |
removePaint(paint: Paint): void |
Removes a paint from this node. | SceneNode |
getWorldPosition(): number[] |
Returns this node’s origin in world space. | SceneNode |
getWorldMatrix(): Float32Array<ArrayBufferLike> |
Returns this node’s world transform — its local transform composed with all ancestor transforms. | SceneNode |
setViewportPosition(camera: AbstractCamera, x: number, y: number, z: number = 0.5): boolean |
Sets the node's local translation so that it appears at the specified viewport position. | SceneNode |
getViewportPosition(camera?: AbstractCamera): [number, number, number] | null |
Returns the node's current world position projected to viewport CSS pixel coordinates. | SceneNode |
setNDCPosition(camera: AbstractCamera, ndcX: number, ndcY: number, ndcZ: number = 0.5): boolean |
Sets the node's local translation so that it appears at the specified NDC position in the viewport. | SceneNode |
animate(firstArg: TypedKeyframe<this>[] | TypedPropertyIndexedKeyframes<this> | Record<string, any> | globalThis.Keyframe[] | globalThis.PropertyIndexedKeyframes | null, secondArg?: number | KeyframeAnimationOptions | globalThis.KeyframeAnimationOptions): SkenraAnimation & Animation |
Creates a new SkenraAnimation for this target per Web Animations API. | SkenraAnimatable |
removeAnimation(animation: SkenraAnimation): boolean |
Removes a specific animation from this object. | SkenraAnimatable |
constrain(type: K, config: ConstraintConfigMap[K]): ConstraintReturnMap[K] |
Creates a constraint on this Animatable using a fluent API. | SkenraAnimatable |
const label = new RasterizedAnnotationNode({
id: 'label',
content: '<svg viewBox="0 0 120 30" width="120" height="30"><text x="10" y="20" fill="white">Label</text></svg>',
anchor: 'bottom'
});
scene.appendChild(label);