Cesium
包装器import React,{useState,useEffect} from "react";
import { Viewer } from "resium";
import * as Resium from "resium";
import * as Cesium from 'cesium';
import flightData from "./data";
const terrainProvider = Cesium.createWorldTerrain();
const sleep = (ms) =>{
return new Promise((res)=>{
setTimeout(()=>res(),ms);
})
}
const positions = [];
flightData.map(dataPoint=>{
positions.push(dataPoint.longitude);
positions.push(dataPoint.latitude);
positions.push(dataPoint.height);
});
const ResiumComp=()=>{
let viewer;
const [posModel, setPosModel] = useState(null);
const [airplaneUri, setAirplaneUri] = useState(null);
const handleReady = tileset => {
if (viewer) {
//viewer.zoomTo(tileset);
}
};
const airPlaneURI = async() => {
const uri = await Cesium.IonResource.fromAssetId(246327)
setAirplaneUri(uri);
};
const movePlane = async() =>{
airPlaneURI();
for(let i=0; i<flightData.length; i++){
const dataPoint = flightData[i];
const position = Cesium.Cartesian3.fromDegrees(dataPoint.longitude, dataPoint.latitude, dataPoint.height);
setPosModel(position);
await sleep(100);
}
}
useEffect(()=>{
Cesium.Ion.defaultAccessToken = process.env.REACT_APP_CESIUM_TOKEN;
movePlane();
},[]);
return <Viewer
full terrainProvider={terrainProvider}
ref={e=>{
viewer = e && e.cesiumElement;
}}
style={{
position: "absolute",
top: 0,
left: 100,
right: 0,
bottom: 100,
}}
>
{/* <Resium.Cesium3DTileset url={Cesium.IonResource.fromAssetId(5714)} onReady={handleReady}/> */}
{
flightData.map((dataPoint,idx)=>{
const position = Cesium.Cartesian3.fromDegrees(dataPoint.longitude, dataPoint.latitude, dataPoint.height);
return <>
<Resium.Entity
key={`point-${idx}`}
name="Tokyo"
description = {`Location: (${dataPoint.longitude}, ${dataPoint.latitude}, ${dataPoint.height})`}
position={position}
>
<Resium.PointGraphics pixelSize={10} />
</Resium.Entity>
</>
})
}
{/* polyline */}
<Resium.Entity>
<Resium.PolylineGraphics
show
width={3}
material={Cesium.Color.RED}
positions={Cesium.Cartesian3.fromDegreesArrayHeights(positions)}
/>
</Resium.Entity>
{/* Model */}
{
(airplaneUri&&posModel)&&<Resium.Entity
tracked
position={posModel}
>
<Resium.ModelGraphics
scale={1}
uri={airplaneUri}
minimumPixelSize={100}
runAnimations
show
color={Cesium.Color.WHITE}
/>
</Resium.Entity>
}
</Viewer>
}
export default ResiumComp;
此处 PolylineGraphics
未呈现。当我检查代码时,我明白了,问题是由于状态变量的变化而出现的。
因此,当我注释掉 setPosModel(position);
行时,折线正在呈现。
更改以下功能代码
const movePlane = async() =>{
airPlaneURI();
for(let i=0; i<flightData.length; i++){
const dataPoint = flightData[i];
const position = Cesium.Cartesian3.fromDegrees(dataPoint.longitude, dataPoint.latitude, dataPoint.height);
// after commenting this line, there is no issue
//setPosModel(position);
await sleep(100);
}
}
折线图形在任何情况下都应该呈现,但我无法弄清楚。
答案 0 :(得分:0)
这个问题与铯/resium无关,而是自身反应。
请注意,在您的 useEffect()
方法中,您调用 movePlane()
,然后调用 setPosModel(position)
- 一个状态更改函数,它将重新渲染应用程序,它将调用 useEffect()
...
知道我要去哪里了吗?
有多种解决方案可以阻止您的应用无限重新渲染。最简单的方法是遵循 react 建议并将 movePlane
包裹在 useCallback()
钩子中,如下所示:
const movePlane = useCallback(() => async() =>{
airPlaneURI();
for(let i=0; i<flightData.length; i++){
const dataPoint = flightData[i];
const position = Cesium.Cartesian3.fromDegrees(dataPoint.longitude, dataPoint.latitude, dataPoint.height);
setPosModel(position);
await sleep(100);
}
}, [])
当然,您还必须将 movePlane
添加到 useEffect()
的依赖项数组中:
useEffect(()=>{
Cesium.Ion.defaultAccessToken = process.env.REACT_APP_CESIUM_TOKEN;
movePlane();
},[movePlane]);
旁注:您的代码需要考虑许多问题!
例如,为什么在 for 循环的每次迭代之后调用 setPosModel()
?据我所知,flightData
是一个巨大的数组,你也应该修复它