Maison  >  Questions et réponses  >  le corps du texte

React Three Fiber : Pourquoi mes événements de défilement sont-ils en retard ?

Dans React Three Fiber, j'ai un composant React qui génère un sprite que je souhaite conserver sur les zooms de la caméra. L'algorithme semble fonctionner (la taille ne semble pas changer avec le temps), mais je peux visiblement le voir évoluer lors d'un zoom avant et arrière.

J'ai vu des opérations similaires effectuées sur des sprites ailleurs et cela semble bien fonctionner sans apparition de problèmes. Je pense qu'il y a une sorte de décalage, mais je ne sais pas où il se situe ni comment y remédier.

J'ai également joint une vidéo du problème : https://drive.google.com/file/d/121XPY1pB5bNJr5EYNESnyPfLDdtEeIhn/view?usp=sharing

J'ai joint le code du composant React. Comme le code React Three Fiber classique, il s'agit simplement d'une saisie dans le composant canevas :

function TestFunction() {
  const [scale, setScale] = useState(new Vector3(1, 1, 1));
  const map = new THREE.TextureLoader().load("src/assets/Joshy.png");

  let state = useThree();
  let zoom = state.camera.zoom / 100;
  let scaler: Vector3 = new Vector3(1 / zoom, 1 / zoom, 1 / zoom);
  const handleMouseScroll = (event: WheelEvent) => {
    // Perform actions when the mouse is scrolled
    scaler.set(1 / zoom, 1 / zoom, 1 / zoom);
    setScale(scaler);
  };
  useFrame(() => {
    window.document.addEventListener("wheel", handleMouseScroll, {
      capture: true,
      passive: true,
    });
  });

  return (
    <sprite scale={scale}>
      <spriteMaterial map={map} />
    </sprite>
  );
}

J'espère qu'il n'a pas cet aspect lent/glitch puisque je mets à jour chaque image, donc je ne suis pas sûr de savoir quel est le problème.

Ce que je recherche, c'est ceci : https://drive.google.com/file/d/1KtEcrikFJFYboC6LX0mFVttx2eSTia0c/view?usp=sharing Aucun décalage notable. Le code qui génère cette version sans décalage est du pur JavaScript Three.js.

const cont = document.documentElement;
const [w, h] = [cont.clientWidth - 20, cont.clientHeight - 20];
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(50, w / h, 0.1, 100);
camera.position.set(10, 10, 10);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(w, h);
document.body.appendChild(renderer.domElement);

const hlp = new THREE.AxesHelper(3);
scene.add(hlp);

const map = new THREE.TextureLoader().load(
  'https://source.unsplash.com/random/200x200'
);
const material = new THREE.SpriteMaterial({
  map: map
});

const sprite_scale = 4;
const sprite = new THREE.Sprite(material);
/* sprite.scale.set(sprite_scale, sprite_scale); */
const virtual_d = sprite.position.distanceTo(camera.position) *1.4/ sprite_scale;

scene.add(sprite);

const controls = new THREE.OrbitControls(camera, renderer.domElement);

const render = () => {
  renderer.render(scene, camera);
};

const animate = () => {

  requestAnimationFrame(animate);

  render();

};

document.addEventListener('wheel', scaler);

function scaler() {
  const scale = sprite.position.distanceTo(camera.position)/2;
  console.log(sprite.position.distanceTo(camera.position) )
  console.log("CAMERA POSITION: ", camera.position)
  sprite.scale.set(scale, scale);
}

animate();

La logique des Three.js ordinaires et de React Three Fiber est la même, mais les résultats sont complètement différents.

P粉238433862P粉238433862218 Il y a quelques jours500

répondre à tous(1)je répondrai

  • P粉755863750

    P粉7558637502024-04-07 10:49:22

    Vous utilisez React.

    Soyez donc prudent lorsque vous utilisez "window.document.addEventListener". Chaque fois que le composant est restitué, un nouvel écouteur d'événement est créé, ce qui entraîne la présence de nombreux écouteurs d'événement sur la page.

    Pensez plutôt à utiliser des crochets. Vous pouvez trouver de nombreux crochets dans React-Three-Drei. Je recommande fortement d'utiliser React-Two-Drei.

    useEffect(() => {
        function handleMouseScroll() {
          //do something
        }
    
        window.addEventListener('wheel', handleMouseScroll);
    
        return () => {
          window.removeEventListener('wheel', handleMouseScroll);
        };
      }, []);

    Dans votre cas, vous utilisez l'écouteur d'événements dans useFrame. Ensuite, useFrame s’exécute 60 fois par seconde. Vous créez 60 écouteurs d'événements par seconde.

    répondre
    0
  • Annulerrépondre