算法艺术创作
algorithmic-art
通过代码和可调参数创作生成艺术与交互式视觉效果。
cesiumjs【设计与创意】Use when building browser-based 3D globes, 3D Tiles visualization, time-dynamic geospatial data, or virtual globe applications. CesiumJS: high-performance WebGL 3D geospatial engine for interactive earth visualization.
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
name: cesiumjs description: "Use when building browser-based 3D globes, 3D Tiles visualization, time-dynamic geospatial data, or virtual globe applications. CesiumJS: high-performance WebGL 3D geospatial engine for interactive earth visualization." tags:
项目地址: https://github.com/CesiumGS/cesium
官方文档: https://cesium.com/learn/cesiumjs-learn/
API 参考: https://cesium.com/learn/cesiumjs/ref-doc/
Sandcastle: https://sandcastle.cesium.com/
许可证: Apache-2.0
CesiumJS 提供:
npm install cesium
<link href="https://cdn.jsdelivr.net/npm/cesium/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/cesium/Build/Cesium/Cesium.js"></script>
import { defineConfig } from 'vite';
import cesium from 'vite-plugin-cesium';
export default defineConfig({ plugins: [cesium()] });
需将 node_modules/cesium/Build/Cesium/{Workers,Assets,Widgets} 拷贝到输出目录,并设置 window.CESIUM_BASE_URL。
<div id="cesiumContainer" style="width:100%;height:100vh"></div>
<script type="module">
import * as Cesium from 'cesium';
import 'cesium/Build/Cesium/Widgets/widgets.css';
Cesium.Ion.defaultAccessToken = 'YOUR_ION_TOKEN';
const viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider: await Cesium.createWorldTerrainAsync(),
timeline: false, animation: false
});
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(116.397, 39.908, 5000)
});
</script>
| 概念 | 说明 |
|---|---|
Viewer | 顶层容器 |
Scene | 渲染场景,含 globe/camera/primitives |
Entity | 高层数据对象,时序、属性、可视化封装 |
DataSource | Entity 集合(CZML/GeoJSON/KML) |
Primitive | 低层渲染单元,性能最优 |
Cesium3DTileset | 3D Tiles 数据集 |
viewer.imageryLayers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({
url: 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}'
}));
viewer.terrainProvider = await Cesium.createWorldTerrainAsync({
requestVertexNormals: true,
requestWaterMask: true
});
const ds = await Cesium.GeoJsonDataSource.load('/data/poi.geojson', {
stroke: Cesium.Color.RED, fill: Cesium.Color.RED.withAlpha(0.3),
strokeWidth: 2, clampToGround: true
});
viewer.dataSources.add(ds);
viewer.flyTo(ds);
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(116.397, 39.908),
point: { pixelSize: 10, color: Cesium.Color.YELLOW },
label: { text: '天安门', font: '14px sans-serif',
verticalOrigin: Cesium.VerticalOrigin.BOTTOM }
});
viewer.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([116, 39, 121, 31]),
width: 3, material: Cesium.Color.CYAN, clampToGround: true
}
});
viewer.entities.add({
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray([116,39, 117,39, 117,40, 116,40]),
material: Cesium.Color.RED.withAlpha(0.5),
extrudedHeight: 1000
}
});
const tileset = await Cesium.Cesium3DTileset.fromUrl('https://server/tileset.json', {
maximumScreenSpaceError: 16
});
viewer.scene.primitives.add(tileset);
viewer.flyTo(tileset);
tileset.style = new Cesium.Cesium3DTileStyle({
color: { conditions: [
['${height} >= 100', 'rgba(255,0,0,0.8)'],
['true', 'rgb(180,180,180)']
]}
});
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 0),
model: { uri: '/models/airplane.glb', minimumPixelSize: 64, maximumScale: 200 }
});
const czml = [
{ id: 'document', name: 'demo', version: '1.0',
clock: { interval: '2024-01-01/2024-01-02', currentTime: '2024-01-01' } },
{ id: 'plane',
position: { epoch: '2024-01-01T00:00:00Z',
cartographicDegrees: [0, 116, 39, 1000, 3600, 117, 40, 1000] },
point: { color: { rgba: [255, 0, 0, 255] }, pixelSize: 10 } }
];
viewer.dataSources.add(Cesium.CzmlDataSource.load(czml));
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(e => {
const picked = viewer.scene.pick(e.position);
if (Cesium.defined(picked)) console.log(picked.id);
const c3 = viewer.camera.pickEllipsoid(e.position);
if (c3) {
const c = Cesium.Cartographic.fromCartesian(c3);
console.log(Cesium.Math.toDegrees(c.longitude),
Cesium.Math.toDegrees(c.latitude));
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(116.4, 39.9, 5000),
orientation: { heading: 0, pitch: -Cesium.Math.PI_OVER_FOUR, roll: 0 },
duration: 2
});
viewer.trackedEntity = entity;
dynamicScreenSpaceError、skipLevelOfDetailrequestRenderMode = true(按需渲染)clampToGround 适度使用viewer.entities.removeAll()、tileset.destroy()webglcontextlost| 问题 | 解决 |
|---|---|
| 黑屏 | 检查 CESIUM_BASE_URL 与静态资源 |
| 模型贴地不准 | HeightReference.CLAMP_TO_GROUND 或地形采样 |
| 性能卡顿 | 启用 requestRenderMode,降低 maximumScreenSpaceError |
| 国内瓦片偏移 | 使用 GCJ02→WGS84 纠偏 |
| Token 过期 | 不需要 ion 时不设置 token;或自托管 |
Cesium.Viewer 创建三维地球,设置地形和影像提供者DataSource,3D 瓦片用 Cesium3DTileset,单模型用 Entity.modelcamera.flyTo() 定位到目标区域ScreenSpaceEventHandler 处理点击拾取requestRenderMode、调整 maximumScreenSpaceErrorCesium.Ion.defaultAccessToken;自托管数据则无需Cesium.Cartesian3.fromDegrees(lon, lat, height) 将经纬度转为内部坐标clampToGround: true 或 HeightReference.CLAMP_TO_GROUNDDataSource 调用 viewer.dataSources.remove(ds),3D Tileset 调用 tileset.destroy()Assets、Workers、Widgets 目录正确复制到输出目录