web-dev-qa-db-fra.com

Three.js Resizing Canvas

J'ai travaillé sur un projet 3D où nous montrons des objets 3D dans le navigateur Web en utilisant la bibliothèque Three.js.

Le problème est:

  • Tout d'abord, le modèle est affiché dans un petit élément dom ou lorsque la fenêtre du navigateur elle-même est petite.
  • Ensuite, lorsque la fenêtre (ou l'élément dom est redimensionné), le modèle devient pixellisé

Voici quelques captures d'écran:

Avant de redimensionner:

enter image description here

Après le redimensionnement:

enter image description here

Comment cela devrait être après le redimensionnement:

enter image description here

Voici la partie du code qui définit les dimensions du modèle (hauteur et largeur), et cette fonction est appelée lorsque l'événement resize est déclenché:

console.log("domChanged fired")

instance.domBoundingBox = instance.dom.getBoundingClientRect();
instance.domCenterPos.x = instance.domBoundingBox.width / 2 + instance.domBoundingBox.left;
instance.domCenterPos.y = instance.domBoundingBox.height / 2 + instance.domBoundingBox.top;

var width = instance.dom.clientWidth, height = instance.dom.clientHeight;
instance.domWidthHalf = width / 2, instance.domHeightHalf = height / 2;

// TODO: fire event to expose it to site developers

// here we should update several values regarding width,height,position
if(instance.cameraReal) {
    instance.cameraReal.aspect = instance.dom.clientWidth / instance.dom.clientHeight;
    instance.cameraReal.updateProjectionMatrix();
}

if(instance.renderer3D)
    instance.renderer3D.setSize(instance.dom.clientWidth, instance.dom.clientHeight);

Quelqu'un peut-il me donner un indice? J'y travaille déjà depuis quelques jours mais aucun indice jusqu'à présent

33
Abu Romaïssae

Enfin, le problème a été résolu, le problème provenait en fait, car l'application utilise le THREE.EffectComposer objet, dans le constructeur de classe un objet composer ont été créés comme suit:

this.composer = new THREE.EffectComposer(this.renderer3D);

Donc, comme pour le rendu, le composer devait avoir la taille mise à jour après la fonction du gestionnaire d'événements comme suit:

if(instance.renderer3D)
    instance.renderer3D.setSize(instance.dom.clientWidth, instance.dom.clientHeight);
if(instance.composer)
    instance.composer.setSize(instance.dom.clientWidth, instance.dom.clientHeight);

Et cela a parfaitement résolu le problème :)

9
Abu Romaïssae

Ainsi, l'élément canvas peut être redimensionné comme tous les autres éléments. Ce que vous voulez faire, c'est de dire au rendu et à la caméra de redimensionner également le contenu de votre toile.

window.addEventListener( 'resize', onWindowResize, false );

function onWindowResize(){

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize( window.innerWidth, window.innerHeight );

}
81
Shawn Whinnery

J'ai appliqué la réponse de Shawn Whinnery à mes besoins avec React JS:

Démarrer l'écouteur surMount:

componentDidMount() {
  window.addEventListener('resize', this.handleResize, false)
}

Supprimer l'écouteur onUnmount (parce que nous aimons la collecte des ordures):

componentWillUnmount() {
  window.removeEventListener('resize', this.handleResize, false)
}

Installer la fonction de gestionnaire:

handleResize = () => {
  this.camera.aspect = window.innerWidth / window.innerHeight
  this.camera.updateProjectionMatrix()
  this.renderer.setSize(window.innerWidth, window.innerHeight)
}

La syntaxe des flèches grasses est utilisée pour éviter de lier this. Le code ne fonctionnera pas si vous avez ceci: handleResize() { ... }, mais bien sûr, cela fonctionnerait si vous ajoutiez ceci à votre constructeur:

this.handleResize = this.handleResize.bind(this)

Note finale: confirmez que votre caméra est this.camera Et que votre rendu est this.renderer. En plus de cela, vous devriez pouvoir tout coller.

5
agm1984

Pour ceux qui recherchent sur Google, si vous voulez commencer rapidement avec un utilitaire d'aide qui fait le redimensionnement pour vous, consultez ce github: https://github.com/jeromeetienne/threex.windowresize

La seule chose que vous avez à faire est de l'installer via bower et de l'initialiser:

new THREEx.WindowResize(renderer, camera)
2
polyclick