Masing-masing dari Anda mungkin memiliki kebutuhan untuk bekerja dengan grafik saat membangun aplikasi React. Atau Anda perlu merender sejumlah besar elemen, dan melakukannya secara efisien dan mencapai kinerja tinggi saat menggambar ulang elemen. Ini bisa berupa animasi atau semacam komponen interaktif. Tentu, hal pertama yang terlintas dalam pikiran adalah Kanvas. Tapi kemudian muncul pertanyaan: "Konteks apa yang digunakan?" Kami memiliki pilihan - konteks 2d atau WebGl . Bagaimana dengan grafik 2d? Tidak semuanya begitu jelas di sini.
Saat mengerjakan tugas berperforma tinggi, kami mencoba kedua solusi untuk menentukan dalam praktiknya mana dari dua konteks yang lebih efisien. Seperti yang diharapkan, WebGl mengalahkan konteks 2d, jadi sepertinya pilihannya mudah.
. , 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-. , .
! , .