【问题标题】:Loading three.js texture in react as base64 string在反应中加载three.js纹理作为base64字符串
【发布时间】:2021-04-02 04:37:18
【问题描述】:

我正在使用服务器来生成图表的 base64 字符串表示。然后通过使用 POST 请求获取数据来加载它以响应组件。数据加载到反应状态,但场景在纹理加载之前渲染。我已经阅读了 Is there a way to wait for THREE.TextureLoader.load() to finish? ,我是否也应该使用 promise ?我想使用反应状态进行交流,因为最终的交流会比下面的例子更复杂。

const Comp= () => {
    const [state, setState] = useState(null)

    // basic three.js scene setting
    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera(28, 1, 1, 1000);
    camera.position.set(75, 25, 50);

    camera.lookAt(scene.position);
    scene.add(camera);
    camera.add(new THREE.PointLight(0xffffff, 1, Infinity));

    var cubeGeo = new THREE.BoxBufferGeometry(3,3, 0.0001);

    // fetching data
    const getFile = (event) => {
        fetch('http://127.0.0.1:5000/getFile',
            {
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                },
                method: 'POST'
            })
            .then(response => response.json())
            .then(response => setState(response.state))
    }
    
    // fetch data when loading
    useEffect(
        () => getFile(), []
    )

    // use effect when change of state happens
    // (it depends on [state])
    useEffect(
        () => {
            // state contains image data as string representation of base64 
            var texture = new THREE.TextureLoader().load("data:image/jpeg;base64," + state);
            var mat = new THREE.MeshBasicMaterial({ map: texture });

            var cubes = []
            const n = 100;
            const V = 111;
    
            // rest is irrelevant
            for (var i = 0; i < n; i++) {
                var mesh = new THREE.Mesh(cubeGeo, mat);

                cubes[i] = mesh
                var x = V * (Math.random() - .5);
                var y = V * (Math.random() - .5);
                var z = V * (Math.random() - .5);
                var r = Math.sqrt(x ** 2 + y ** 2 + z ** 2) / 20
                x /= r
                y /= r
                z /= r
                // console.log(r, x,y,z)
                cubes[i].position.x = x;
                cubes[i].position.y = y;
                cubes[i].position.z = z;
                scene.add(cubes[i]);
            }
        }, [state])

        return (
            <p ref={() => animate()} />
        )
}

export default Comp;

【问题讨论】:

    标签: javascript reactjs three.js render-to-texture


    【解决方案1】:

    TextureLoader.load 对onLoad、onError 和onProgress 使用回调。

    因此,如果您想让场景等到纹理加载完毕,请在调用 onLoad 或 onError 之前不要开始渲染。

    例子:

    let url = "...";
    let loader = new THREE.TextureLoader();
    
    function onLoad(tex){
      // start rendering now
    }
    
    function onError(){
      // start rendering now?
    }
    
    function onProgress(xhr){
      //...
    }
    
    loader.load(url, onLoad, onError, onProgress);
    

    在three.js的最新版本中,还有一个loadAsync函数,它返回一个Promise。有了这个,您可以构建您的应用程序以利用 async/await 来等待纹理完成加载。

    伪代码:

    // set up your scene, etc., then...
    
    async function run(){
      let url = "...";
      let loader = new THREE.TextureLoader();
    
      function onProgress(xhr){
        //...
      }
    
      await loader.loadAsync(url, onProgress); // or use .then/.catch
    
      // start rendering now
    }
    
    run();
    

    三.js r127

    【讨论】:

    • 它不起作用,我不传递 URL,而是通过状态将数据传递给loader.load,数据:"data:image/jpeg;base64," + state
    • 根据TextureLoader.load 的文档判断,它应该像“url — 文件的路径或 URL。这也可以是数据 URI”。认为进度事件可能不起作用,因为它还说“请注意 three.js r84 放弃了对 TextureLoader 进度事件的支持。”不过,我不确定文档的最新情况。
    • 如果做不到这一点,您总是可以只创建图像元素并附加一个 onload 侦听器来创建和更新纹理,就像我在 fiddle 中所做的那样
    • 看起来文档落后了。但是,是的,b64 数据 URL 仍然是 URL,并且仍然可以与 TextureLoader 一起使用。
    【解决方案2】:

    我知道这不是正确的答案,但你应该看看 R3F React-three-fiber

    https://github.com/pmndrs/react-three-fiber

    它的 api 上有 useLoader:

    https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#useloader

    你可以在哪里做:

    useLoader(loader: THREE.Loader, url: string, extensions?, xhr?)

    【讨论】:

      猜你喜欢
      • 2016-10-11
      • 2013-06-28
      • 2015-05-30
      • 2015-09-15
      • 2014-03-10
      • 1970-01-01
      • 1970-01-01
      • 2016-10-19
      • 2013-07-28
      相关资源
      最近更新 更多