Add a 3D preview to a theme
In this tutorial you'll render a live 3D preview of a product and update it as the customer chooses a material. You'll attach the Spiff Commerce 3D preview service to a bundle, draw it on a canvas, and select a material variant from a list of buttons.
Before you begin
You'll need:
- A client and a bundle created within an activation. See Getting Started with the Core SDK or the theme getting started guide.
- A product whose workflow has a 3D model and a material step. Have its integration product ID and workflow ID to hand.
1. Install the preview package
yarn add @spiffcommerce/preview-3d@latest
2. Create the preview service
Create a single SpiffCommerce3DPreviewService and keep it for the life of the page. Creating one per render is expensive, and a preview service can only be associated with one bundle at a time.
import { SpiffCommerce3DPreviewService } from "@spiffcommerce/preview-3d";
const previewService = new SpiffCommerce3DPreviewService();
3. Add a canvas
The preview draws into a canvas element. Give it a size, because the canvas is what determines the size of the preview.
<div style="position: relative; width: 100%; height: 480px;">
<canvas id="preview" style="position: absolute; width: 100%; height: 100%; outline: none;"></canvas>
</div>
<div id="materials"></div>
4. Add a workflow experience to your bundle
Request a workflow experience for the product and add it to the bundle. Always use the list-based functions, even for one item, and await both calls.
const experiences = await client.getWorkflowExperiences([
{
type: "integration",
integrationProductId: "<Your integration product ID>",
workflowId: "<Your workflow ID>",
},
]);
await bundle.addWorkflowExperiences(experiences);
const workflowExperience = experiences[0];
5. Associate the bundle with the preview service
Call setPreviewService on the bundle. Every workflow experience in the bundle is injected into the preview service, and experiences you add or remove later are injected and ejected for you.
await bundle.setPreviewService(previewService);
6. Register the canvas and wait for the model
Register the canvas with the preview service. Nothing is drawn until a view is registered. Then wait for both the scene and the model to finish loading before showing the preview.
const canvas = document.getElementById("preview") as HTMLCanvasElement;
previewService.registerView(canvas);
await Promise.all([
previewService.getInitializationPromise(),
workflowExperience.getWorkflowManager().getModelContainer()?.getInitializationPromise(),
]);
// Frame the model once everything has loaded.
await previewService.animateToLastCameraFocus();
You should now see the product rendered on the canvas, and be able to orbit around it.
7. Let the customer pick a material
A material step lets the customer choose between texture assets. Find the material steps with getStepsByType, read the variants the customer can choose from, and call selectVariant when one is clicked. The preview updates by itself, because the workflow experience is already attached to it.
import { StepType } from "@spiffcommerce/core";
const materialStep = workflowExperience.getStepsByType(StepType.Material)[0];
const variants = await materialStep.getAvailableVariants();
const container = document.getElementById("materials")!;
variants.forEach((variant) => {
const button = document.createElement("button");
button.textContent = variant.getName();
button.addEventListener("click", async () => {
await materialStep.selectVariant(variant);
});
container.appendChild(button);
});
Click a button and the material on the model changes. A model step works the same way: get the steps with StepType.Model, then call selectVariant.
Only render steps that are currently active. Conditions in the workflow can show and hide steps as the customer makes choices. See Getting Active Steps.
8. Clean up
When your experience closes, unregister the canvas and eject the workflow experiences from the preview service.
previewService.unregisterView(canvas);
await bundle.setPreviewService();
Next steps
- Highlight materials when they are hovered and respond to clicks. See Enabling material highlighting.
- Play animations on the model. See Model Animations.
- Look at
apps/corporate-theme/src/generic/3DPreview/index.tsxfor a complete React implementation. - Read the 3D Product Previews guide for the full interface.