1

After clicking the button, I want the whole 3D object(width and height) to fit to left side of the screen and show a div HTML info in the right side of the screen.

How to fit object to left side of the screen? Is it possible to set margin(px)?

var camera, scene, renderer;
var geometry, material, mesh;
var lookDirection = new THREE.Vector3();

init();
animate();

function init() {

    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
    camera.position.z = 1;

    scene = new THREE.Scene();
 
    geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
    material = new THREE.MeshNormalMaterial();

    mesh = new THREE.Mesh( geometry, material );
    scene.add( mesh );

    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );
    
    controls = new THREE.OrbitControls( camera, renderer.domElement );
    controls.mouseButtons = {
      LEFT: THREE.MOUSE.RIGHT, 
      MIDDLE: THREE.MOUSE.MIDDLE, 
      RIGHT: THREE.MOUSE.LEFT
    }
    controls.enableZoom = false;
    

}

function animate() {

    requestAnimationFrame( animate );

    renderer.render( scene, camera );
    
    controls.update();
    
    TWEEN.update();

}

function fit(){
 
    controls.enabled = false;

    var box = new THREE.Box3().setFromObject(mesh);
    var boxSize = box.getSize(new THREE.Vector3()).length();
    var boxCenter = box.getCenter(new THREE.Vector3());

    var halfSizeToFitOnScreen = boxSize * 0.5;
    var halfFovY = THREE.Math.degToRad(camera.fov * 0.5);
    var distance = halfSizeToFitOnScreen / Math.tan(halfFovY);

    // compute a unit vector that points in the direction the camera is now
    // in the xz plane from the center of the box
    const direction = (new THREE.Vector3())
        .subVectors(camera.position, boxCenter)
        .multiply(new THREE.Vector3(1, 0, 1))
        .normalize();

    // tween animation
    var from = camera.position;
    var to = direction.multiplyScalar(distance).add(boxCenter);

    var tween = new TWEEN.Tween(from)
        .to(to, 1000)
        .easing(TWEEN.Easing.Quadratic.InOut)
        .onUpdate(function () {
            camera.position.set(this.x, this.y, this.z);

            // update the Trackball controls to handle the new size
            controls.enabled = true;
            controls.target.copy(boxCenter);
            controls.update();
        })
        .start();
  
}

document.getElementById("btn").addEventListener("click", fit);
body {
  margin: 0;
  overflow: hidden;
}

button {
  position: fixed;
  top: 0;
  left: 0;
}
<button id="btn">Fit</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/104/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://sole.github.io/tween.js/build/tween.min.js"></script>

Thanks!

gman
  • 100,619
  • 31
  • 269
  • 393
Tiffany
  • 219
  • 7
  • 17
  • Perhaps set a `viewport` https://jsfiddle.net/6vjm1bqd/. – WestLangley May 16 '19 at 14:12
  • I know it's quite some years later, but written an answer similar to what you're asking here if it helps: https://stackoverflow.com/questions/69817901/how-to-align-meshes-to-the-left-and-make-it-responsive-three-js – aggregate1166877 Mar 03 '23 at 04:49

2 Answers2

1

Sounds like you're really just asking an HTML/JavaScript question

One way would be to use a flex box

function fit(){
   const elem = document.querySelector('#panes> .right');
   elem.style.display = elem.style.display == 'none' ? '' : 'none';
  
}

document.getElementById("btn").addEventListener("click", fit);
html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}
body {
  margin: 0;
}

canvas {
  display: block;
  width: 100%;
  height: 100%;
}
#panes {
  display: flex;
  width: 100vw;
  height: 100vh;
}
#panes>.left,
#panes>.right {
  flex: 1 1 50%;
  height: 100%;
}

#panes>.left {
  padding: 1em;
  text-align: center;
  background: red;
}

#panes>.right {
  padding: 1em;
  background: blue;
  color: white;
}

button {
  position: fixed;
  top: 0;
  left: 0;
}
<div id="panes">
  <div class="left"> Stuff On Left</div>
  <div class="right" style="display: none;">Stuff on right</div>
</div>
<button id="btn">Fit</button>

Then insert the canvas in the left pane and use a better example of how to set the canvas's size

var camera, scene, renderer;
var geometry, material, mesh;
var lookDirection = new THREE.Vector3();

init();
animate();

function init() {

    camera = new THREE.PerspectiveCamera( 70, 2, 0.01, 10 );
    camera.position.z = 1;

    scene = new THREE.Scene();
 
    geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
    material = new THREE.MeshNormalMaterial();

    mesh = new THREE.Mesh( geometry, material );
    scene.add( mesh );

    renderer = new THREE.WebGLRenderer( { antialias: true } );
    document.querySelector("#panes>.left").appendChild( renderer.domElement );
    
    controls = new THREE.OrbitControls( camera, renderer.domElement );
    controls.mouseButtons = {
      LEFT: THREE.MOUSE.RIGHT, 
      MIDDLE: THREE.MOUSE.MIDDLE, 
      RIGHT: THREE.MOUSE.LEFT
    }
    controls.enableZoom = false;
    

}

function resizeRendererToDisplaySize(renderer) {
  const canvas = renderer.domElement;
  const width = canvas.clientWidth;
  const height = canvas.clientHeight;
  const needResize = canvas.width !== width || canvas.height !== height;
  if (needResize) {
    renderer.setSize(width, height, false);
  }
  return needResize;
}

function animate() {

  if (resizeRendererToDisplaySize(renderer)) {
    const canvas = renderer.domElement;
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
  }

    renderer.render( scene, camera );
    
    controls.update();
    
    TWEEN.update();

    requestAnimationFrame( animate );

}

function fit(){
   const elem = document.querySelector('#panes> .right');
   elem.style.display = elem.style.display == 'none' ? '' : 'none';
  
}

document.getElementById("btn").addEventListener("click", fit);
html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}
body {
  margin: 0;
}

canvas {
  display: block;
  width: 100%;
  height: 100%;
}
#panes {
  display: flex;
  width: 100vw;
  height: 100vh;
}
#panes>.left,
#panes>.right {
  flex: 1 1 50%;
  height: 100%;
}

#panes>.right {
  padding: 1em;
  background: blue;
  color: white;
}

button {
  position: fixed;
  top: 0;
  left: 0;
}
<div id="panes">
  <div class="left"></div>
  <div class="right" style="display: none;">Stuff on right</div>
</div>
<button id="btn">Fit</button>

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/104/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://sole.github.io/tween.js/build/tween.min.js"></script>
gman
  • 100,619
  • 31
  • 269
  • 393
0

I hope it's not late to answer this question, but I found something that maybe is what you were looking for. Check Is there ANY way to have the three.js camera lookat being rendered off-center?

camera = new THREE.PerspectiveCamera( for, aspect, near, far );

camera.setViewOffset( fullWidth, fullHeight, widthOffset, heightOffset, viewWidth, viewHeight );

Take widthOffset and heightOffset as parameters to slide de target of your camera to any side.

Marcosaurios
  • 97
  • 2
  • 8