Gráficos 2d en React con three.js

Es posible que cada uno de ustedes tenga la necesidad de trabajar con gráficos al crear una aplicación React. O necesitará renderizar una gran cantidad de elementos y hacerlo de manera eficiente y lograr un alto rendimiento al volver a dibujar elementos. Puede ser animación o algún tipo de componente interactivo. Naturalmente, lo primero que me viene a la mente es Canvas. Pero entonces surge la pregunta: "¿Qué contexto usar?" Tenemos una opción: contexto 2d o WebGl . ¿Qué pasa con los gráficos 2d? No todo es tan obvio aquí.





Al trabajar en tareas de alto rendimiento, probamos ambas soluciones para determinar en la práctica cuál de los dos contextos sería más eficiente. Como era de esperar, WebGl derrotó al contexto 2d, por lo que parece que la elección es sencilla.





. , 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