Babylon.js Viewer in modal window?

I’m playing around with the Babylon.js Viewer for the first time. It’s great! But I’m having a slight difficulty when I try to put it in a modal div. On fresh page load when I open the modal for the first time the 3D viewport isn’t updating properly (the model isn’t in frame/visible), but as soon as I manually resize the browser window the model snaps into view and any subsequent opening of the modal div with different models are displayed fine. I tried viewer.forceResize() called after model loading but that had no effect.

My assumption is that the model div is being rendered only after being displayed / opened. You will need to initialize the viewer after the model opened and not before, as the viewer doesn’t have any HTML nodes to attach to.

A simple call to the viewer’s Init will work - Advanced usage - Babylon.js Documentation , but with the right html tag . I assume it will work, will be great to see an example if it doesn’t.

1 Like

Hi @RaananW. Here’s what I’m doing:

import * as BabylonViewer from '@babylonjs/viewer';
import MicroModal from 'micromodal';

BabylonViewer.viewerManager.getViewerPromiseById('model-viewer').then((viewer) => {

    viewer.onEngineInitObservable.add((scene) => {

        // Init modal.
        MicroModal.init();

        // Init vars.
        let models: NodeListOf<HTMLElement> = document.querySelectorAll(".model");
        let currentModel: HTMLElement | null = null;

        // Setup event listeners.
        models.forEach((model) => {
            model.addEventListener('click', (event) => {
                loadModel(<HTMLElement>event.target);
            });
        });

        // Load a model.
        function loadModel(requestedModel: HTMLElement) {
            if (requestedModel != currentModel) {
                let name = requestedModel.innerHTML;
                let path = <string>requestedModel.getAttribute("data-path");
                viewer.loadModel({
                    url: `${path}`
                }).then(model => {
                    console.log(`Model "${name}" loaded!`);
                    currentModel?.classList.remove('active');
                    currentModel = requestedModel;
                    currentModel.classList.add('active');
                    // This makes it work.
                    viewer.engine.setSize(window.innerWidth, window.innerHeight);
                }).catch(error => {
                    console.log(`Error loading "${name}"!`, error);
                });
            }
        }
    });
});

Note: now that I’ve added the following line to force a resize, it works:

viewer.engine.setSize(window.innerWidth, window.innerHeight);

does the container that holds the model have a predefined size before the model is loaded?

The default MicroModal suggested markup has a few nested divs and I’ve made sure each div, including the container div for the babylon viewer, has width: 100% height: 100% applied from the outset.

Thanks for your help, but I don’t want to waste your time if my workaround solution does the trick :slight_smile:

1 Like

No time wasted, I’m happy you found a solution.

Just s not that percentage-based size definition can still be 0 pixel, if the container holding it has no size when the viewer is initialized. So calling resize is actually the proper solution in that case :blush:

1 Like