Babylonjs/canvas in a horizontally collapsible panel with animation

Hello, could you please help me with the following :

In my React app , I have a container that displays a 3d model.
E.g

<div id="containerA">  
   <canvas id="my-babylon-canvas-a" />
</div>

In my css I have :

canvas {
   width: 100%;
   height: 100%;
}

This container originally has 100% available width.

Upon clicking on a certain button I would like to reduce the width of that container to make room for some other stuff to be shown right next to it. I was more or less able to achieve this by just setting a new smaller width for that container in css and then just relying on css transition to animate the change of its width. E.g

 width: MY-NEW-REDUCED-WIDTH;
 transition: width 0.5s ease-out;

but while the animation happens, the canvas does not properly “resize” ( its CSS width changes correctly but the canvas “width” attribute does not. This makes the 3d model look skewed.

I know that I could wait for the animation to complete and then follow up with a “engine.resize()” but could I do this constantly while animating so that the 3d model does not get distorted?

What would be the right approach please? Could you give me some pointers on implementation if applicable?

Many thanks for your time!

Hey @gper2020 - Welcome to the Babylon family! We’re sincerely happy to have you here!

Adding @bghgary to lend his thoughts

1 Like

I don’t know if calling resize constantly while animating will work. Have you tried it? :slight_smile: I’m not the expert on this part. Maybe someone else on the forum has experience doing something like this.

1 Like

thanks a lot for your time guys, I gave it a try, it does nt behave too well, when you bombard the engine with “resize()” the animation gets sluggish even though in principle it works.

Calling resize is unfortunately the way to go here. Are you sure you call it only once per frame ?

It is the main approach used on the playground splitter code.

Hi sebavan, thanks for your reply

Well I tried something like this :

        // set the reduced CSS width of the canvas which starts a CSS animation of the canvas CSS width
       // and then : 
        const resizeEngine = () => {
          engineA.resize();
          if (canvasA.width > 300) {
            requestAnimationFrame(resizeEngine);
          }
        };
        requestAnimationFrame(resizeEngine);

What above does :
a) css canvas width shrinks via animation and is sluggish
b) the 3d model inside that canvas completely and literally disappears
until the animation is done and then the 3d model appears again.
Have no clue why the 3d model totally disappears from the view…

Best I can manage seems to be :

        // set the reduced CSS width of the canvas which starts a CSS animation of the canvas CSS width
       // and then : 
       setInterval(() => engineA.resize(), 50);

which yields some acceptable results but due to the resize() happening every 50ms or so you can tell that the 3d model gets distorted/corrected whilst the animation is happening. ( I then clear that interval , not shown in the code above )

1 Like