CDNS
https://cdn.3dcloud.io/mxt-3d-spin-viewer/8.5.0/Mxt3dSpin-8.5.0.min.js
https://cdn.3dcloud.io/mxt-3d-spin-viewer/8.5.0/Mxt3dSpin-8.5.0.js
If using from CDN, this creates a global object Mxt3dSpin
that has the Mxt3dSpinViewer and MxtAssetEnvironment
on it, so basic setup would be new Mxt3dSpin.Mxt3dSpinViewer
Browser Support
Chrome | 51+ | May 2016 |
Firefox | 54+ | Jun 2017 |
Edge | 14+ | Aug 2016 |
Safari | 10+ (except 15.0; 15.1+ supported) | Sep 2016 |
Opera | 38+ | Jun 2016 |
Basic Usage
Your Api Key will be provided to you by Marxent to provide secure access to a single-tenant cloud function.
Initialization
If you have multiple selectable sku on a page, can re-use the spin viewer like so:
const spinViewer = new Mxt3dSpinViewer();
await spinViewer.init({
apiKey: "yourCustomApiKey",
assetEnvironment: MxtAssetEnvironment.TEST or MxtAssetEnvironment.STAGING or MxtAssetEnvironment.PRODUCTION,
element: document.getElementById('my-3d-spin-element'),
//this section is optional; omit any lines for which you do not have custom icons
icons: {
close: yourCustomIcon,
collapse: yourCustomIcon,
download: yourCustomIcon,
expand: yourCustomIcon,
rotateLeft: yourCustomIcon,
rotateRight: yourCustomIcon,
zoomIn: yourCustomIcon,
zoomOut: yourCustomIcon
},
expandButton: {
position: 'right',
onExpand: putYourDesiredCallbackHere,
onCollapse: putYourOtherDesiredCallbackHere
},
}, {
//all of these options are optional and specific to 3D
camera : {
allowPanning: true,
// Rotation of Camera on X axis (Yaw) around the object in Radians
defaultAlpha: -Math.PI / 2, // -90 degrees
// Rotation of Camera on Y axis (Pitch) around the object in Radians
defaultBeta: Math.PI / 4, // 45 degrees
}
});
try {
await spinViewer.load(sku);
//then on selection of a different sku,
//await spinViewer.load(otherSku);
} catch(e) {
if(e.status == 404) {
//invalid sku
}
else if(e.status == 403) {
//bad API key
}
}
If you have an initial sku to load with your page, then you can provide that like so
const spinViewer = new Mxt3dSpinViewer();
try {
await spinViewer.init({
initialSku: sku,
apiKey: "yourCustomApiKey",
assetEnvironment: MxtAssetEnvironment.TEST or MxtAssetEnvironment.STAGING or MxtAssetEnvironment.PRODUCTION,
element: document.getElementById('my-3d-spin-element'),
//custom icons are optional
icons: {
close: yourCustomIcon,
collapse: yourCustomIcon,
download: yourCustomIcon,
expand: yourCustomIcon,
rotateLeft: yourCustomIcon,
rotateRight: yourCustomIcon,
zoomIn: yourCustomIcon,
zoomOut: yourCustomIcon
},
expandButton: {
position: 'right',
onExpand: putYourDesiredCallbackHere,
onCollapse: putYourOtherDesiredCallbackHere
},
}, {
//all of these options are optional and specific to 3D
camera : {
allowPanning: true
}
});
} catch(e) {
if(e.status == 404) {
//invalid sku
}
else if(e.status == 403) {
//bad API key
}
}
Support
See //docs/
Note that to see if rendering is supported, use spinViewer.isRenderingSupported()
prior to init to see. Returns {supported:boolean, reason?:string}
A Note on Initializing
If you are initializing in a div in a hidden context (display: none css), use the initialization option loadPaused: true.
Then, after displaying the div, call run() on the the spin viewer and rendererResize() in order to get the renderer to size properly.
Styling
The spin viewer will take up the full amount of space that its container allows it. So in the example above, style document.getElementById('my-3d-spin-element')
to be at the position and of the appropriate size that you want the mxt spin viewer to be
API
Mxt3dSpin.Mxt3dSpinViewer
init(commonOptions:MxtSpinsCommonOptions, options3D: Mxt3dSpinViewerOptions)
Only needs to be called once. Loads the renderer.
Due to current renderer limitations, the element that you load the renderer onto must NOT be display:none. It can be visibility:hidden. Next minor update of renderer should fix this. Renderer loads very fast, so not much performance loss in initializing on demand. However, do not need to re-initialize once initialized once.
Hiding the Spin Viewer
If you need to hide the spin viewer for any reason, you will want to either destroy the viewer and reinitialize it when shown again, or use the stop and run commands below.
Mxt3dSpin.Mxt3dSpinViewer.stop()
: This will stop the renderer, which would otherwise continuously undermine page performance when the spin viewer is hidden. Run this method when hiding the spin viewer, or it’s containing element.
Mxt3dSpin.Mxt3dSpinViewer.run()
: This can be used to start the render from a stopped state. Run this when a hidden spin viewer is shown again.
Mxt3dSpin.Mxt3dSpinViewer.destroy()
: This will destroy the spin viewer, allowing you to hide the containing element. When you want to show it again, initialize the spin viewer as you did in the beginning.
Babylon does not load properly when loaded onto display:none div
Common Options
export interface MxtSpinsCommonOptions {
/** private access key to spins */
apiKey: string;
/** The environment to pull assets from */
assetEnvironment: MxtAssetEnvironment;
/** Element to place the spins inside of */
element: HTMLElement;
/** Log level; defaults to WARN (3) */
logging?: log.LogLevel;
/** If an initial sku is provided, will auto load that sku after loading renderer */
initialSku?: string;
/** If initial child skus is provided (along with initial sku), will auto load those children sku after loading renderer */
initialChildSkus?: string[];
/** Size in pixels */
loadingIconSize?: number;
/** provide a CSS string */
loadingIconColor?: string;
/** provide a CSS string. If not provided, will default to transparent background */
loadingIconBackgroundColor?: string;
webArMode?: WebArMode;
webArOptions?: {
//by default, both USDZ and GLTF are turned on, this allows forcing USDZ off
disableUsdz?: boolean;
//by default, both USDZ and GLTF are turned on, this allows forcing GLTF off
disableGltf?: boolean;
//by default, scaling on USDZ is turned off. If you wish to enable, set this flag
enableScaling?: boolean;
};
/** Use the 3d preset views. The azimuth can be converted to the nearest image index */
presetViews?: MxtPresetViewOptions;>;> /** Custom Icons to override defualts */
icons?: MxtSpinsIconOptions;
/** provides a client-specific way of resolving skus from products, and vice-versa */
skuResolver?: IMxtSkuResolver | IMxtSkuDelegate;
/** Provide custom analytics, if empty then uses default mxt analytics */
analyticsPlugin?: SpinsAnalyticsPlugin;
/** Provide the ability to download a BOM from the toolbar */
downloadBomPlugin?: AbstractBomPlugin;
/** The position of this optional button is determined by accepted values, 'left' or 'right' */
expandButton?: {
onExpand?: any;
onCollapse?: any;
position?: string;
};
customText?: {
/** language should be an language ISO code (https://www.metamodpro.com/browser-language-codes)*/
[language: string]: any;
};
services?: {
environment?: MSServiceEnvironment;
};
}
export interface MxtSpinsIconOptions {
close?: string;
collapse?: string;
ellipses?: string;
presetView?: string;
download?: string;
expand?: string;
rotateLeft?: string;
rotateRight?: string;
zoomIn?: string;
zoomOut?: string;
}
export interface MxtPresetViewOptions="" {=""> /** Enabled by default, but can be turned off */
enabled?: boolean;
views?: T[];
}
expandButton
You may add an expand button to the 3D spin viewer.
Position
The expand/collapse button will appear on the far left of the button bar, by default. You may change its position to the far right side of the button bar by setting this to “right“.
onExpand
Provide a callback function, to be executed upon clicking the expand button.
onCollapse
Provide a callback function, to be executed upon clicking the collapse button.
3D Options
export interface Mxt3dSpinViewerOptions {
/** Zoom Delta - in meters; defaults to .3 */
zoomDelta?: number;
/** Rotate Delta - in radians; defaults to .3 */
rotateDelta?: number;
/** Multiplier; amount of space product takes up in screen by default; defaults to .75. */
fitToScreenMultiplier?: number;
/** Multiplier; How much you can zoom out past the initial zoom. Defaults to 1.33. A value of 1 would mean that the initial zoom distance is the farthest you can zoom out */
maxDistanceMultiplier?: number;
/** If true, init will NOT start the renderer. Use this if you want to create the spin viewer prior to actually displaying it. Use .run() to start the renderer */
loadPaused?: boolean;
/** Provide custom analytics, if empty then uses default mxt analytics */
analyticsPlugin?: Mxt3dSpinsAnalyticsPlugin;
/** Override if emissive materials used for lights are on in scene Default is TRUE **/
emissiveMatsOn: boolean;
/** provides client-specific way of modifying the load of a product */
loadModifiers?: IProductLoadModifierPlugin[];
hotspots?: {
invisibleOnLoad?: boolean;
hotspotMeshBasePath?: string;
hotspotMeshFilename?: string;
};
screenshot?: Mxt3dSpinsScreenshotOptions;
room?: RoomOptions;
presetViews?: MxtPresetViewOptions;>;> dimensions?: {
cameraPosition?: DataVector3;
cameraTarget?: DataVector3;
color?: IColor4;
enabled?: boolean;
unitType?: UnitType;
lineScale?: number;
arrowScale?: number;
visibleOnLoad?: boolean;
};
/** If not provided, default to == camera.allowPanning. If true, then will create guidance with panning guidance if panning is allowed, and guidance without panning if panning is not allowed*/
showGuidance?: boolean;
/** Advanced camera options */
camera?: {
allowPanning?: boolean;
defaultBeta?: number;
defaultAlpha?: number;
fieldOfView?: number;
lowerBetaLimit?: number;
upperBetaLimit?: number;
lowerAlphaLimit?: number;
upperAlphaLimit?: number;
embeddedReflectionCubeTextureUrls?: {
nx: string;
ny: string;
nz: string;
px: string;
py: string;
pz: string;
};
/** Lighting app config; only applicable when using spins in a stand-alone context; from within product config or other application, use manifest app config to set lighting config */
lighting?: Lighting;
};
/** Custom Icons to override defualts */
icons?: Mxt3dSpinIconOptions;
disableProgressiveLoad?: boolean; // bool to disable the progressive loading if true
}
export enum RoomChildType {
Portal = 0,
Window = 1,
Door = 2,
}
export interface RoomChildOptions {
childType: RoomChildType;
height: number;
width: number;
/** distance from edge of wall */
offset: number;
productId: string;
/** distance off floor, for windows only */
floorOffset?: number;
/** for doors only */
doorSwingBackwards?: boolean;
/** for doors only */
doorSwingDegrees?: number;
/** for doors only */
hingeSideRight?: false;
}
export interface RoomOptions {
width: number;
length: number;
floor?: string;
baseboard?: {
profile: string;
finish: string;
};
backWall?: {
height: number;
paint?: string;
children?: RoomChildOptions[];
};
sideWall?: {
height: number;
paint?: string;
children?: RoomChildOptions[];
};
}
export interface Mxt3dSpinIconOptions extends MxtSpinsIconOptions {
hotspotToggle?: string;
hotspotToggleActive?: string;
dimensions?: string;
dimensionsActive?: string;
panningGuidanceMouse?: string;
panningGuidanceMousePan?: string;
panningGuidanceDrag?: string;
panningGuidanceTwoFingerDrag?: string;
}
export interface Mxt3dSpinsScreenshotOptions {
/** By default, screenshot 1024x1024. May specify a different width, or set to -1 to use size on screen */
width?: number;
/** By default, screenshot 1024x1024. May specify a different height, or set to -1 to use size on screen */
height?: number;
/** By default, hi res screenshot 4096x4096. May specify a different width, or set to -1 to use size on screen */
hiResWidth?: number;
/** By default, hi res screenshot 4096x4096. May specify a different height, or set to -1 to use size on screen */
hiResHeight?: number;
waterMarkPlugin?: IMxtImageWatermarkPlugin;
downloadImagePlugins?: IMxt3dSpinDownloadImagePlugin[];
/** Enabled by default, but can be turned off */
enabled?: boolean;
imageFilename?: string | ((skus: string[], product: Product) => string);
}
lighting
You may pass in configurations to affect lighting in the viewer. These values will overwrite the default values in the appConfig.
_BackFaceCullingDisabled
: booleandefault value : false
_BackgroundColorMid
: {r:number,g:number;b:number} - the background color of the renderer. Values from 0 to 1.
load
Loads the given sku into the renderer. Will automatically delete anything previously loaded into renderer. In addition to loading a single product you can also swap out steps of the assembly using a sku and a step type.
loadSku(sku:string, configuration:{sku:string,stepType:string}[]): Promise<>
The above function can be used to replace things like arm pads on a chair, casters, and/or seat covers. Use this function by passing in the sku of the main product and then pass in an array of sku’s and step types that need to be replaced.
Another function is also provided for replacing product id. This works the same as the loadSku()
except with productId’s.
loadProductId(productId:string, configuration:{productId:string,stepType:string}[]): Promise>>
Additional helper methods
/**
* Show renderer debug panels
*/
showDebug():void;
/**
* Clear what is currently rendered
*/
clearView(): void;
/**
* Show camera controls
*/
showControls():void;
/**
* Hide camera controls
*/
hideControls(): void;
/**
* Hide expand button (pass in false to unhide)
*/
hideExpand(hide: boolean=true): void;
/**
* Reset camera to initial position
*/
resetCamera():void;
/**
* Set the cubemap textures for reflections off of the object
* See order below; its very important
* @param cubemapUrls PX/NY/PZ/NX/PY/NZ
*/
setEmbeddedReflectionCubemap(cubemapUrls:string[]): void;
/**
* Update the endpoint/api key (if implementing a multi tenant system)
*/
setNewEndpoint(endpoint:string, apiKey:string, clientId:string, appId:string, webArEndpoint?:string):void;
Lighting
If you would like to tweak the lighting, please contact us.
/**
* Properties used in the setup of three point lighting. Position is not meant for input, but is present for
* autocalculation based on direction.
*/
export class ThreeLightOptions {
_ConeAngle?: number; //Full angle in degress of Spot Light cone
_InnerAnglePercent?: number; //Percentage of full spot light angle over which the intensity falloff is greater
_DiffuseIntensity?: number; //Intensity of the diffuse color of the light (usually between 0 and 1)
_SpecularIntensity?: number; //Intensity of the specular contribution of the light (usually between 0 and 1)
_Color?: IColor3; //Linear color space color of the light, will be premultiplied by the _DiffuseIntensity
_DistanceMultiplier?: number; //Used to manipulate the distance that the light is shifted, relative to the center of the lighting target, in the inverse of the provided direction (or default).
_Position?: DataVector3; //This property is not meant for input. It exists for automatic calculation of a light’s position, based on _Direction from the target object in the scene.
_Direction?: DataVector3; //World space direction of the light in reference to the center of the lighting target.
_Range?: Number; //The max distance that the light is projected until it completely dissipates.
}
/**
* Interface for handling Lighting specific app data
* each property is optional since these are meant to act as potential overrides for existing default values
* meaning some of them may not exist when the data is read in
*/
export interface Lighting {
...,
_ThreeLightSetup: {
_EnableThreeLightSetup: boolean;
_KeyLight?: ThreeLightOptions;
_FillLight?: ThreeLightOptions;
_BackLight?: ThreeLightOptions;
};
// if true, enables antialiasing for iOS devices (this implies Apple fixed an issue in iOS 15.4 or we upgraded to BabylonJS 5.0)
_EnableIOSAntialiasing?: boolean;
,...
}