cesium-expert
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCesium 전문가
Cesium专家
$ARGUMENTS CesiumJS 관련 질문에 답변하고 구현을 도와드립니다.
$ARGUMENTS 为您解答CesiumJS相关问题并协助实现。
@pf-dev/map 패키지 구조
@pf-dev/map 包结构
packages/map/src/
├── components/
│ ├── MapViewer.tsx # 메인 뷰어 컴포넌트
│ ├── Imagery.tsx # 이미지 레이어
│ ├── Terrain.tsx # 지형
│ └── Tiles3D.tsx # 3D 타일셋
├── stores/
│ ├── useMapStore.ts # 지도 상태
│ ├── useCameraStore.ts # 카메라 상태
│ └── useFeatureStore.ts # Feature 관리
├── hooks/
│ └── useCamera.ts # 카메라 제어
└── types/
└── index.tspackages/map/src/
├── components/
│ ├── MapViewer.tsx # 主查看器组件
│ ├── Imagery.tsx # 影像图层
│ ├── Terrain.tsx # 地形
│ └── Tiles3D.tsx # 3D瓦片集
├── stores/
│ ├── useMapStore.ts # 地图状态
│ ├── useCameraStore.ts # 相机状态
│ └── useFeatureStore.ts # 要素管理
├── hooks/
│ └── useCamera.ts # 相机控制
└── types/
└── index.ts주요 패턴
主要模式
MapViewer 사용
使用MapViewer
tsx
import { MapViewer, Imagery, Terrain } from "@pf-dev/map";
function Map() {
return (
<MapViewer
options={{
baseLayerPicker: false,
geocoder: false,
}}
>
<Imagery provider="vworld" />
<Terrain provider="cesium-world" />
</MapViewer>
);
}tsx
import { MapViewer, Imagery, Terrain } from "@pf-dev/map";
function Map() {
return (
<MapViewer
options={{
baseLayerPicker: false,
geocoder: false,
}}
>
<Imagery provider="vworld" />
<Terrain provider="cesium-world" />
</MapViewer>
);
}카메라 제어
相机控制
tsx
import { useCameraStore } from "@pf-dev/map";
function Controls() {
const { flyTo, lookAt, zoomTo } = useCameraStore();
const handleFlyToSeoul = () => {
flyTo({
destination: Cesium.Cartesian3.fromDegrees(126.978, 37.5665, 10000),
duration: 2,
});
};
return <button onClick={handleFlyToSeoul}>서울로 이동</button>;
}tsx
import { useCameraStore } from "@pf-dev/map";
function Controls() {
const { flyTo, lookAt, zoomTo } = useCameraStore();
const handleFlyToSeoul = () => {
flyTo({
destination: Cesium.Cartesian3.fromDegrees(126.978, 37.5665, 10000),
duration: 2,
});
};
return <button onClick={handleFlyToSeoul}>前往首尔</button>;
}Feature 관리
要素管理
tsx
import { useFeatureStore } from "@pf-dev/map";
function FeatureManager() {
const { addEntity, removeEntity, findByProperty } = useFeatureStore();
const addMarker = (position: Cesium.Cartesian3) => {
addEntity({
id: `marker-${Date.now()}`,
position,
billboard: {
image: "/marker.png",
scale: 1,
},
properties: {
type: "cctv",
name: "CCTV 1",
},
});
};
const findCCTVs = () => {
return findByProperty("type", "cctv");
};
}tsx
import { useFeatureStore } from "@pf-dev/map";
function FeatureManager() {
const { addEntity, removeEntity, findByProperty } = useFeatureStore();
const addMarker = (position: Cesium.Cartesian3) => {
addEntity({
id: `marker-${Date.now()}`,
position,
billboard: {
image: "/marker.png",
scale: 1,
},
properties: {
type: "cctv",
name: "CCTV 1",
},
});
};
const findCCTVs = () => {
return findByProperty("type", "cctv");
};
}자주 묻는 질문
常见问题
Q: 성능이 느려요
Q: 性能变慢
A: 최적화 방법
- 설정 (필요할 때만 렌더)
requestRenderMode: true - 3D 타일셋 LOD 설정
- 엔티티 수 제한 (1000개 이상이면 Primitive 사용)
- 로 숨긴 엔티티 정리
show: false
tsx
<MapViewer
options={{
requestRenderMode: true,
maximumRenderTimeChange: Infinity,
}}
/>A: 优化方法
- 设置(仅在需要时渲染)
requestRenderMode: true - 配置3D瓦片集LOD
- 限制实体数量(超过1000个时使用Primitive)
- 清理通过隐藏的实体
show: false
tsx
<MapViewer
options={{
requestRenderMode: true,
maximumRenderTimeChange: Infinity,
}}
/>Q: 이미지 레이어 안 보여요
Q: 影像图层不显示
A: 토큰 확인
env
VITE_ION_CESIUM_ACCESS_TOKEN=your-token
VITE_VWORLD_API_KEY=your-keyA: 检查令牌
env
VITE_ION_CESIUM_ACCESS_TOKEN=your-token
VITE_VWORLD_API_KEY=your-keyQ: 카메라가 지하로 들어가요
Q: 相机钻入地下
A: 지형 충돌 설정
tsx
viewer.scene.globe.depthTestAgainstTerrain = true;
viewer.scene.screenSpaceCameraController.enableCollisionDetection = true;A: 设置地形碰撞
tsx
viewer.scene.globe.depthTestAgainstTerrain = true;
viewer.scene.screenSpaceCameraController.enableCollisionDetection = true;Q: 클릭 이벤트 처리
Q: 处理点击事件
tsx
import { useMapStore } from "@pf-dev/map";
function ClickHandler() {
const viewer = useMapStore((state) => state.viewer);
useEffect(() => {
if (!viewer) return;
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction((click: { position: Cesium.Cartesian2 }) => {
const picked = viewer.scene.pick(click.position);
if (Cesium.defined(picked)) {
console.log("Picked:", picked.id);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
return () => handler.destroy();
}, [viewer]);
}tsx
import { useMapStore } from "@pf-dev/map";
function ClickHandler() {
const viewer = useMapStore((state) => state.viewer);
useEffect(() => {
if (!viewer) return;
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction((click: { position: Cesium.Cartesian2 }) => {
const picked = viewer.scene.pick(click.position);
if (Cesium.defined(picked)) {
console.log("选中对象:", picked.id);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
return () => handler.destroy();
}, [viewer]);
}좌표 변환
坐标转换
tsx
// 위경도 → Cartesian3
const position = Cesium.Cartesian3.fromDegrees(126.978, 37.5665, 100);
// Cartesian3 → 위경도
const cartographic = Cesium.Cartographic.fromCartesian(position);
const lng = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
// 화면 좌표 → Cartesian3
const cartesian = viewer.camera.pickEllipsoid(screenPosition, viewer.scene.globe.ellipsoid);tsx
// 经纬度 → Cartesian3
const position = Cesium.Cartesian3.fromDegrees(126.978, 37.5665, 100);
// Cartesian3 → 经纬度
const cartographic = Cesium.Cartographic.fromCartesian(position);
const lng = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
// 屏幕坐标 → Cartesian3
const cartesian = viewer.camera.pickEllipsoid(screenPosition, viewer.scene.globe.ellipsoid);3D 타일셋 로딩
加载3D瓦片集
tsx
import { Tiles3D } from "@pf-dev/map";
<Tiles3D
url="/tiles/building/tileset.json"
onReady={(tileset) => {
viewer.zoomTo(tileset);
}}
style={{
color: {
conditions: [
["${height} > 100", "color('red')"],
["true", "color('white')"],
],
},
}}
/>;tsx
import { Tiles3D } from "@pf-dev/map";
<Tiles3D
url="/tiles/building/tileset.json"
onReady={(tileset) => {
viewer.zoomTo(tileset);
}}
style={{
color: {
conditions: [
["${height} > 100", "color('red')"],
["true", "color('white')"],
],
},
}}
/>;Context7 참고
参考Context7
CesiumJS 최신 API가 필요하면 Context7로 조회하세요.
如果需要CesiumJS最新API,请通过Context7查询。