three.js を使用した React の 2D グラフィックス

React アプリケーションを構築するときに、それぞれがグラフィックスを扱う必要があるかもしれません。または、多数の要素をレンダリングし、要素を再描画するときに効率的に実行し、高いパフォーマンスを実現する必要があります。アニメーションまたは何らかのインタラクティブなコンポーネントにすることができます。当然、真っ先に思い浮かぶのはキャンバス。しかし、「どのコンテキストを使用するか」という疑問が生じます。2D コンテキストまたはWebGlという選択肢があります2Dグラフィックスはどうですか?ここですべてが明らかなわけではありません。





パフォーマンスの高いタスクに取り組むときは、両方のソリューションを試して、実際には 2 つのコンテキストのどちらがより効率的かを判断しました。予想通り、WebGl は 2D コンテキストを打ち負かしたので、選択は簡単に思えます。





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