Graphiques 2D dans React avec three.js

Chacun d'entre vous peut avoir besoin de travailler avec des graphiques lors de la création d'une application React. Ou vous aurez besoin de rendre un grand nombre d'éléments, de le faire efficacement et d'obtenir des performances élevées lors du redessin d'éléments. Il peut s'agir d'une animation ou d'une sorte de composant interactif. Naturellement, la première chose qui vient à l'esprit est Canvas. Mais alors la question se pose : « Quel contexte utiliser ? Nous avons le choix - contexte 2d ou WebGl . Et les graphismes 2D ? Tout n'est pas si évident ici.





Lorsque nous travaillons sur des tâches à haute performance, nous avons essayé les deux solutions pour déterminer en pratique lequel des deux contextes serait le plus efficace. Comme prévu, WebGl a vaincu le contexte 2D, il semble donc que le choix soit simple.





. , WebGl. , , 2d context. , , – . pixi.js three.js – , .





Pixi.js three.js

, : pixi.j 2d-, three.js – 3d. , 2d 3d? , 3d- . ,





, : “ ?”. Camera – , scene renderer. . , , . , – scene. , , – scene. camera , renderer – , 3d- 2d-.





, , , , . , , , – . , z, . , .





, three.js 2d-. ? three.js.





  • -, . , : pixi.js – , three.js – three.interaction.





, , . pixi.js , . ? . . three.js, , .





  • SVG. , SVG , , . three.js , pixi.js – .





  • , three.js . , , 3d-, pixi.js .





, – three.js.





Three.js React

– react- “” three.js. 





react – react-three-fiber. , , . , three.js react-three-fiber . 





, . drei storybook . , , , - . 





– react. view - ? .





, three.js . , ES6 – .





. , – .





three.js three.js. , .





class Three {
  constructor({
    canvasContainer,
    sceneSizes,
    rectSizes,
    color,
    colorChangeHandler,
  }) {
    //        this
    this.sceneSizes = sceneSizes;
    this.colorChangeHandler = colorChangeHandler;
 
    this.initRenderer(canvasContainer); //  
    this.initScene(); //  
    this.initCamera(); //  
    this.initInteraction(); //    
    this.renderRect(rectSizes, color); //    
    this.render(); //  
  }
 
  initRenderer(canvasContainer) {
    //   (    WebGL2)
    // antialias    
    this.renderer = new THREE.WebGLRenderer({antialias: true});
 
    //  
    this.renderer.setSize(this.sceneSizes.width, this.sceneSizes.height);
 
    //   -,    
    canvasContainer.appendChild(this.renderer.domElement);
  }
 
  initScene() {
    //   
    this.scene = new THREE.Scene();
 
    //   
    this.scene.background = new THREE.Color("white");
  }
 
  initCamera() {
    //    (   2d)
    this.camera = new THREE.OrthographicCamera(
      this.sceneSizes.width / -2, //   
      this.sceneSizes.width / 2, //   
      this.sceneSizes.height / 2, //   
      this.sceneSizes.height / -2, //   
      100, //  
      -100 //  
    );
 
    //    
    this.camera.position.set(
      this.sceneSizes.width / 2, //   x
      this.sceneSizes.height / -2, //   y
      1 //   z
    );
  }
 
  initInteraction() {
    //   (    )
    new Interaction(this.renderer, this.scene, this.camera);
  }
 
  render() {
    //    (    )
    this.renderer.render(this.scene, this.camera);
  }
 
  renderRect({width, height}, color) {
    //   -    "height"   "width"
    const geometry = new THREE.PlaneGeometry(width, height);
 
    //     "color"
    const material = new THREE.MeshBasicMaterial({color});
 
    //   - 
    this.rect = new THREE.Mesh(geometry, material);
 
    //   
    this.rect.position.x = this.sceneSizes.width / 2;
    this.rect.position.y = -this.sceneSizes.height / 2;
 
    //   "three.interaction"
    //       
    this.rect.on("click", () => {
      //   
      this.colorChangeHandler();
    });
 
    this.scene.add(this.rect);
  }
 
  //     
  rectColorChange(color) {
    //   
    this.rect.material.color.set(color);
 
    //   (    )
    this.render();
  }
}
      
      



ThreeContauner, React- Three.





import {useRef, useEffect, useState} from "react";
 
import Three from "./Three";
 
//    
const sceneSizes = {width: 800, height: 500};
const rectSizes = {width: 200, height: 200};
 
const ThreeContainer = () => {
  const threeRef = useRef(); //       canvas
  const three = useRef(); //   ,   ,    
  const [color, colorChange] = useState("blue"); //     
 
  // Handler   ,   
  const colorChangeHandler = () => {
    //             
    colorChange((prevColor) => (prevColor === "grey" ? "blue" : "grey"));
  };
 
  //    Three,     three.js
  useEffect(() => {
    //    "Three"   ,   
    if (!three.current) {
      //    "Three",       three.js
      three.current = new Three({
        color,
        rectSizes,
        sceneSizes,
        colorChangeHandler,
        canvasContainer: threeRef.current,
      });
    }
  }, [color]);
 
  //        Three
  useEffect(() => {
    if (three.current) {
      //  ,     
      three.current.rectColorChange(color);
    }
  }, [color]);
 
  //      canvas (  three.js)
  return <div className="container" ref={threeRef} />;
};
 
export default ThreeContainer;
      
      



.





, , , .





.





, three.js React- - , . , , / . , , virtual dom React-. , react-three-fiber drei – React-.





:





import {useState} from "react";
import {Canvas} from "@react-three/fiber";
import {Plane, OrthographicCamera} from "@react-three/drei";
 
//    
const sceneSizes = {width: 800, height: 500};
const rectSizes = {width: 200, height: 200};
 
const ThreeDrei = () => {
  const [color, colorChange] = useState("blue"); //     
 
  // Handler   , 
  const colorChangeHandler = () => {
    //             
    colorChange((prevColor) => (prevColor === "white" ? "blue" : "white"));
  };
 
  return (
    <div className="container">
      {/*   ,      */}
      <Canvas className="container" style={{...sceneSizes, background: "grey"}}>
        {/*       three.js,     makeDefault, 
           ,       */}
        <OrthographicCamera makeDefault position={[0, 0, 1]} />
        <Plane
          //     
          onClick={colorChangeHandler}
          //        ,     three.js
          args={[rectSizes.width, rectSizes.height]}
        >
          {/*       three.js, 
                 attach     */}
          <meshBasicMaterial attach="material" color={color} />
        </Plane>
      </Canvas>
    </div>
  );
};
 
export default ThreeDrei;
      
      



, , . , ,   . , , . 





three.js React-. , .





! , .








All Articles