9.1.0 Modular Configurator Manual

Prev Next

CDN

Global variable MxtModularConfigurator is created, access classes from there, i.e.

Exported classes are shown at @mxt/mxt-modular-config

const config = new MxtModularConfigurator.MxtModularConfigurator(options);

Basic Usage Example

<!DOCTYPE html>
<html>
<head>
    <title>MxtModularConfigurator Example</title>
    <link rel="stylesheet" href="https://cdn.3dcloud.io/mxt-modular-config/9.1.0/MxtModularConfigurator-9.1.0.css">
    <style>
        marxent-viewer {
            width: 100%;
            height: 100%;
            position: absolute;
        }
    </style>
</head>
<body>
    <marxent-viewer id="marxent-3d-viewer"> </marxent-viewer>
    <script src="https://cdn.3dcloud.io/mxt-modular-config/9.1.0/MxtModularConfigurator-9.1.0.min.js"></script>
    <script>
        async function startModular(element_name) {
            const parentElement = document.getElementById(element_name);
            try {
                const options = {
                    apiKey: 'insert your api key here',
                    element: parentElement,
                    assetEnvironment: "Stage",
                    primaryColor: {
                        r:255, g:0, b:0
                    }
                };
                const config = new MxtModularConfigurator.MxtModularConfigurator(options);
                await config.init();
            } catch(e) {
                    console.error(e);
            }    
        }
        startModular('marxent-3d-viewer');
    </script>
</body>
</html>

Additional requirements and notes for Implementation

You must have the following styles defined for the html element you are initializing the modular configurator inside:

  • width (we recommend at least 80%)

  • height (we recommend at least 80%)

  • position:  absolute

Your account team may give you a custom URL to retrieve your javascript and css, replace those in the above example.

Use assetEnvironment: "Stage" for your test or staging environment

Use assetEnvironment: "Active" for your production environment

Destruction

To destroy and clean up a modular config, use the destroy function on the MxtModularConfigurator class

Advanced Options

Load product on initial load

defaultProductLoad? : {
    product?: Product;
    sku?: string;
    productId?: string;
    skuAndAssembly?: {sku:string, assembly:{sku:string, stepType:string}[]};
    productIdAndAssembly?: {productId:string, assembly:{productId:string, stepType:string}[]};
    productConfigSku?: {productId:string, skuOverride:string[]};
}

You can provide information as to what should initially load in the scene. If you provide any of this information, it will skip the inspiration UI and go straight to 3d, loading the starting product specified. There are several ways to do this (listed in priority order, so if you happen to provide multiple, this is the order that they are evaluated):

  • product - provide a fully enumerated Marxent product object

  • productId - Provide a Marxent product id. Loads the default configuration options on that product

  • sku - provide the sku of the product. If there are multiple products with the same sku, it uses the first one. IF you have a 3d cloud product configurator for this product, do NOT use this option, use productConfigSku

  • productConfigSku - provide the Marxent product id for your 3d cloud product configurator product. Additionally, provide the sku(s) that it should resolve to. This is only necessary if you are attempting to load the non-default sku on the product.

  • productIdAndAssembly - Provide a Marxent product id, as well as the Marxent product ids of child steps to provide a custom configuration of the product. IF you have a 3d cloud product configurator for this product, do NOT use this option, use productConfigSku

  • skuAndAssembly - provide the sku of the product, as well as the skus of child steps to provide a custom configuration of the product. If there are multiple products with the same sku, it uses the first one. IF you have a 3d cloud product configurator for this product, do NOT use this option, use productConfigSku

Customize CTA Buttons

/**
  * A list of menu itmes can that be set / moved from the main menu
  * or moved into the Call to Action footer. default: Share(non-CTA) Add To Cart (CTA)
  */
menuActions?: {
    action: MenuAction;
    /** Which Menu the Action should be moved to
      * Defaults to Hamburger Main Menu
      * combined with hide == true, this is the menu to remove from
      */
    type?: MenuType;
    /**
      * Will hide a menu item from its original place
      * combined with type to say which menu to be hiddedn
      * if type == null, all items of this action will be removed
      */
    hide?: boolean;
    order?: number;
    /**
      * If the action should be moved into the Footer as the CTA
      */
    cta?: boolean;
    /**
      * Acts as pass through for metadata
      * @example [["menuPosition", "right"]]
      */
    metadata?: [string, string][];
}[];

You can provide a list of menuActions to move/hide various menu items through out the app.
Example below would be to…

  • move the SIF download into the Sidebar Footer’s Call To Action button

  • move the Add To Cart into the Desktop bottom bar.

  • hide the Share non-CTA button from the footer

"menuActions": [
    {"action": "DOWNLOAD_SIF", "cta": true},
    {"action": "ADD_TO_CART", "type": "MODULAR_CONFIG_DESKTOP_BOTTOM_BAR", "order": 10, "metadata": [["menuPosition", "right"]]},
    {"action": "SHARE_PROJECT", "hide": true}
]

URL Params for initial product load

There is an exported enum UrlParams for your usage. Details:

UrlParams.PRODUCT_ID = "productId"

export enum UrlParams {
    PRODUCT_ID = 'productId',
    PRODUCT_ASSEMBLY = 'assembly',
    SKU = 'sku',
}

Map from url params to runtime config options:

Runtime Option

URL Params

productId

productId

sku

sku

productConfigSku

productId + sku (can have multiple sku url params)

productIdAndAssembly

productId + assembly (place entire assembly JSON as string in url param)

skuAndAssembly

sku + assembly (place entire assembly JSON as string in url param)

product

CANNOT be provided via url param

Setting up multiple categories or families of products

If you have a multiple sets of products that you want to show in your Modular Configurator, you may want to ask us to split up the data. We will do so using a construct called Menu data. Each product set will be grouped under a menu label, or id. We will provide you with the menu label for each product set and it should be used in your initialization options, i.e.

const options: MxtModularConfiguratorOptions = {
        apiKey: 'insert your api key here',
        ...
        menuId: 'the family menu id'

Add to cart callback

const options: MxtModularConfiguratorOptions = {
        apiKey: 'insert your api key here',
        ...
        addToCartScreenshot: {
          /** name of pre-set camera for screenshots
          * if undefined, will create and set a front-facing camera
          * if null will use the active camera (what the user sees)
          */
          type?: string | null;
          /** width of the screenshot
          * if given a height but no width the aspect ratio of the canvas will be preserved
          * width = height * aspect ratio
          * @default 2048
          */
          width?: number;
          /** height of the screenshot
          * if given a width but no height the aspect ratio of the canvas will be preserved
          * @default width / aspect ratio
          */
          height?: number;
          mimeType?: string;
          clearColor?: IColor4;
        },
        addToCart: async (data: {sourceURL: string; projectShareCode: string; bomProducts: BomProduct[]; screenshot: string}) => {
            //do whatever you want with the products in the scene
            //send them to an API to add to a cart, create a modal to view the products, etc
        },
        

bomProducts Object Schema (“Contact your account team for specific fields to use”)

bomProduct [
  {
    "availability": true,
    "availabilityEnum": null,
    "availabilityStatus": null,
    "availabilityString": "",
    "currency": "$",
    "parent": null,
    "price": 0,
    "priceState": 1,
    "product": {
      "sku": "",
      "productId": "",
      "clientProductId": "",
      "name": "",
      "description": ""
    },
    "productId": "",
    "qty": 1,
    "sku": "",
    subProducts[]:{}
  }
]
priceState enum:
    NO_PRICE = 0, //dont show price at all
    VALID = 1, //use price
    NOT_APPLICABLE = 2, //N/A as price
availabilityEnum:
    UNKNOWN = 'unknown'
    DISCONTINUED = 'discontinued'
    AVAILABLE = 'available'
    OUT_OF_STOCK = 'outOfStock'

Customizing screenshot extension/filename

const options: MxtModularConfiguratorOptions = {
        apiKey: 'insert your api key here',
        ...
        screenshot: {
            imageExtension: 'jpeg',
            screenshotDownloadName: (products) => {
                return `Mod Config Example (${products.length} products)`;
            },
        },
        

Customizing screenshot resolution

By default, the Screenshot tool renders an image at the size of the on-screen display. To increase or decrease the resolution (and therefore, the detail) of the image, you can specify a multiplier, which will mutliply the size of the rendered image download.

Beware that mutliplying the dimensions may also change its download size by the square of the multiplier, depending on the filetype extension that is defined. For example, a multiplier of 2 may increase the file size by 4.

const options: MxtModularConfiguratorOptions = {
        apiKey: 'insert your api key here',
        ...
        screenshot: {
            resolutionMultiplier: 2 // double the resolution
            
            /** If you define high and low resolution width and height below you do not need these
            /** width of the screenshot
            * if given a height but no width the aspect ratio of the canvas will be preserved
            * width = height * aspect ratio
            * @default Desktop: 4096
            * @default Mobile: height / aspect ratio
            */
            width?: number;
            /** height of the screenshot
            * if given a width but no height the aspect ratio of the canvas will be preserved
            * @default Desktop: width / aspect ratio
            * @default Mobile: 2048
            */
            height?: number;
          
            screenshotDownloadName?: (products: Product[]) => string;
            
            highResolution?: {
              width?: number;
              height?: number;
            }
            lowResolution?: {
              width?: number;
              height?: number;
            }
  
            dimensionLineLabelOptions?: {
              /**
              * @example {r: 255, g: 255, b: 255, a: 255}
              * #ffffff
              * rgba(255, 255, 255, 1)
              */
              background?: IColor4 | string;
              /**
              * @example {r: 255, g: 255, b: 255, a: 255}
              * #ffffff
              * rgba(255, 255, 255, 1)
              */
              color?: IColor4 | string;
              borderRadius?: number;
              /**
              * single value for all padding
              * if top/bottom is set but the other is missing, will use the same value
              * same with left/right
              * @example {top: 10, left: 5} == {top: 10, bottom: 10, left: 5, right: 5}
              */
              padding?: number | {
                  top: number;
                  right: number;
                  bottom: number;
                  left: number;
              };
              fontSizeScale?: (distance: number, meshId: string, position: IVector3) => number;
            }
        },

Fullscreen

We have a fullscreen button that hides the UI and makes the rendering canvas take up our entire element.

If you need to do additional work on your page to make the parent element of the modular configurator take up the entire screen, hook into the following callbacks:

const options: MxtModularConfiguratorOptions = {
        apiKey: 'insert your api key here',
        ...
        callbacks: {
            onFullscreenEnter: () => console.info('onFullscreenEnter callback'),
            onFullscreenExit: () => console.info('onFullscreenExit callback'),
        }
        

Availability

Availability defaults to not shown, pricing defaults to shown.

Example of non-defaults:

const options: MxtModularConfiguratorOptions = {
        apiKey: 'insert your api key here',
        ...
        pricingAndAvailability: { 
            showAvailability: true,
            hidePricing: true
        },

All Options

export interface MxtModularConfiguratorOptions {
    /** private access key to spins */
    apiKey: string;
    /** The environment to pull assets from */
    assetEnvironment: MxtAssetEnvironment;
    /** Element to place the spins inside of */
    element: HTMLElement;
    /** ID to match menu data; use this if you have multiple different categories of products and you need to specify which one */
    menuId?: string;
    /** Log level; defaults to WARN (3) */
    logging?: log.LogLevel;
    customText?: {
        /** language should be an language ISO code (https://www.metamodpro.com/browser-language-codes)*/
        [language: string]: any;
    };
    customIcons?: {
        place?: MxtModularConfigPlacingIcons;
    };
    services?: {
        environment?: MSServiceEnvironment;
    };
    plugins?: IPlugin[];
    /** 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 1.2 (leaves 20% of space on edges). */
    fitToScreenMultiplier?: number;
    /** Multiplier; How much you can zoom out past the initial zoom. Defaults to 2. 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;
    /** provides client-specific way of modifying the load of a product */
    loadModifiers?: IProductLoadModifierPlugin[];
    /** Unit type to display values in */
    unitType?: UnitType;
    /** 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;
    };
    // Sets the line-height of the description for product detail on mobile
    productDetail?: { descriptionLineHeight?: number };
    addToCart(products: BomProduct[]): Promise;>;>    
    addToCartScreenshot?: {
        /** name of pre-set camera for screenshots
         * if null, will create and set a front-facing camera
         */
        type?: string | null;
        /** width of the screenshot
         * if given a height but no width the aspect ratio of the canvas will be preserved
         * width = height * aspect ratio
         * @default 2048
         */
        width?: number;
        /** height of the screenshot
         * if given a width but no height the aspect ratio of the canvas will be preserved
         * @default width / aspect ratio
         */
        height?: number;
        mimeType?: string;
        clearColor?: IColor4;
    };
    /**
     * Return the name to give the screenshot
     * @param products
     */
    screenshot?: MxtModularConfigScreenshotOptions;
    
    share?: {
        /** by default, the share URL matches the URL of the window. If you are using the modular config in an iframe, you may want to provide a different base URL */
        baseShareUrl?: string | (() => string);
    };
    
    searchAndBrowse?: MxtModularConfigSearchAndBrowseOptions;
    
    /**
     * Code to load into the scene on startup
     */
    initialProjectCode?: string;
    /**
     * disable the progressive loading if true
     */
    disableProgressiveLoad?: boolean;
    /** Primary color, rgb 0->255 */
    primaryColor?: IColor3;
    callbacks?: {
        onFullscreenEnter?: () => void;
        onFullscreenExit?: () => void;
    };
    
    disableCollision?: boolean;
    
    responsive?: {
        minDesktopWidth?: number;
    };
    pricingAndAvailability?: {
        hidePricing?: boolean;
        showAvailability?: boolean;
    };
    font?: {
        /** Reflects CSS font-family, assuming values are browser-supported or already imported */
        family?: string;
        /** RGB values 0-255 */
        color?: IColor3;
        /** Number values are treated as pixels, otherwise as string unit values */
        sizeHeaderLg?: string | number;
        sizeHeader?: string | number;
        sizeSubHeader?: string | number;
        sizeBodyLg?: string | number;
        sizeBody?: string | number;
        sizeBodySm?: string | number;
        sizeBodyXs?: string | number;
    };
    
    inspirationStart?: {
        /** Label/ID to match inspiration filter id, will start app with that inspiration filter  */
        filter?: string;
        /** Label/ID to match inspiration hero id, will start app with that inspiration hero loaded  */
        hero?: string;
    };
    
    disableOverallDimensions?: boolean;
}
export interface MxtModularConfigPlacingIcons {
    /** Icon to use in bubble for adding a product onto a surface */
    addToSurface?: string;
    /** Icon to use in bubble for adding a product onto the floor */
    addToFloor?: string;
    /** Icon to use in bubble for attaching a product to a sibling */
    placeSibling?: string;
    /** Icon to use in bubble for attaching a product between two siblings */
    insertSibling?: string;
    /** Icon to use in bubble when the normal icon for attaching a product to a sibling is hidden from the camera */
    occludedSibling?: string;
}
export interface MxtModularConfigScreenshotOptions {
    screenshotDownloadName?: (products: Product[]) => string;
    imageExtension?: 'jpeg' | 'png' | 'jpg';
    resolutionMultiplier?: number;
}
export interface MxtModularConfigSearchAndBrowseOptions {
    /**If true, the loading screen only covers the search and browse menu itself rather than the full screen */
    legacyLoadingScreen?: boolean;
}

Client Customizations

Initialization Options

  • Option parameters passed in on initialization (? indicates it is optional)

    • assetEnvironment: MxtAssetEnvironment

      • The environment to pull assets from

    • element: HTMLElement

      • HTML element on website to place the spins inside of

    • menuId?: string

      • ID to match menu data; use this if you have multiple different categories of products and you need to specify which one (Marxent Account team can provide ID to use)

    • customIcons?: {  place?: MxtModularConfigPlacingIcons; };

      • Pass in object that defines svg icons to override platform defaults

        • addToSurface?: string;  /**Icon to use in bubble for adding a product onto a surface */  

        • addToFloor?: string;  /** Icon to use in bubble for adding a product onto the floor */

        • placeSibling?: string;  /** Icon to use in bubble for attaching a product to a sibling */

        • insertSibling?: string;  /** Icon to use in bubble for attaching a product between two siblings */

        • occludedSibling?: string;  /** Icon to use in bubble when the normal icon for attaching a product to a sibling is hidden from the camera */

    • zoomDelta?: number;

      • Zoom Delta - in meters; defaults to .3

    • rotateDelta?: number;

      • Rotate Delta - in radians; defaults to .3

    • fitToScreenMultiplier?: number;

      • Multiplier; amount of space product takes up in screen by default; defaults to 1.2 (leaves 20% of space on edges).

    • maxDistanceMultiplier?: number;

      • Multiplier; How much you can zoom out past the initial zoom. Defaults to 2. A value of 1 would mean that the initial zoom distance is the farthest you can zoom out

    • loadPaused?: boolean;

      • 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

    • loadModifiers?: IProductLoadModifierPlugin[];

      • provides client-specific way of modifying the load of a product

    • unitType?: UnitType;

      • Unit type to display values in

    • Camera?:

      • allowPanning?: boolean;

        • Allow camera panning not just rotation, default true

      • defaultBeta?: number;

        • Pitch of camera in radians (0 is straight ahead, default is Pi/4)

      • defaultAlpha?: number;

        • Heading of camera in radians (0 is straight ahead, default is -Pi/2)

      • fieldOfView?: number;

        • In radians (default is 0.3, about 17.19 degrees)

      • lowerBetaLimit?: number;

        • Lower limit of pitch that the camera allows in radians

      • upperBetaLimit?: number;

        • Max pitch the camera will allow in radians

      • lowerAlphaLimit?: number;

        • Min heading the camera will allow in radians

      • upperAlphaLimit?: number;

        • Max heading the camera will allow in radians

    • font?:

      • family?: string;

        • Reflects CSS font-family, assuming values are browser-supported or already imported

      • color?: IColor3;

        • RGB values 0-255

      • sizeHeaderLg?: string | number;

        • Number values are treated as pixels, otherwise as string unit values

      • sizeHeader?: string | number;

        • Number values are treated as pixels, otherwise as string unit values

      • sizeSubHeader?: string | number;

        • Number values are treated as pixels, otherwise as string unit values

      • sizeBodyLg?: string | number;

        • Number values are treated as pixels, otherwise as string unit values

      • sizeBody?: string | number;

        • Number values are treated as pixels, otherwise as string unit values

      • sizeBodySm?: string | number;

        • Number values are treated as pixels, otherwise as string unit values

      • sizeBodyXs?: string | number;

        • Number values are treated as pixels, otherwise as string unit values

    • productDetail?:

      • descriptionLineHeight?: number

        • Sets the line-height of the description for product detail on mobile

    • addToCart(products: BomProduct[]): Promise<>

      • Add to cart function for callback when user clicks add to cart button in configurator

    • screenshot?: MxtModularConfigScreenshotOptions;

      • Return the name to give the screenshot* @param products

    • initialProjectCode?: string;

      • Code to load into the scene on startup

    • disableProgressiveLoad?: boolean;

      • disable the progressive loading if true, model will only appear once fully loaded

    • primaryColor?: IColor3;

      • Primary color, rgb 0->255

    • Callbacks?:

      • onFullscreenEnter?: () => void;

      • onFullscreenExit?: () => void;

    • Responsive?:

      • minDesktopWidth?: number;

    • pricingAndAvailability?:

      • hidePricing?: boolean;

      • showAvailability?: boolean;

    • inspirationStart?:

      • filter?: string;

        • The inpiration filter id/name. This causes the modular configurator load into the heroes for the specified filter.

      • hero?: string;

        • The hero id/name. This loads right into the hero if set

    • disableOverallDimensions?: boolean

      • disable feature to show overall dimensions of design, these measurements will be based on bounds of all products in the scene

Callbacks via Javascript

  • addToCart(products: BomProduct[]): Promise<>

    • Add to cart function for callback when user clicks add to cart button in configurator

  • callbacks:

    • onFullscreenEnter: () => console.info('onFullscreenEnter callback')

    • onFullscreenExit: () => console.info('onFullscreenExit callback')

  • screenshot:

    • screenshotDownloadName: (products) => { return `Mod Config Example (${products. Length} products)`;}