Augmented Reality
Dopple Visual allows 3D products to be viewed in augmented reality (AR) on a user’s device, directly within the web browser.
Before launching an AR experience, an AR scene needs to be generated by Dopple in the cloud, then presented to the user by one of two methods:
- Displaying a QR code for the user to scan, linking to the AR experience — ideal for when the user is on a device that does not support augmented reality.
- Showing a “Launch AR” button for the user to click — ideal for when a user is on an AR-supported device, such as a smartphone or tablet.
:::caution Note AR scene generation may be time consuming and computationally heavy in certain cases. For the best user experience, it is strongly recommended to keep track of when users make changes to their product’s configuration so that new AR scenes and QR codes only need to be generated for new configurations, and not repeated for existing configurations.
See the tracking configuration changes section below for more info. :::
Generating the AR scene
Section titled “Generating the AR scene”To create an AR scene of the current product configuration, use the create
method available on Atlatl.ARScene
, passing in the Visual instance as its only parameter.
const renderCanvas = document.getElementById('my-canvas')const visual = new Atlatl.Visual(renderCanvas)
const createArScene = async () => { const arScene = await Atlatl.ARScene.create(visual)}
This will begin the process of converting the user’s scene (handled for you in the cloud by Dopple) into an AR scene that can be launched within their web browser. Once the AR scene has finished generating, a QR code linking to the AR experience or a button to launch the experience directly may then be displayed to the user.
Creating and displaying the QR code
Section titled “Creating and displaying the QR code”To generate a QR code, an HTML <img>
element needs to first be created in the DOM. This may be done either by adding an <img>
tag to your HTML document, or using JavaScript (for example, document.createElement('img')
).
<img id="qr-code-img" alt="QR code" />
This image’s src
attribute will be populated by the base64 data returned by the generateQRCode
method on the Atlatl.ARScene
.
const createQrCode = async () => {
// Generate a new AR scene with the current product configuration const arScene = await Atlatl.ARScene.create(visual)
// Generate a PNG image of the QR code onto the page const qrCodeData = 'data:image/png;base64,' + arScene.generateQRCode() document.getElementById('qr-code-img').setAttribute("src", qrCodeData)}
Launching AR
Section titled “Launching AR”To launch the AR experience directly, call the launchAR
method on the Atlatl.ARScene
after the AR scene has been generated.
const launchAr = async () => {
// Generate a new AR scene with the current product configuration const arScene = await Atlatl.ARScene.create(visual)
// Launch the AR experience if (confirm('Warning! You are about to leave this page. To continue to the AR experience, select "OK".')) { arScene.launchAR() }}
The launchAr()
function may then be triggered anytime after Dopple Visual has loaded, such as when the user clicks a <button>
on the webpage.
<button id="launch-ar">Launch AR</button>
document.getElementById('launch-ar').addEventListener('click', () => { launchAr()})
Detecting AR-supported devices
Section titled “Detecting AR-supported devices”If the user is currently on a device that supports AR, it may be a desirable user experience to display only the “Launch AR” button and not the QR code (or vice versa if the user is on a non-AR device).
One method is to use a regular expression to check the user agent of the browser for known mobile devices, since these devices will typically have AR capabilities.
const isMobileDevice = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
Then, if isMobileDevice
returns true
, the launch button or the QR code image may be shown or hidden accordingly.
if (isMobileDevice) { // Hide the QR code (show only the Launch AR button) document.getElementById('qr-code-img').style.display = 'none'} else { // Hide the Launch AR button (show only the QR code) document.getElementById('launch-ar').style.display = 'none'}
Showing a loader while AR generates
Section titled “Showing a loader while AR generates”Since the AR scene creation process may take a few seconds, it is recommended to show a loading screen or indicator to the user while they wait.
A custom loading screen may be created by placing a “loading” message in the page’s HTML, then conditionally showing or hiding the message depending on the loading state of the AR scene.
<p id="ar-loading-screen"> Your AR experience is loading... <span id="ar-loading-percent">0%</span> <progress id="ar-progress-bar" max="100" value="0"></progress></p>
const renderCanvas = document.getElementById('my-canvas')const visual = new Atlatl.Visual(renderCanvas)
const createArScene = async () => { // Show the "loading" message as the AR scene generates // highlight-next-line document.getElementById('ar-loader').style.display = ''
// Generate the AR scene const arScene = await Atlatl.ARScene.create(visual, onProgress(e) { console.log(e.currentStep + '/' + e.totalSteps + ' (' + e.overallProgress * 100 + '%)') } )
// Hide the "loading" message once the AR scene has finished generating // highlight-next-line document.getElementById('ar-loader').style.display = 'none'}
Additionally, ARScene.create()
also accepts an onProgress()
callback function which gives access to the current step, total number of steps, and overall progress during the AR generation process.
const arScene = await Atlatl.ARScene.create(visual, {
// Get the current step, total number of steps, and overall progress of the AR scene generation onProgress(e) { console.log(e.currentStep) console.log(e.totalSteps) console.log(e.overallProgress * 100 + '%') }})
Tracking configuration changes
Section titled “Tracking configuration changes”As mentioned earlier, AR scene generation is usually a time consuming process. Depending on the complexity of the product and the scene, this could take upwards of 10 or 20 seconds. To help mitigate this, avoid calling Atlatl.ARScene.create()
for repeat views of the same product configuration in AR.
One method is to wrap your Atlatl.ARScene.create()
functionality in a conditional statement that first checks to see if the product configuration has been changed since the last time it was called.
// Default to true so that a new AR scene may be generated on the first trylet configHasChanged = true
// Generate the AR scene only if the product configuration is newif (this.configHasChanged) { const arScene = await Atlatl.ARScene.create(visual)
// Set back to false after AR scene creation to prevent repeat creations of an unchanged product configHasChanged = false}
Then, when the user makes an update to the product’s configuration, such as when using setValue()
(see Updating the product using setValue()
), the configHasChanged
variable can be set back to true
to allow your code to re-generate the AR scene with the updated configuration.
// Update the product's configuration when a button is clickeddocument.getElementById('my-button').addEventListener('click', () => { myProduct.setValue('some_property', 'some_value')
// Set to true to allow for a new AR scene to be generated // highlight-next-line configHasChanged = true})
Full code example
Section titled “Full code example”<html lang="en"> <head> <meta charset="utf-8"> <title>My Page</title> <!-- Link to the Visual Component's scripts --> <script src="https://builds.dopple.io/atlatl-visual-api/releases/current/index.js" defer></script> <!-- Link to custom scripts --> <script src="scripts.js" defer></script> </head> <body> <!-- Canvas to render the 3D scene to --> <canvas id="my-canvas"></canvas> <div> <button id="generate-qr">Generate QR Code</button> <button id="launch-ar">Launch AR</button> <img id="qrCodeOutput" alt="" /> </div> </body></html>
// Initialize some global variables for the Visual instancelet visual;let myProduct;let namespace = 'demo-assets';let name = 'arrow_shoe';
// Initialize Dopple Visual when the document loadswindow.addEventListener('load', async () => {
// Initialize the Visual instance on the page's canvas const renderCanvas = document.getElementById('my-canvas') visual = new Atlatl.Visual(renderCanvas)
// Replace with your client ID here await visual.initClient('a1a1a1a1-b2b2-c3c3-d4d4-e5e5e5e5e5e5')
// Create and load the ProductTemplate const template = new Atlatl.ProductTemplate(visual, namespace, name) await template.load()
// Create the Product instance myProduct = new Atlatl.Product(template)
// Hide the loading screen to show the product once the product is ready await myProduct.ready() visual.loadingScreen.hide()})
// Initialize some global variables for the AR featurelet arScenelet arScenePromiselet configHasChanged = true
// Create a new AR scene, generate a QR code image, and display the Launch AR buttonconst createNewArScene = async () => {
// Create a new AR scene arScene = await Atlatl.ARScene.create(visual, { onProgress(e) {
// Show the AR loading % document.getElementById('ar-loading-percent').innerHTML = e.overallProgress * 100 + '%'
// Update the AR loading progress bar document.getElementById('ar-progress-bar').value = e.overallProgress * 100 } })
// Generate a PNG image of the QR code onto the page const qrCodeData = 'data:image/png;base64,' + arScene.generateQRCode() document.getElementById('qr-code-img').setAttribute('src', qrCodeData)
// Display the AR container with the QR code and Launch AR button document.getElementById('ar-container').style.display = ''
// Show/hide the QR code or "Launch AR" button depending on user's device type const isMobileDevice = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) if (isMobileDevice) { document.getElementById('qr-code-img').style.display = 'none' } else { document.getElementById('launch-ar').style.display = 'none' }}
// Initialize the AR scene when the "View in AR" button is clickeddocument.getElementById('view-in-ar').addEventListener('click', () => {
// Call createNewArScene() to generate a new AR scene ONLY if the product configuration has been updated if(configHasChanged) { createNewArScene()
// Set to false to prevent repeat AR scene creations of an unchanged product configHasChanged = false }})
// Launch the AR experience when the "Launch AR" button is clickeddocument.getElementById('launch-ar').addEventListener('click', () => { if (confirm('Warning! You are about to leave this page. To continue to the AR experience, select "OK".')) { arScene.launchAR() }})
document.getElementById('change-product-config').addEventListener('click', () => { myProduct.setValue('some_property', 'some_value')
// Set to true to allow for a new AR scene to be created configHasChanged = true})