Gráficos 2D no React com three.js

Cada um de vocês pode precisar trabalhar com gráficos ao construir um aplicativo React. Ou você precisará renderizar um grande número de elementos com eficiência e obter alto desempenho ao redesenhar os elementos. Pode ser uma animação ou algum tipo de componente interativo. Naturalmente, a primeira coisa que vem à mente é o Canvas. Mas então surge a pergunta: "Que contexto usar?" Temos uma escolha - contexto 2d ou WebGl . E os gráficos 2D? Nem tudo é tão óbvio aqui.





Ao trabalhar em tarefas de alto desempenho, tentamos ambas as soluções para determinar na prática qual dos dois contextos seria mais eficiente. Como esperado, WebGl derrotou o contexto 2d, então parece que a escolha é direta.





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