Viewer postMessage API
Gebruik de viewer postMessage API wanneer een bovenliggende HTML-pagina de Voluma-viewer in een iframe insluit en pagina-UI met de viewerstatus moet afstemmen. De parent kan een marker in de viewer focussen, en de viewer kan de parent melden dat hij klaar is, dat markerfocus verandert, of dat een markeractie een aangepast bericht verzendt.
Instellen
Gebruik de aangepaste viewer-URL uit Aangepaste viewer (insluiten), open daarna Projectinstellingen en vul Toegestane origins in onder Viewer API. Dit projectniveauveld wordt opgeslagen als settings.embed.allowedParentOrigins en moet de exacte origin van de bovenliggende pagina bevatten.
Voer origins in als kommagescheiden volledige URL's, bijvoorbeeld https://www.example.com, https://partner.example.com. Lokale ontwikkelorigins zoals http://127.0.0.1:5172 kunnen tijdens het testen worden toegevoegd.
<iframe
id="voluma-viewer"
src="https://voluma.ai/embed/client/project/scene"
width="100%"
height="640"
allowfullscreen
></iframe>Alle runtimecontroles gebruiken exacte origins. Commando's van parent naar viewer vanaf andere origins worden geweigerd, en berichten van viewer naar parent worden met exacte targetOrigin-waarden verzonden. Gebruik in productiecode van de parent geen * als target origin.
Parent naar viewer
Het ondersteunde commando van parent naar viewer is voluma.viewer.focusMarker.
| Veld | Type | Verplicht | Beschrijving |
|---|---|---|---|
type | string | Ja | Moet voluma.viewer.focusMarker zijn. |
version | number | Ja | Moet 1 zijn. |
requestId | string | Ja | Door de parent gegenereerde ID om de bevestiging of fout te koppelen. |
markerId | string of number | Ja | Marker-ID om te focussen. |
const iframe = document.querySelector("#voluma-viewer");
const viewerOrigin = new URL(iframe.src).origin;
let requestCounter = 0;
function focusMarker(markerId) {
iframe.contentWindow?.postMessage(
{
type: "voluma.viewer.focusMarker",
version: 1,
requestId: `marker-${Date.now()}-${++requestCounter}`,
markerId
},
viewerOrigin
);
}Viewer naar parent
De viewer verzendt getypeerde protocol-events voor de embedlevenscyclus en commandofeedback.
| Eventtype | Payload | Wanneer verzonden |
|---|---|---|
voluma.viewer.ready | { type, version } | De embed-viewer is geladen en klaar voor commando's. |
voluma.viewer.markerFocused | { type, version, markerId, requestId? } | Een marker krijgt focus. requestId is aanwezig wanneer het event een commando bevestigt. |
voluma.viewer.error | { type, version, code, message, requestId? } | Een commando is ongeldig, niet toegestaan, niet ondersteund, of kan niet worden uitgevoerd. |
Bekende foutcodes zijn INVALID_MESSAGE, UNAUTHORIZED_ORIGIN, MARKER_NOT_FOUND, VIEWER_NOT_READY, UNSUPPORTED_VERSION, UNSUPPORTED_COMMAND en INTERNAL_ERROR.
window.addEventListener("message", (event) => {
if (event.origin !== viewerOrigin) return;
if (!event.data || typeof event.data !== "object") return;
if (event.data.type === "voluma.viewer.ready") {
console.log("Viewer ready");
}
if (event.data.type === "voluma.viewer.markerFocused") {
console.log("Focused marker", event.data.markerId, event.data.requestId);
}
if (event.data.type === "voluma.viewer.error") {
console.warn("Viewer command failed", event.data.code, event.data.message);
}
});Markeractieberichten
Markers kunnen ook aangepaste berichten naar de bovenliggende pagina sturen. Configureer in Studio een markeractie met actietype postMessage, een berichttype en optioneel een payloadtemplate.
De viewer verzendt markeractieberichten met deze vorm:
{
source: "volumaviewer",
type: "marker-action",
payload: {
id: 7,
parent_id: 0,
type: "sphere",
title: "Marker title"
},
timestamp: 1710000000000
}Payloadtemplates kunnen {id}, {parent_id}, {type} en {title} gebruiken. Als de gerenderde payload geldige JSON is, ontvangt de parent geparste JSON. Zo niet, dan ontvangt de parent de gerenderde string.
window.addEventListener("message", (event) => {
if (event.origin !== viewerOrigin) return;
const data = event.data;
if (!data || typeof data !== "object") return;
if (data.source === "volumaviewer" && data.type === "marker-action") {
console.log("Marker action payload", data.payload);
}
});Patroon voor parentpagina's
Voor pagina-UI die de iframe aanstuurt, bewaar je de viewer-origin op een plek, valideer je elk binnenkomend bericht, en genereer je unieke request-ID's voor commando's. De Veerse Toren-demo gebruikt dit patroon om viewermarkers te focussen vanuit externe calloutknoppen, en reageert daarna op een aangepast markerbericht door content onder de iframe te tonen.
const iframe = document.querySelector(".embedCode iframe");
const viewerOrigin = new URL(iframe.src).origin;
let latestRequestId = 0;
window.addEventListener("message", (event) => {
if (event.origin !== viewerOrigin) return;
const data = event.data;
if (!data || typeof data !== "object") return;
if (data.source === "volumaviewer" && data.payload?.action === "geschiedenis") {
document.querySelector(".history-section")?.classList.add("is-visible");
}
});
document.querySelectorAll("[data-marker-id]").forEach((button) => {
button.addEventListener("click", () => {
iframe.contentWindow?.postMessage(
{
type: "voluma.viewer.focusMarker",
version: 1,
requestId: `parent-${Date.now()}-${++latestRequestId}`,
markerId: button.dataset.markerId
},
viewerOrigin
);
});
});URL-fallback
Als de iframe nog niet klaar is, naar een andere scene is genavigeerd, of opnieuw geladen moet worden voordat een marker wordt gefocust, werk dan de iframe-URL bij met de markerqueryparameter in plaats van een commando te sturen:
function buildMarkerUrl(originalIframeUrl, markerId) {
const url = new URL(originalIframeUrl, window.location.href);
url.searchParams.set("m", markerId);
return url.toString();
}
iframe.src = buildMarkerUrl(iframe.dataset.iframe || iframe.src, markerId);Gebruik deze fallback voor volledige iframe-herladingen. Gebruik voluma.viewer.focusMarker wanneer de huidige iframe geladen is en op dezelfde scene moet blijven.
