Skip to content

Viz4D Viewer JavaScript API

API latest version v0.7

html
<script type="text/javascript" src="https://r.viz4d.com/api/viewer-api-0.7.js"></script>
Changelog
v0.7:
  • Add new fn: captureImage, requestVideoCapture, getView, setView, getTourStep, getTourSteps, setTourSteps, getHotspots, deleteMtl
  • Changes:
    • Rename getCurrentTourStep to getCurrentTourStepIndex
    • getMtl and getMtlBySKU now resolve null if mtl not found instead of reject
    • goToTourStep, nextTourStep, prevTourStep, now resolve false if transition is interrupted before finish (instead of reject)
    • selectMtl and selectMtlBySKU now resolve true if the transition succeeds, false if interrupted (previously, both success and interrupted cases resolve without value)
    • HotspotInfo now include mtlSetID property for hotspot type config
    • getMtls now include thumbnail property for each mtl
v0.6:
v0.5:
v0.4:
v0.3:
v0.2:
v0.1:
  • Initial release
Sample Code
html
<script type="text/javascript" src="https://r.viz4d.com/api/viewer-api-0.7.js"></script>

<!-- Normal iframe embed code -->
<iframe id="viewer-iframe" src="https://viz4d.com/viewer/_YOUR_SCENE_ID_" width="640" height="480" frameborder="0" allowfullscreen mozallowfullscreen="true" webkitallowfullscreen="true" allow="autoplay;fullscreen;xr-spatial-tracking;display-capture;gamepad" xr-spatial-tracking execution-while-out-of-viewport execution-while-not-rendered web-share></iframe>

<script>
    const viewer = new ViewerAPI( document.getElementById("viewer-iframe"), {
        btnXR: false,
        btnCrossSection: false
    } );

    viewer.ready().then( async () => {
        console.log("Begin select new mtl");
        await viewer.selectMtl( "FLOOR", "Dark Wood Mtl" );
        console.log("Finish select new mtl");
    });
</script>

ViewerAPI Constructor

js
const viewer = new ViewerAPI ( HTMLIFrameElement, options = {
    debug: false, // verbose logging
    btnXR: true,
    btnFullScreen: true,
    btnCrossSection: true,
    btnCapture: true,
    btnMeasure: true,
    btnHelp: true,
    btnShare: true,
    btnControlMode: true,
    btnHotspot: true,
    btnPlay: true,
    btnInfo: true,
    
    logo: true,
    preloaderInfo: true,
    loadingSign: true,
    progressBar: true,
    menuTour: true,
    initialInfo: true, // Open scene info sidepanel at start, auto close after some seconds
    initialHelp: true, // Show help dialog at start, auto close after some seconds

    tourAutoplay: true,
    autoVariant: false // if true, auto change mtl without needing user action, it will be stopped when user open any configHotspot for the first time
} );

METHODS

General

play()

Returns: Promise<void>


pause( options )

Parameters:

  • options object (optional)
    • showPreloader boolean - Show preloader screen after pause (default: true)

Returns: Promise<void>


isPlaying()

Returns: Promise< boolean >


on( eventName, callback )

Returns: void

Description: Add a callback to an event


off( eventName, callback )

Returns: void

Description: Remove a callback from an event


once( eventName, callback )

Returns: void

Description: Add a callback to an event, but it will be removed after the first time it is triggered.


toggleControlMode()

Returns: Promise<void>

Description: Switch between Orbit and Walk control modes


toggleMeasure()

Returns: Promise<void>

Description: Toggle measure tool


toggleHotspotVisible()

Returns: Promise<void>

Description: Toggle visibility of all hotspots


Loading States

LOADING STATES

Viewer has 3 loading states, sorted in chronological order:

initialized >> ready >> loaded

initialized()

Returns: Promise<void>

Description: This promise resolve when the Viewer finish initialization and begin to loading assets.

List of fn available before initialized: on, off, once, initialized, ready, loaded, isPlaying, pause, play

Note

If Viewer has autoplay off (?autoplay=0) then initialized only trigger after the Viewer play.


ready() Promise<void>

This promise resolve when scene has loaded minimum necessary data of all objects and materials, but not fully loaded, which means low LOD of meshes/textures are added to scene, but higher LOD are still loading progressively.

INFO

All api fn are available after this ready state.


loaded() Promise<void>

This promise resolve when all data of scene is fully loaded.


Material

selectMtl( mtlSetID, mtlName, options )

Parameters:

  • mtlSetID string
  • mtlName string
  • options object (optional)
    • transition number - Transition duration in ms (default: 2000)

Returns: Promise<boolean> - Promise resolve true when transition end successfully, resolve false when transition is interrupted before finish (e.g user may select another material before this transition finish).

Description: Select a material from existing materials in mtlSet


selectMtlBySKU( mtlSetID, mtlSKU, options )

Description: Behavior similar to selectMtl(), but select by SKU instead of name.


getSelectedMtl( mtlSetID )

Parameters:

  • mtlSetID string

Returns: Promise< MtlInfo >

Description: Get currently selected material in mtlSet


getMtl( mtlName )

Parameters:

  • mtlName string

Returns: Promise< MtlInfo >

Description: Get material info by name. Resolve null if mtl not found.


getMtlBySKU( mtlSKU )

Parameters:

  • mtlSKU string

Returns: Promise< MtlInfo >

Description: Get material info by SKU. Resolve null if mtl not found.
Can be useful in case where you mainly refer to mtl by SKU, but some fn requires mtlName, so you can use getMtlBySKU to get the name of mtl

Example:
js
// get mtlName from SKU
const mtlInfo = await viewer.getMtlBySKU("MTL_SKU_HERE");
const mtlName = mtlInfo.name;

// pass mtlName to use in other fn
const diffuseTransform = await viewer.getMapTransform( mtlName, "diffuse" );

getMtls( mtlSetID )

Parameters:

  • mtlSetID string

Returns: Promise< Array[ { name: string, sku: string|null, visible: boolean, content: string|null, thumbnail: string|null }, ... ] > - example: [ {name: "Mtl 1", sku: null, visible: true, content: ""}, {name: "Mtl 2", sku: null, visible: true, content: ""} ]

Description: Get all materials of mtlSet in order. This fn can be used with reorderMtls() to re-order materials, or updateMtlsVisibility() to update visibility of materials.


reorderMtls( mtlSetID, mtlList )

Parameters:

  • mtlSetID string
  • mtlList Array [MtlInfo, ... ] - should be array of MtlInfo get from getMtls(), only the order of mtl inside array can be changed, don't add or remove any mtl from array. Require name or sku property for each mtl in array, other properties are optional.

Returns: Promise<void>

Description: Use to reorder materials in mtlSet.

Common workflow:

  1. Get materials array from getMtls()
  2. Sort materials array by some criteria
  3. Call reorderMtls() with sorted materials array
Re-order materials examples:
js
// Sort materials by name alphabetically
const mtlList = await viewer.getMtls( "MTL_SET_ID" );
mtlList.sort( (mtlA, mtlB) => {
    return mtlA.name.localeCompare(mtlB.name);
});
await viewer.reorderMtls( "MTL_SET_ID", mtlList );

js
// Move materials with "metal" in their sku to the top of the list
const mtlList = await viewer.getMtls( "MTL_SET_ID" );
mtlList.sort( (mtlA, mtlB) => {
    const isMetalA = mtlA.sku && mtlA.sku.toLowerCase().includes("metal");
    const isMetalB = mtlB.sku && mtlB.sku.toLowerCase().includes("metal");
    if (isMetalA && !isMetalB) return -1;
    if (!isMetalA && isMetalB) return 1;
    return 0;
});
await viewer.reorderMtls( "MTL_SET_ID", mtlList );

updateMtlsVisibility( mtlSetID, visibilityChanges )

Parameters:

  • mtlSetID string
  • visibilityChanges Array[ {name, visible}, ... ] - Array of objects specifying visibility changes:
    js
    [ // No need to provide all materials of mtlSet here, only include the ones you want to change visiblity.
      // the order in this array doesn't matter, it does not affect the order of materials in mtlSet. 
      { name: "Material Name", visible: true }, // either name or sku must be provided. If both are provided, name will be preferred because name is guaranteed to be unique, while sku may not be unique or be null.
      { sku: "SKU_123", visible: false }
    ]

Returns: Promise<void>

Description: Update visibility of specified materials in mtlSet. Each entry in visibilityChanges can specify a material by name or SKU and the desired visibility state.

updateMtlsVisibility examples:
js
// Hide material with SKU "SKU_123"
await viewer.updateMtlsVisibility( "MTL_SET_ID", [ { "sku": "SKU_123", "visible": false } ] );

js
// Hide all materials with "wood" in their name
const mtlList = await viewer.getMtls( "MTL_SET_ID" );
const visibilityChanges = mtlList
    .filter(mtl => mtl.name.toLowerCase().includes("wood")) // filter array to only include materials with "wood" in their name
    .map(mtl => ({ name: mtl.name, visible: false })); // map array to only include the name and set visible to false
await viewer.updateMtlsVisibility( "MTL_SET_ID", visibilityChanges );

js
// Only show materials with "metal" in their sku, hide all other materials
const mtlList = await viewer.getMtls( "MTL_SET_ID" );
const visibilityChanges = mtlList.map(mtl => ({
    name: mtl.name,
    visible: mtl.sku && mtl.sku.toLowerCase().includes("metal")
}));
await viewer.updateMtlsVisibility( "MTL_SET_ID", visibilityChanges );

createMtl( mtlDef, mtlSetID )

Parameters:

  • mtlDef object
  • mtlSetID string - (optional) target mtlSet to add the new mtl

Returns: Promise<void>
Promise resolve when all textures of this new mtl are loaded.

Description: Create a new material from mtlDef and add to mtlSet

mtlDef Structure

Note:
All properties are optional (except "name"). If any properties are not provided, default value like below will be used, so you don't need to provide all properties.

js
{
    name: string, // REQUIRED, must be unique in scene, otherwise Promise will reject
    sku: string, // default null
    content: string, // Markdown description of the material, default null

    diffuse: {
        color: [1, 1, 1], // [r, g, b], range from 0 to 1
        map: { // default null
            url: "/url/to/map.jpg", // .jpg / .png / .webp
            repeat: [1, 1], // [x, y]
            offset: [0, 0], // [x, y]
            rotation: 0 // in degree
        },
        mapAmount: 1, // range 0-1
        mapBrightness: 1
    },

    reflect: {
        color: [0, 0, 0],
        map: {
            url: "/url/to/map.jpg",
            repeat: [1, 1],
            offset: [0, 0],
            rotation: 0
        },
        mapAmount: 1
    },

    glossiness: {
        factor: 0, // range 0-1
        map: {
            url: "/url/to/map.jpg",
            repeat: [1, 1],
            offset: [0, 0],
            rotation: 0
        },
        mapAmount: 1,
        mapInvert: false // default false. If true, invert glossiness map, essentially treat it as roughness map. Only affect map, does not affect glossiness.factor
    },

    ior: {
        factor: 1.5, // range 1 - 1000
        map: {
            url: "/url/to/map.jpg",
            repeat: [1, 1],
            offset: [0, 0],
            rotation: 0
        },
        mapAmount: 1
    },

    metalness: {
        factor: 0, // range 0-1
        map: {
            url: "/url/to/map.jpg",
            repeat: [1, 1],
            offset: [0, 0],
            rotation: 0
        },
        mapAmount: 1
    },

    opacity: {
        factor: 1, // range 0-1
        map: {
            url: "/url/to/map.jpg",
            repeat: [1, 1],
            offset: [0, 0],
            rotation: 0
        },
        mapAmount: 1
    },

    transparency: {
        factor: 0, // range 0-1
        map: {
            url: "/url/to/map.jpg",
            repeat: [1, 1],
            offset: [0, 0],
            rotation: 0
        },
        mapAmount: 1
    },

    emissive: {
        factor: 1, // range 0-1
        color: [0, 0, 0],
        map: {
            url: "/url/to/map.jpg",
            repeat: [1, 1],
            offset: [0, 0],
            rotation: 0
        },
        mapAmount: 1
    },

    normal: {
        map: {
            url: "/url/to/map.jpg",
            repeat: [1, 1],
            offset: [0, 0],
            rotation: 0
        },
        mapAmount: 1 // normal scale, can be negative (similar to inverted Y channel)
    },

    bump: {
        map: {
            url: "/url/to/map.jpg",
            repeat: [1, 1],
            offset: [0, 0],
            rotation: 0
        },
        mapAmount: 1 // bump scale, can be negative
    },

    clearcoat: {
        factor: 0, // range 0-1
        glossiness: 0, // range 0-1
    },

    environment: {
        factor: 1, // range 0-1
        localMode: true // if false, treat the reflection probe as infinite far away
    },

    sheen: {
        enable: false,
        color: [0, 0, 0],
        glossiness: 0, // range 0-1
    },

    side: 1, // 1: front-side, -1: back-side, 2: double-side
    alphaCutoff: 0, // range 0-1
    depthWrite: true,
    flatShading: false,
    excludeFromLightIntensity: false,
    excludeFromLightReflection: false,
    
    polygonOffset: {
        enable: false,
        factor: 0,
    }
}
createMtl Examples:
js
// Create mtl with red diffuse color
await viewer.createMtl({
    name: "Red Mtl",
    sku: "SKU_123",
    content: "This is a **Markdown** description of the material",

    diffuse: {
        color: [1, 0, 0],
    }
}, "MTL_SET_ID");

// Select new mtl right afterward
await viewer.selectMtl( "MTL_SET_ID", "Red Mtl" );

js
// Create mtl with diffuse map
await viewer.createMtl({
    name: "Mtl with diffuse map",

    diffuse: {
        map: {
            url: "https://example.com/diffuse.jpg",
            repeat: [2, 2], // custom repeat
        },
        mapAmount: 0.9
    },

    reflect: {
        color: [ 1, 1, 1 ]
    },

    glossiness: {
        factor: 0.9
    }
}, "MTL_SET_ID");

deleteMtl( mtlName )

Parameters:

  • mtlName string

Returns: Promise<boolean> - resolve true if mtl deleted successfully, resolve false if mtl not found

Description: Delete a material from scene, it will be removed from all mtlSet. This fn will not remove the material from any object it is currently assigned to. Useful in case you want to recreate a material with the same name.

INFO

If the material to delete is currently assigned to any object, it will still be assigned to that object after deletion, the deleted material will be removed from mtl set, will not shown in configurator options.

deleteMtl Examples:
js
// Delete mtl with name "Green Mtl"
const deleted = await viewer.deleteMtl('Green Mtl');
console.log(deleted); // true if deleted successfully, false if mtl not found

js
// Delete and re-create mtl with name "Green Mtl" with random glossiness, keep order of mtl in mtlSet
const mtlName = 'Green Mtl';
const mtlSetID = 'teapot';

const existingMtl = await viewer.getMtl(mtlName);
const origSelectedMtl = await viewer.getSelectedMtl(mtlSetID);

let origOrder;
if ( existingMtl ) { // only need to save/restore order if the mtl already exists in mtlSet
    origOrder = await viewer.getMtls(mtlSetID); // get original order of mtl in mtlSet before delete
    await viewer.deleteMtl(mtlName);
}

const randomGlossiness = Math.random();

await viewer.createMtl({
    name: mtlName,
    content: 'Current glossiness: ' + randomGlossiness,
    glossiness: {
        factor: randomGlossiness
    },
    diffuse: {
        color: [0, 1, 0]
    },
    reflect: {
        color: [1, 1, 1]
    }
}, mtlSetID);

if ( origSelectedMtl.name === mtlName ) {
    // if the deleted mtl was the selected mtl before delete, then we need to select the new mtl after created, otherwise the displayed mtl will still be the old mtl
    await viewer.selectMtl(mtlSetID, mtlName, { transition: 0 });
}

if ( origOrder ) {
    await viewer.reorderMtls(mtlSetID, origOrder); // restore original order before delete
}

Map

getMapTransform( mtlName, mapSlot )

Parameters:

  • mtlName string
  • mapSlot string - Valid values for mapSlot: "diffuse", "opacity", "transparency", "emissive", "glossiness", "reflect", "ior", "metalness", "normal", "bump", "any"

Returns: Promise< { repeat: [number, number], offset: [number, number], rotation: number } >

This fn will resolve null if the specified map slot is empty (doesn't have a map).
MapSlot "any" mean that it will get transform of one of any map this mtl using (prioritize diffuse map if available). If mtl doesn't have any map, fn will resolve null.

Examples:
js
const diffuseTransform = await viewer.getMapTransform( "MTL_NAME", "diffuse" );
if ( diffuseTransform != null ) {
    console.log(diffuseTransform);
    // logged values: { repeat: [1,1], offset: [0,0], rotation: 0 }
}

setMapTransform( mtlName, mapSlot, transform )

Parameters:

  • mtlName string
  • mapSlot string - Valid values for mapSlot: "diffuse", "opacity", "transparency", "emissive", "glossiness", "reflect", "ior", "metalness", "normal", "bump", "all"
  • transform object
    • repeat [number, number] - [x, y] (optional)
    • offset [number, number] - [x, y] (optional)
    • rotation number - in degree (optional)

Returns: Promise<void>

Examples:
js
// set repeat of diffuse map to 2x2
await viewer.setMapTransform( "MTL_NAME", "diffuse", {
    repeat: [3, 3]
} );

// set repeat and offset of all map (note that lightmap is not affected)
await viewer.setMapTransform( "MTL_NAME", "all", {
    repeat: [3, 3],
    offset: [0.5, 0.5]
} );

// x2 existing repeat of diffuse map
const existingTransform = await viewer.getMapTransform( "MTL_NAME", "diffuse" );
if ( existingTransform != null ) {
    await viewer.setMapTransform( "MTL_NAME", "diffuse", {
        repeat: [ existingTransform.repeat[0] * 2, existingTransform.repeat[1] * 2 ]
    } );
}

Hotspot

getHotspots( options )

Parameters:

  • options object (optional)
    • type string - Filter hotspots by type: "config" for configurator hotspots, "info" for info hotspots, "embed" for embed hotspots (default: null)

Returns: Promise< Array [HotspotInfo, ... ] >

Description: Get all hotspots in the scene

Examples:
js
// Get all configurator hotspots
const configHotspots = await viewer.getHotspots({ type: "config" });
console.log(configHotspots);

// Get all info hotspots
const infoHotspots = await viewer.getHotspots({ type: "info" });
console.log(infoHotspots);

// Get all types of hotspots
const allHotspots = await viewer.getHotspots();
console.log(allHotspots);

openHotspot( hotspotName, options )

Parameters:

  • hotspotName string
  • options object (optional)
    • goToView boolean - Go to the hotspot view after open (default: true)
    • transition number - Transition duration in ms (default: 3000)

Returns: Promise<void>

Description: Open a hotspot. Note: This promise resolve when transitionEnd


UI

openInfo()

Returns: Promise<void>

Description: Open the scene info popup (title, description)


isPopupOpen()

Returns: Promise< boolean >

Description: Check if any popup is currently opened.

INFO

Only 1 popup can be opened at one time. Open a new popup will auto close the current popup.


closePopup()

Returns: Promise<void>

Description: Close the currently opened popup (hotspot / info)


toggleHelpDialog()

Returns: Promise<void>


toggleSectionDialog()

Returns: Promise<void>


toggleCaptureDialog()

Returns: Promise<void>


toggleXRDialog()

Returns: Promise<void>


Camera

getView()

Returns: Promise< View >

Description: Get the current camera view. See View for all properties.


setView( view, options )

Parameters:

  • view View
    • position [x, y, z] - (optional) Camera position
    • target [x, y, z] - (optional) Camera target position. In Orbit mode, this is the center the camera look at and rotate around. In Walk mode, this is the point that the camera will look at.
    • fov number - (optional) Camera field of view in degree
    • mode string - (optional) Controls mode: "walk" or "orbit" (if not provided, will use current mode)
  • options object (optional)
    • transition number - Transition duration in ms (default: 2000)
    • force boolean - If true, disable user interaction during setView transition (default: false)

Returns: Promise<boolean> - Promise resolve true when transition end successfully, resolve false when transition is interrupted before finish.

Description: Move camera to a specific view.


captureImage( options )

Parameters:

  • options object (optional) All params of options are also optional
    • width number - Output image width in pixels (default: current canvas width)
    • height number - Output image height in pixels (default: current canvas height)
    • mimeType string - Output image mime type, valid values: 'image/png', 'image/jpeg', 'image/webp' (default: 'image/jpeg')
    • quality number - Image quality from 0 to 1 (default: 0.8, only used when mimeType is 'image/jpeg' or 'image/webp')
    • panorama boolean - Capture 360° panorama equirectangular image (default: false). Note: When capture 360, only width will be used, height will be ignored because height will always be equal to 1/2 of width
    • view View (optional) - Camera view to use for capture (if provided, will capture at this view, then reset camera to original view after capture)

Returns: Promise<string> - Base64 encoded image data URL

Description: Capture current view as an image.
The returned Promise resolves with a data URL that can be used as the src attribute of an img element or downloaded as a file.

Examples:
js
const imageDataURL = await viewer.captureImage();
const img = document.createElement('img');
img.src = imageDataURL;
document.body.appendChild(img);

requestVideoCapture( options )

Parameters:

  • options object
    • mimeType string - MIME type of the recorded video. Default: 'video/webm; codecs=vp8'. Valid values: 'video/webm; codecs=vp8' (low quality, high fps), 'video/webm; codecs=vp9' (high quality, low fps), 'video/webm', 'video/mp4', 'video/ogg', see more here)

Returns: Promise< Blob | null >

  • Resolve with a Blob object containing the recorded video in webm format when the recording is successfully stopped
  • Resolve with null if recording is not allowed by user.

Description:
Request video capture, browser will show a dialog that user have to manually click "Allow" to begin recording (this confirm dialog is a browser security restriction, it's not possible to start recording automatically without user's permission).

Examples:
js
// Example of capturing video and downloading it
async function captureAndDownloadVideo() {
    try {
        // Request video capture and wait for the blob
        const blob = await viewer.requestVideoCapture();
        
        if (!blob) {
            console.warn('Video capture was cancelled or failed');
            return;
        }

        // Create a download link for the video
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'video.webm'; // Default filename
        
        // Trigger download
        document.body.appendChild(a);
        a.click();
        
        // Cleanup
        document.body.removeChild(a);
        URL.revokeObjectURL(url);

    } catch (error) {
        console.error('Error capturing video:', error);
    }
}

// Usage
captureAndDownloadVideo();

Tour

playTour()

Returns: Promise<void>

Description: Start or resume tour autoplay
Note: Tour will be paused when user interact with scene (move, rotate, open hotspot...)


pauseTour()

Returns: Promise<void>


isTourPlaying()

Returns: Promise<boolean>


nextTourStep( options )

Parameters:

  • options object (optional)
    • transition number - Override transition duration (in ms)
    • force boolean - If true, disable user interaction during tour transition (default: false)

Returns: Promise<boolean> - Promise resolve true when transition end successfully, resolve false when transition is interrupted before finish.

Description: Go to next step in the tour.
When tour is at last step, calling nextTourStep will loop back to first step.


prevTourStep( options )

Parameters:

  • options object (optional)
    • transition number - Override transition duration (in ms)
    • force boolean - If true, disable user interaction during tour transition (default: false)

Returns: Promise<boolean> - Promise resolve true when transition end successfully, resolve false when transition is interrupted before finish.

Description: Go to previous step in the tour.
When tour is at first step, calling prevTourStep will loop back to last step.


goToTourStep( index, options )

Parameters:

  • index number
  • options object (optional)
    • transition number - Override transition duration (in ms)
    • force boolean - If true, disable user interaction during tour transition (default: false)

Returns: Promise<boolean> - Promise resolve true when transition end successfully, resolve false when transition is interrupted before finish.

Description: Go to a specific step in the tour.
When tour is at last step, calling goToTourStep will loop back to first step.


getCurrentTourStepIndex()

Returns: Promise<number>

Description: Get the index of the current step in the tour


getTourStepCount()

Returns: Promise<number>


getTourSpeed()

Returns: Promise<number>


setTourSpeed( multiplier )

Parameters:

  • multiplier number - Speed multiplier (default: 1)

Returns: Promise<void>

Description: Set the speed multiplier, all transition and wait time of tour will be multiplied by this value.


getTourStep( index )

Parameters:

  • index number

Returns: Promise< TourStep >

Description: Get a specific tour step.


getTourSteps()

Returns: Promise< Array< TourStep > >

Description: Get all tour steps.


setTourSteps( steps )

Parameters:

Returns: Promise<void>

Description: Replace the tour steps.

EVENTS

Events Usage Example:
javascript
viewer.on("playStateChange", (isPlaying) => {
    console.log("Viewer is now:", isPlaying ? "playing" : "paused");
});

viewer.on("hotspotOpen", ( hotspotInfo) => {
    console.log(`Hotspot "${hotspotInfo.name}" opened`);
});

playStateChange

Callback Parameters: ( isPlaying )

  • isPlaying boolean - Current play state of the viewer

hotspotOpen

Callback Parameters: ( HotspotInfo )


hotspotClose

Callback Parameters: void


selectMtlStart

Callback Parameters: ( object )

typescript
{
    mtlSetID: string,  // ID of the material set being changed
    name: string       // Name of the new material
}

selectMtlEnd

Callback Parameters: ( object )

typescript
{
    mtlSetID: string,  // ID of the material set that was changed
    name: string       // Name of the applied material
}

tourTransitionStart

Callback Parameters: ( object )

typescript
{
    fromStep: number,     // Index of the previous step
    toStep: number,       // Index of the target step
    transition: number    // Transition duration in ms
}

tourTransitionEnd

Callback Parameters: ( object )

typescript
{
    fromStep: number,     // Index of the starting step
    currentStep: number,  // Index of the current step
    completed: boolean   // Whether transition completed successfully or interrupted
}

tourPlayStateChange

Callback Parameters: ( object )

typescript
{
    isTourPlaying: boolean, // Whether tour is currently playing
    currentStep: number    // Current step index
}

TYPES

View

  • position [x, y, z] - Camera position
  • target [x, y, z] - Camera target position. In Orbit mode, this is the center the camera look at and rotate around. In Walk mode, this is the point that the camera will look at.
  • mode string - (optional) Controls mode: "orbit" or "walk"
  • fov number - (optional) Camera field of view in degree

TourStep

  • view View - Camera view for this tour step
  • rest number - (optional) How long to stay at this step in ms (if provided, will override global rest value)
  • duration number - (optional) Transition duration to this step in ms (if provided, will override global duration value)

MtlInfo

  • name string - Name of the material
  • sku string - SKU of the material
  • content string - Markdown content of the material

HotspotInfo

  • name string - Name of the hotspot
  • content string - Markdown content of the hotspot
  • type string - Type of the hotspot ("info", "config", "embed")
  • mtlSetID string - mtlSetID only available on hotspot type config