English
Appearance
English
Appearance
By default, once assets finish downloading, Kivicube shows a "Start Now" button and waits for the user to click before entering the scene.
It is not just a UI element. It also helps with browser media policy:
You can force-hide it with the hideStart property:
await kivicubeIframePlugin.openKivicubeScene(iframe, {
sceneId,
hideStart: true,
});Or directly in HTML:
<iframe id="kivicubeScene" scene-id="..." hide-start></iframe>Compared with directly using hideStart, it is usually better to:
If your feature depends on a button click to work reliably, a host-layer button coordinated with the default flow is safer than forcing auto-entry.
If you want to keep the native Kivicube Start Now Button and its default behavior, but align it with your host page UI, the advanced Scene / Collection APIs provide:
getStartButtonRect(): Promise<DOMRect | undefined>
setStartButtonRect(rect: Partial<CSSStyleDeclaration>): Promise<void>getStartButtonRect() returns the real getBoundingClientRect() result of the button inside the iframe.setStartButtonRect(rect) merges the given object into the button's inline style. Common fields include position, left, top, right, bottom, width, height, transform, etc.On a scene page, get SceneApi from the ready event:
let api = null;
iframe.addEventListener('ready', (event) => {
api = event.detail.api;
});On a collection page, get CollectionApi from ready:
let api = null;
iframe.addEventListener('ready', (event) => {
api = event.detail.api;
});ready event and any later event, such as downloadAssetEnd. You can fetch or change the button's position and size even before it appears.hideStart: true is configured, the methods can still be called but no longer serve a purpose.The host page overlays a custom button at the same position and sets CSS pointer-events: none so the click lands on the real button inside the iframe.
Use setStartButtonRect() to move the button inside the iframe to a new position, then align it with host-layer titles, hint text, and brand decoration.
const hostStartButton = document.querySelector('#hostStartButton');
hostStartButton.style.visibility = 'hidden'; // Hide the button by default
hostStartButton.style.pointerEvents = 'none'; // Must be set
iframe.addEventListener("ready", async (e) => {
const api = e.detail.api;
// Make sure hostStartButton is already rendered in the DOM and laid out at this point.
const rect = hostStartButton.getBoundingClientRect();
// Keep the start button inside the iframe below aligned with the host button above.
// This way, when the user clicks the host button, the click passes through to the real start button below.
// It also covers the plugin's internal button, which is required to customize the button style.
await api.setStartButtonRect({
left: rect.left + 'px',
top: rect.top + 'px',
width: rect.width + 'px',
height: rect.height + 'px'
});
});
iframe.addEventListener("downloadAssetEnd", async (e) => {
// Assets finished downloading; show the button
hostStartButton.style.visibility = 'visible';
});
iframe.addEventListener("loadSceneStart", (e) => {
// The iframe start button was clicked and the scene starts loading; hide the button now
hostStartButton.style.display = 'none';
});Use getStartButtonRect() to keep the custom button's position and size in sync with the iframe button. This also covers the plugin's internal button, which is necessary to customize the button style.
const hostStartButton = document.querySelector('#hostStartButton');
iframe.addEventListener('ready', (event) => {
const api = event.detail.api;
const rect = await api.getStartButtonRect();
Object.assign(hostStartButton.style, {
visibility: 'hidden', // Hidden at this point
position: 'fixed',
left: `${rect.left}px`,
top: `${rect.top}px`,
width: `${rect.width}px`,
height: `${rect.height}px`,
pointerEvents: 'none', // Important; must be set
});
});
iframe.addEventListener("downloadAssetEnd", async (e) => {
// Assets finished downloading; show the button
hostStartButton.style.visibility = 'visible';
});
iframe.addEventListener("loadSceneStart", (e) => {
// The iframe start button was clicked and the scene starts loading; hide the button now
hostStartButton.style.display = 'none';
});Whether you use Approach A or B, the idea is to keep the iframe button and the host-layer button aligned. When the user clicks the host-layer button, the click passes through to the iframe button, which triggers the iframe button's click event.
To be improved, but the core logic is the same as for scenes.