React projeleri genellikle pubilc'in mutlak yollardan erişilebilen statik kaynakları koyduğu bir yere sahiptir. Bu nedenle, Threejs dosyasını herkese açık hale getirebilir ve ardından tepki bileşenini iframe aracılığıyla içe aktarabiliriz veya bir etiket bağlantısı koyabiliriz.





vantajlar ve dezavantajlar


Artıları : Basit ve sade . İnternette bulunan örnekler doğrudan projeye konur ve herhangi bir değişiklik yapmaya gerek yoktur. (Ve tepkinin threejs etkisini düşünmeyin)
Bunun aslında 2 projeye bölmekten farkı yok.
Dezavantajları : Etkileşim daha sıkıntılıdır.Threejs ile harici modül arasında herhangi bir etkileşim varsa çok sıkıntılıdır. (Yalnızca iframe'in posta mesajı veya başka bir şey aracılığıyla etkileşime girebilir)
Özet :Threejs nispeten bağımsız ise, temelde diğer modüllerle ilgisi yoktur ve aynı zamanda başka projeleri de düşünmez. Hızlı geliştirme için bu yöntemi kullanabilirsiniz.
2. Modül, üçlü vb. tanıtıyor ve bileşen içinde gelişiyor

Yukarıdaki soruya devam etmek: neden tepkide üç kullanıyorsunuz? Threejs performansını optimize etmek için hangi tepki özellikleri kullanılır?
Miyavlıyordu, görüşmeci tarafından röportaj yapılırken, "performans" kelimesi etrafında döndüğünde, kafamda sadece performansı düşündüm...
Üç modülü tepki olarak geliştirdim ve kesinlikle üç modülü geliştirmek için modülerliği kullanmak istiyorum !
Gerçek bir uygulama senaryosu için, bir sürü cihazım var ve her cihazın ayrıntılarının cihazın 3D modelini göstermesi gerekiyor. Bu 3B modelin üç bileşenine sahipsem, üzerinde farklı parametreleri mi geçmem gerekiyor? 3D modülünün genel arka plan renginin ayarlanmasını içeriyorsa. Sadece üç bileşeni ayarlamam gerekiyor ve bu iyi!

import * as THREE from 'three';
BSP gibi modülleri içe aktarmak için babel-plugin-import, vb. kullanın.
umi kullanılarak yapılandırılabilir: externals parametresi
Ardından bileşeni iyi bir şekilde geliştirin. (Örneğin)


interface MyProps {
  style?: Record<string, any>;
  [key: string]: any;
}
let timeNow = new Date().valueOf();
const values = { tep: '40.0', sec: '20.0' };
const meshcolor = 0xffffff;
let renderer: any,
  camera: any,
  scene: any,
  light: any,
  controls: any,
  isAutoRotate: boolean,
  cube: any;

export default (props: MyProps) => {
  const { style, ...pros } = props;
  const [btnRender, setBtnRender] = useState<boolean>(false);
  const renderRef = useRef<any>();
  // 初始化render
  const threeInit = (curDom: any) => {
    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(curDom.clientWidth, curDom.clientHeight);
    renderer.setClearColor(0xeeeeee);
    renderer.shadowMap.enabled = true;
    // curDom.innerHTML = null;
    curDom.appendChild(renderer.domElement);
  };
  // 初始化相机
  const initCamera = (curDom: any) => {
    camera = new THREE.PerspectiveCamera(45, curDom.clientWidth / curDom.clientHeight, 0.1, 300);
    camera.position.set(0, 15, 40);
  };
  // 初始化场景
  const initScene = () => {
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0x39609b);
    // scene.fog = new THREE.Fog( 0xa0a0a0, 5, 250 );
  };
  // 初始化光线
  const initLight = (myScene: any) => {
    light = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.6);
    myScene.add(light);
  };
  // 初始化控制器
  const initControls = (myCamera: any) => {
    controls = new OrbitControls(myCamera, renderer.domElement);
    //设置控制器的中心点
    controls.target.set(0, 10, 0);
    // 如果使用animate方法时,将此函数删除
    //controls.addEventListener( 'change', render );
    // 使动画循环使用时阻尼或自转 意思是否有惯性
    controls.enableDamping = false;
    //动态阻尼系数 就是鼠标拖拽旋转灵敏度
    // 阻尼系数
    controls.dampingFactor = 0.1;

    controls.minPolarAngle = Math.PI / 12;
    controls.maxPolarAngle = (Math.PI * 19) / 40;
    //是否可以缩放
    controls.enableZoom = true;
    //是否自动旋转
    controls.autoRotate = true;
    controls.autoRotateSpeed = 0.5;
    //设置相机距离原点的最远距离
    controls.minDistance = 10;
    //设置相机距离原点的最远距离
    controls.maxDistance = 200;
    //是否开启右键拖拽
    controls.enablePan = true;
    controls.update();
  };

  // 获取带数据的canvas
  const getTextCanvas = async ({ tep, sec }: any) => {
    const time = moment().format('HH:mm:ss');
    const width = 200,
      height = 300;
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d');
    return new Promise((resole) => {
      if (ctx) {
        const img = new Image();
        img.src = collectorImg;
        //图片加载完后,将其显示在canvas中
        img.onload = () => {
          ctx.drawImage(img, 0, 0, width, height);
          ctx.font = 30 + 'px " bold';
          ctx.fillStyle = '#333';
          ctx.textAlign = 'center';
          ctx.textBaseline = 'middle';
          ctx.fillText(tep, (width * 11) / 24, (height * 10) / 40);
          ctx.fillText(sec, (width * 11) / 24, (height * 20) / 40);
          ctx.font = 10 + 'px " bold';
          ctx.fillText(time, (width * 16.5) / 24, (height * 26.6) / 40);
          resole(canvas);
        };
      }
    });
  };

  // 改变材质种类
  const changeMaterial = async (myScene: any) => {
    const canvas: any = await getTextCanvas({ tep: 40, sec: 20 });
    if (canvas) {
      const texture = new THREE.CanvasTexture(canvas);
      const materials = [
        new THREE.MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),
        new THREE.MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),
        new THREE.MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),
        new THREE.MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),
        new THREE.MeshLambertMaterial({
          color: meshcolor,
          opacity: 1,
          transparent: true,
          map: texture,
        }),
        new THREE.MeshLambertMaterial({ color: meshcolor, opacity: 1, transparent: true }),
      ];
      const geometry = new THREE.BoxGeometry(20, 20, 5);
      cube = new THREE.Mesh(geometry, materials);
      cube.position.set(0, 10, 0);
      myScene.add(cube);
    }
  };
  // 初始化物体
  const initModel = (myScene: any) => {
    // 添加collector
    changeMaterial(myScene);
  };
  // 更新value数据
  const changeValues = () => {
    values.tep = (39 + Math.random() * 2).toFixed(1);
    values.sec = (19 + Math.random() * 2).toFixed(1);
  };

  const updateData = async () => {
    if (new Date().valueOf() - timeNow > 5000) {
      timeNow = new Date().valueOf();
      changeValues();
    }
    const canvas: any = await getTextCanvas(values);
    if (canvas && cube) {
      cube.material[4].map = new THREE.CanvasTexture(canvas);
      cube.material.map.needsUpdate = true;
    }
  };

  const render = () => {
    if (renderer && scene && camera) {
      renderer.render(scene, camera);
    }
  };
  const animate = () => {
    //更新控制器
    render();
    if (controls && isAutoRotate) {
      controls.update();
    }
    requestAnimationFrame(animate);
  };

  useEffect(() => {
    if (renderRef && renderRef.current) {
      threeInit(renderRef.current);
      initCamera(renderRef.current);

      initScene();
      animate();
    }
    const timer = setInterval(() => {
      updateData();
    }, 1000);
    return () => {
      cancelAnimationFrame(1);
      clearInterval(timer);
    };
  }, [renderRef]);

  useEffect(() => {
    if (scene) {
      initLight(scene);
      initModel(scene);
    }
  }, [scene]);
  useEffect(() => {
    if (camera) {
      initControls(camera);
    }
  }, [camera]);

  return (
    <div
      ref={renderRef}
      style={{ width: '300px', height: '200px', position: 'relative', ...style }}
      {...pros}
    >
      <div className={styles.btns}>
        <div
          className={styles.btn}
          onClick={() => {
            isAutoRotate = !isAutoRotate;
            setBtnRender(isAutoRotate);
          }}
        >
          {btnRender ? '自动旋转' : '旋转关闭'}
        </div>
      </div>
    </div>
  );
};

Avantajlar ve dezavantajlar:


Avantajları : Modüler geliştirme, etkileşim ve değer aktarımı için uygun.
dezavantajları :
1. İlgili modülleri tanıtırken iğrenç (çok zor).
2. Temel kodun yine de kendi başına yavaş bir şekilde paketlenmesi gerekir.
3. İşleme sorunu: Tepki durumu değeri üç güncellemeyi kontrol edemez; (tabii ben söylemediğim halde işlemeyi doğrudan tepki vermek üzere verirseniz)

3- Kendim yapamıyorum Hazır Var mı?



Kendiniz yapmak çok mu zahmetli, hazır olan var mı?
Var tabiki.
Github
Demo
npm install three @react-three/fiber

import ReactDOM from 'react-dom'
import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'

function Box(props) {
  // This reference gives us direct access to the THREE.Mesh object
  const ref = useRef()
  // Hold state for hovered and clicked events
  const [hovered, hover] = useState(false)
  const [clicked, click] = useState(false)
  // Subscribe this component to the render-loop, rotate the mesh every frame
  useFrame((state, delta) => (ref.current.rotation.x += 0.01))
  // Return the view, these are regular Threejs elements expressed in JSX
  return (
    <mesh
      {...props}
      ref={ref}
      scale={clicked ? 1.5 : 1}
      onClick={(event) => click(!clicked)}
      onPointerOver={(event) => hover(true)}
      onPointerOut={(event) => hover(false)}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
  )
}

ReactDOM.render(
  <Canvas>
    <ambientLight />
    <pointLight position={[10, 10, 10]} />
    <Box position={[-1.2, 0, 0]} />
    <Box position={[1.2, 0, 0]} />
  </Canvas>,
  document.getElementById('root'),
)