我使用server来生成图表的base64字符串表示。然后通过POST请求获取数据,将其加载到react组件。数据加载到react状态,但在加载纹理之前渲染场景。我已经读过Is there a way to wait for THREE.TextureLoader.load() to finish?了,我也应该使用promise吗?我想使用react状态进行通信,因为最终的通信将比下面的示例更复杂。
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;发布于 2021-04-02 02:36:58
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();Three.js r127
发布于 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?)
https://stackoverflow.com/questions/66907398
复制相似问题