首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >以base64字符串的形式在react中加载three.js纹理

以base64字符串的形式在react中加载three.js纹理
EN

Stack Overflow用户
提问于 2021-04-01 23:28:20
回答 2查看 214关注 0票数 0

我使用server来生成图表的base64字符串表示。然后通过POST请求获取数据,将其加载到react组件。数据加载到react状态,但在加载纹理之前渲染场景。我已经读过Is there a way to wait for THREE.TextureLoader.load() to finish?了,我也应该使用promise吗?我想使用react状态进行通信,因为最终的通信将比下面的示例更复杂。

代码语言:javascript
复制
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;
EN

回答 2

Stack Overflow用户

发布于 2021-04-02 02:36:58

TextureLoader.loadonLoadonErroronProgress使用回调。

因此,如果要让场景等待纹理加载,则在调用onLoadonError之前不要开始渲染。

示例:

代码语言:javascript
复制
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等待纹理完成加载。

伪代码:

代码语言:javascript
复制
// 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();

Three.js r127

票数 2
EN

Stack Overflow用户

发布于 2021-04-02 04:32:10

我知道这不是正确的答案,但你应该看看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(加载器: THREE.Loader,url:字符串,扩展名?,xhr?)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66907398

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档