Scene basics

← prev index next →

Every Skenra scene is a tree of Custom Elements inside an <sk-scene>. This guide starts from defaults and builds up a lit, animated, interactive scene one concept at a time — a cube and a sphere on a shadow-catching ground plane, with your own light and camera, an annotated callout, and a click interaction. The live example above is the finished result; each step below shows the scene as it stands, with the newly added markup highlighted.

Final result

Serve these docs to run the live example. WebGPU needs a secure context — open this page via grunt serve rather than double-clicking the file. The Markup tab works from disk.

Build it step by step

1.1 — A lit scene with a ground, a cube, and a sphere

Author an <sk-scene> and drop three meshes in it. Materials are scene resources declared once and referenced by id from a paint. With no camera or light declared, the scene supplies sensible defaults — the shapes are auto-fitted, lit, and interactive out of the box (drag to orbit, scroll to zoom), and the ground plane catches a shadow.

Serve these docs to run the live example. WebGPU needs a secure context — open this page via grunt serve rather than double-clicking the file. The Markup tab works from disk.

1.2 — Outline the cube with edge paint

A node can carry more than one paint. Add an <sk-edge-paint> alongside the surface paint to stroke the cube’s edges. Edge paint references its own material, so the outline colour is independent of the fill.

Serve these docs to run the live example. WebGPU needs a secure context — open this page via grunt serve rather than double-clicking the file. The Markup tab works from disk.

1.3 — Bring your own directional light

Declaring an <sk-directional-light> replaces the scene’s default light. A directional light is defined by its direction, set with the pitch (p) and heading (h) rotation attributes — here p="90deg" points it straight down (rotation attributes take a CSS angle like "90deg" or "1.57rad"); intensity scales it.

Serve these docs to run the live example. WebGPU needs a secure context — open this page via grunt serve rather than double-clicking the file. The Markup tab works from disk.

1.4 — Bring your own camera

Declaring an <sk-perspective-camera> replaces the default camera. Place it directly with the transform attributes — here y="10" with p="-90deg" looks straight down for a top view — though the next step shows an easier way to frame and orbit the scene.

Serve these docs to run the live example. WebGPU needs a secure context — open this page via grunt serve rather than double-clicking the file. The Markup tab works from disk.

1.5 — Frame and orbit with camera-orbit control

Scenes are interactive out of the box, but declaring a scene-root <sk-camera-orbit-control> lets you customize the controller: auto-frame the content (fit-targets="auto"), set the starting angle (azimuth/elevation), and tune the drag-to-orbit, scroll-to-zoom, right-drag-to-pan feel. The camera itself becomes bare; do not also add an orbit constraint to the camera.

Serve these docs to run the live example. WebGPU needs a secure context — open this page via grunt serve rather than double-clicking the file. The Markup tab works from disk.

1.6 — Place and aim the light with an orbit constraint

An <sk-orbit-constraint> positions its host on a sphere around a pivot (radius / azimuth / elevation). With orient-toward-pivot it also aims the host at the pivot — so the directional light’s direction follows the orbit, not just its position.

Serve these docs to run the live example. WebGPU needs a secure context — open this page via grunt serve rather than double-clicking the file. The Markup tab works from disk.

1.7 — Animate the sphere’s colour and the cube’s rotation

Animation is declarative: nest an <sk-animation> inside the node (or material) to animate, with <sk-keyframe> children naming the property at each offset. Material properties (base-color) animate inside the material; transform properties (the roll rotation b) inside the node.

Serve these docs to run the live example. WebGPU needs a secure context — open this page via grunt serve rather than double-clicking the file. The Markup tab works from disk.

1.8 — Animate the light’s orbit

The orbit constraint exposes azimuth as an animatable property, so you animate the light’s orbit by animating the constraint — sweep azimuth 0deg → 360deg for a full revolution of the sun around the scene.

Serve these docs to run the live example. WebGPU needs a secure context — open this page via grunt serve rather than double-clicking the file. The Markup tab works from disk.

1.9 — Add a callout: a label and a connector spline

Point at the cube with a callout built from two elements. An <sk-live-annotation> is an HTML label anchored to a 3D point — here (-3.6, 2, 2), with anchor="bottom" so the label sits above its anchor; its content is ordinary HTML in the element’s body. An <sk-spline> draws the connector: its path is an SVG path string laid in a plane chosen by coordinate-space. Using "xy" puts it in the Skenra X/Y plane with Y up (no inversion), so the path coordinates match the world positions directly — it runs from the label’s anchor straight down, around two rounded elbows, to the cube’s base. The spline is stroked with an <sk-stroke-paint> (width is in screen pixels by default).

Serve these docs to run the live example. WebGPU needs a secure context — open this page via grunt serve rather than double-clicking the file. The Markup tab works from disk.

1.10 — React to a click

Scene elements are real DOM elements, so standard event-handler attributes work — and standard CSS too: style="cursor: pointer" hints the cube is clickable. Clicking it toggles its surface paint between the cube and sphere materials — changing a paint’s material="…" at runtime re-renders it. With the callout inviting the interaction, this is the finished scene shown at the top.

Serve these docs to run the live example. WebGPU needs a secure context — open this page via grunt serve rather than double-clicking the file. The Markup tab works from disk.

Reference