Usage with Frameworks
Dopple is designed to be framework-agnostic, and is compatible with sites built with any front-end JavaScript framework, such as React, Vue, or Svelte.
The examples below showcase the basics of creating a new component with Dopple, binding UI elements to handle product configuration dynamically, and component cleanup when the component is unmounted, but the rest of Dopple’s features — such as hotspots, snapshots, and augmented reality — are fully available as well using the same patterns.
Initialization
Section titled “Initialization”Depending on your use case, you may either hardcode the initialization options or pass them as props to your component. The examples below will show them passed as props.
It is recommended to initialize the DoppleXR
instance when your component first mounts.
import React, { useEffect, useRef, useState } from "react";import { DoppleXR } from "https://builds.dopple.io/packages/dopple-sdk@latest/dopple-sdk.js";
const DoppleComponent: React.FC<DoppleComponentProps> = () => { const doppleContainerRef = useRef<HTMLDivElement>(null); const [dopple, setDopple] = useState<DoppleXR | null>(null);
useEffect(() => { if (doppleContainerRef.current) { const doppleInstance = new DoppleXR({ container: doppleContainerRef.current, owner: "my-org", workspace: "my-workspace", projectName: "My Project", productVersion: "1", selection: {} }); setDopple(doppleInstance); } }, []);
return <div ref={doppleContainerRef}></div>;};
export default DoppleComponent;
<script setup lang="ts"> import { onMounted, useTemplateRef } from "vue"; import { DoppleXR } from "https://builds.dopple.io/packages/dopple-sdk@latest/dopple-sdk.js";
const doppleContainer = useTemplateRef<HTMLDivElement>("dopple-container"); let dopple: DoppleXR | null = null;
onMounted(async () => { dopple = new DoppleXR({ container: doppleContainer.value, owner: "my-org", workspace: "my-workspace", projectName: "My Project", productVersion: "1", selection: {} }); }); </script>
<template> <div ref="dopple-container"></div> </template>
<script lang="ts"> import { onMount, onDestroy } from 'svelte'; import { DoppleXR } from "https://builds.dopple.io/packages/dopple-sdk@latest/dopple-sdk.js";
let doppleContainer: HTMLDivElement; let dopple: DoppleXR | null = null;
onMount(() => { dopple = new DoppleXR({ container: doppleContainer, owner: "my-org", workspace: "my-workspace", projectName: "My Project", productVersion: "1", selection: {} }); });</script>
<div bind:this={doppleContainer}></div>
Product Configuration
Section titled “Product Configuration”Use the updateSelection()
method to update the 3D product’s configuration when a user selects a new option in your UI. See Product Configuration for more info.
In the examples below, “product-color” is a property that has been set in the product’s glTF file using the glTF Editor.
const updateColor = (event) => { dopple?.updateSelection({ "product-color": event.target.value, });};
<select onChange={updateColor}> {["red", "yellow", "green", "blue"].map((color) => ( <option key={color} value={color}> {color} </option> ))}</select>
function updateColor(event) { dopple?.updateSelection({ "product-color": event.target.value, });}
<select @change="updateColor"> <option v-for="color in ['red', 'yellow', 'green', 'blue']" :key="color" :value="color" > {{ color }} </option></select>
const colors = ["red", "yellow", "green", "blue"];
function updateColor(event) { dopple?.updateSelection({ "product-color": event.target.value, });}
<select on:change={updateColor}> {#each colors as color} <option value={color}> {color} </option> {/each}</select>
Unmounting
Section titled “Unmounting”Use the [Symbol.dispose]()
method to destroy the 3D product’s instance when the component is unmounted.
useEffect(() => { /* ... */ return () => { dopple[Symbol.dispose](); dopple = null; };}, []);
When using Dopple with Vue, call [Symbol.dispose]()
on the DoppleXR
instance during the component’s unmounted
lifecycle hook.
onUnmounted(() => { dopple?.[Symbol.dispose](); dopple = null;});
onMount(() => { /* ...*/ return () => { dopple?.[Symbol.dispose](); dopple = null; };});
Most frameworks will handle some resource cleanup automatically as they remove components from the DOM, but it is important to fully dispose of the Dopple instance to avoid memory leaks and clear up all loaded resources for the browser.
Full Code Examples
Section titled “Full Code Examples”import React, { useEffect, useRef, useState } from "react";
// 1. Import Doppleimport { DoppleXR } from "https://builds.dopple.io/packages/dopple-sdk@latest/dopple-sdk.js";
// 2. Define props to be used when creating the 3D product's instanceinterface DoppleComponentProps { defaultSelection: Record<string, string>; owner: string; projectName: string; version: string; workspace: number;}
const DoppleComponent: React.FC<DoppleComponentProps> = ({ defaultSelection, owner, projectName, version, workspace}) => {
// 3. Define a `<div>` element to contain the 3D product's canvas const doppleContainerRef = useRef<HTMLDivElement>(null); const [dopple, setDopple] = useState<DoppleXR | null>(null);
// 4. Initialize the 3D product once the component has been mounted useEffect(() => { if (doppleContainerRef.current) { const doppleInstance = new DoppleXR({ container: doppleContainerRef.current, owner, workspace, projectName, productVersion: version, selection: defaultSelection, });
setDopple(doppleInstance);
// 5. Cleanup the 3D product's instance when the component is unmounted return () => { doppleInstance[Symbol.dispose](); setDopple(null); }; } }, [owner, projectName, version, workspace, defaultSelection]);
// 6. Update the "product-color" property when the user selects a new color const updateColor = (event: React.ChangeEvent<HTMLSelectElement>) => { dopple?.updateSelection({ "product-color": event.target.value, }); };
return ( <div> <div ref={doppleContainerRef}></div> <label> <span>Product Color</span> <select onChange={updateColor}> {["red", "yellow", "green", "blue"].map((color) => ( <option key={color} value={color}> {color} </option> ))} </select> </label> </div> );};
export default DoppleComponent;
<script setup lang="ts"> import { onMounted, onUnmounted, useTemplateRef } from "vue";
// 1. Import Dopple import { DoppleXR } from "https://builds.dopple.io/packages/dopple-sdk@latest/dopple-sdk.js";
// 2. Define props to be used when creating the 3D product's instance const props = defineProps<{ defaultSelection: Record<string, string>; owner: string; projectName: string; version: string; workspace: number; }>();
// 3. Define a `<div>` element to contain the 3D product's canvas const doppleContainer = useTemplateRef<HTMLDivElement>("dopple-container");
// 4. Initialize the 3D product once the component has been mounted let dopple: DoppleXR | null = null; onMounted(async () => { dopple = new DoppleXR({ container: doppleContainer.value, owner: props.owner, workspace: props.workspace, projectName: props.projectName, productVersion: props.version, selection: props.defaultSelection, }); });
// 5. Cleanup the 3D product's instance when the component is unmounted onUnmounted(() => { dopple?.[Symbol.dispose](); });
// 6. Update the "product-color" property when the user selects a new color function updateColor(event: Event) { dopple?.updateSelection({ "product-color": (event.target as HTMLSelectElement).value, }); }</script>
<template> <div ref="dopple-container"></div> <label> <span>Product Color</span> <select @change="updateColor"> <option v-for="color in ['red', 'yellow', 'green', 'blue']" :key="color" :value="color" > {{ color }} </option> </select> </label></template>
<script lang="ts"> import { onMount, onDestroy } from 'svelte';
// 1. Import Dopple import { DoppleXR } from "https://builds.dopple.io/packages/dopple-sdk@latest/dopple-sdk.js";
// 2. Define props to be used when creating the 3D product's instance export let defaultSelection: Record<string, string>; export let owner: string; export let projectName: string; export let version: string; export let workspace: number;
// 3. Define a `<div>` element to contain the 3D product's canvas let doppleContainer: HTMLDivElement;
// 4. Initialize the 3D product once the component has been mounted let dopple: DoppleXR | null = null; onMount(() => { dopple = new DoppleXR({ container: doppleContainer, owner, workspace, projectName, productVersion: version, selection: defaultSelection, });
// 5. Cleanup the 3D product's instance when the component is unmounted return () => { dopple?.[Symbol.dispose](); dopple = null; }; });
// 6. Update the "product-color" property when the user selects a new color const colors = ["red", "yellow", "green", "blue"]; function updateColor(event: Event) { dopple?.updateSelection({ "product-color": (event.target as HTMLSelectElement).value, }); }</script>
<div> <div bind:this={doppleContainer}></div> <label> <span>Product Color</span> <select on:change={updateColor}> {#each colors as color} <option value={color}> {color} </option> {/each} </select> </label></div>