Skip to main content
Version: Next

3D Viewer

Renders an imported GLB model with live tag bindings — the colour, emissive, opacity and visibility of any node in the model can follow a tag. A 3D equivalent of a P&ID mimic.

The 3D Viewer component as it renders with its default settings.The 3D Viewer component as it renders with its default settings.

Reach for it when you need:

  • A 3D plant or machine view where components colour by state

Component name: Viewer3D · Category: Display

In the palette: Renders an imported 3D model (GLB) with live tag bindings: color, emissive, opacity and visibility of any node in the model can follow a tag.

Properties

Any property can be bound to a tag, another component's property, or a query.

PropertyTypeDefaultDescription
modelasset""The 3D model (.glb), from the asset Library or the Uploads folder. Bindable — bind it to a tag/expression yielding a path (e.g. Models/Pumps/p1.glb) or an upload:// ref (e.g. a File Manager widget's {{ <name>.selectedItem.ref }}) to swap the model at runtime.
bindingsarray[]Tag→model bindings. Each row drives one property (color / emissive / opacity / visible) of one node. Bind each row's value to a tag, or the whole array to a Named Query.
labelsarray[]Text overlays pinned to nodes — a live tag readout with a quality badge. Each row binds its own text + quality.
fitOnLoadbooleantrueFrame the model automatically when no camera has been set.
backgroundcolor""Canvas background color. Blank = transparent (the view shows through).
lightingobject{"preset":"studio","intensity":1,"ambient":1,"direction":[5,… (truncated)Light rig, how strong it is, and where the key light comes from. Set the direction with the edit-mode 'Set light' tool (aim the view, then Save) or type it. Every field is bindable.
interactivebooleantrueAllow orbit/pan/zoom in LiveView (the editor always locks the camera; use Set camera to frame it).
cameraobject{}Input: the AUTHORED default camera pose — written by the Set camera tool, or click + to fill the fields and type them. Leave empty to auto-fit the model. (For the LIVE pose an operator orbits to at runtime, read the output.cameraView output instead.)
orbitobject{"minDistance":0,"maxDistance":0,"enableZoom":true,"enablePa… (truncated)Camera interaction limits (three's OrbitControls) — zoom range, pan/zoom toggles, auto-rotate.
lookobject{"projection":"perspective","toneMapping":"none","exposure":… (truncated)How the model READS on screen: projection, tone mapping + exposure, shadows/ground/grid/axes, selection highlight, and the device-pixel-ratio cap.
animationobject{"clip":"","playing":false,"speed":1,"time":0,"loop":true}Input: animation playback CONTROL — clip name, play/pause, speed, scrub time and loop. Every field is bindable. (For the list of clip names this model offers, see the output.animationClips output.)
outputobject{"selectedObject":{},"cameraView":{},"sceneNodes":[],"animat… (truncated)Read-only runtime outputs the widget publishes — bind a leaf, e.g. {{ <Viewer3D>.output.selectedObject.name }}. Leaves: selectedObject { name, path }, cameraView { position, target, fov }, sceneNodes [{ name, path }], animationClips [string], morphTargets [string].
stylestyle{}Custom CSS properties

Events

Attach event actions to these in the Event Manager.

EventLabelGroupPayload
clickClickMouseThe DOM event.
dblclickDouble clickMouseThe DOM event.
contextmenuRight clickMouseThe DOM event.
mouseenterMouse enterMouseThe DOM event.
mouseleaveMouse leaveMouseThe DOM event.
objectClickObject click3D ObjectThe picked model node, under selectedObject ({ name, path }).
objectDoubleClickObject double click3D ObjectThe picked model node, under selectedObject.
Right-click behaves differently in the Designer

contextmenu fires your configured actions at runtime only — in LiveView and in preview. On the Designer canvas the right-click is captured to open the Event Manager, so testing it there will not run your actions. Test right-click in preview.

Notes

Reading what it publishes

Everything the viewer reports back — the picked object, the current camera, the model's animation clips and morph targets — lives under one output object, so a binding reads:

{{ <Viewer3D>.output.selectedObject.name }}
{{ <Viewer3D>.output.cameraView }}
{{ <Viewer3D>.output.animationClips }}
{{ <Viewer3D>.output.morphTargets }}

They were top-level props once, and three of them mirrored an authored input by name — cameraView beside camera, animationClips beside animation — so the property grid read as though the same thing were declared twice and a binding author could not tell which one to bind from. Grouping them says which side of the widget each belongs to.

Clicking one object rather than the whole viewer

Objects in the model are addressable parts: each can carry its own objectClick and objectDoubleClick, wired in the Event Manager under its node name. A click on a multi-primitive node is walked up to the deepest ancestor you wired, so the name you see in the model tree is the name to use. → Events on a part of a widget

Performance

Large models are the most expensive thing you can put on a screen. Check it on the actual panel hardware, not on your laptop.

See also