Threejs in div and resize with Transition!

Hi everyone!
I am trying to put the Threejs scene inside the div tag.
I create a button that when clicked will change the width of the div. I want it to have effects with transitions. How can i do that?
Am I wrong or missing something? Thanks

My code:

var container;
var camera, controls, scene, renderer;
var w,h;

init();
render();
function init() {
  container = document.getElementById('canvas');
  renderer = new THREE.WebGLRenderer({ antialias: true });
  w = container.offsetWidth;
  h = container.offsetHeight;
  renderer.setSize(w, h);
  renderer.setAnimationLoop(render);

  container.appendChild(renderer.domElement);
  window.addEventListener('resize', onWindowResize, false);

  camera = new THREE.PerspectiveCamera(40,w/h, 0.1, 100);
  camera.position.set(4.25, 1.4, - 4.5);

  controls = new OrbitControls(camera, container);
  controls.enableDamping = true;
  controls.target.set(0, 0.5, 0);


  var environment = new RoomEnvironment();
  var pmremGenerator = new THREE.PMREMGenerator(renderer);

  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x808080);
  scene.environment = pmremGenerator.fromScene(environment).texture;
  scene.fog = new THREE.Fog(0x808080, 10, 50);

  
  var grid = new THREE.GridHelper(100, 40, 0x000000, 0xffffff);
  grid.material.opacity = 0.1;
  grid.material.depthWrite = false;
  grid.material.transparent = true;
  scene.add(grid);

}


var btn = document.getElementById('btn1');
btn.addEventListener('click', function () {
  document.getElementById('canvas').style.width = '75%';
});


function onWindowResize() {

  camera.aspect =   container.offsetWidth / container.offsetHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(  container.offsetWidth,  container.offsetHeight);

}


function render() {
  controls.update();
  renderer.render(scene, camera);
}

css:

body {
    font-family: Monospace;
    background-color: #fff;
    margin: 0px;
    overflow: hidden;
}

#canvas {
    width: 100%;
    height: 100%;
    left: 0px;
    position: absolute;
    transition: 2s;
}

.button {
  position: absolute;
  border: none;
  color: white;
  padding: 16px 32px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  margin: 4px 2px;
  transition-duration: 0.4s;
  cursor: pointer;
}

.button1 {
  background-color: white;
  color: black;
  border: 2px solid #4CAF50;
}

html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/style.css">
</head>

<body>
    <div id="canvas">
        <button class="button button1" id="btn1">Transition</button>
    </div>
    <script type="module" src="lib/test.js">
    </script>
</body>

</html>

You can transition size of the div with something like transition: width 4s however scaling canvas is something different. You should change its height and width attributes and update camera and renderer afterwards.

1 Like

When using css transitions, its possible to listen to its animation events. As far as I know there are animationstart, animationend and animationiteration events. You can use it like so:

const animated = document.querySelector('.animated');

animated.addEventListener('animationstart', () => {
  console.log('Animation started');
});

animated.addEventListener('animationend', () => {
  console.log('Animation ended');
});

animated.addEventListener('animationiteration', () => {
  console.log('Animation iterates');
});

You probably want to or already have a onResize function, that updates renderer and camera size and ratio. Then call onResize on those events.
Its probably only nessecary to call it on animationiteration, but never used that event yet.

Not sure on what framerate the css animation is called. Maybe you need to throttle it down and only call the onresize event every second iteration or so to keep it smooth and not laggy

2 Likes

Sincerely thanks!!! :heart: :heart:

2 Likes