2021.07.08
1417
Cesium是一款开源的基于JavaScript的3D地图框架。
Cesium应用程序代码在 Build 文件夹下,可将Build/Cesium文件夹放进项目目录中引入,或引入第三方cdn
<script src="https://cesium.com/downloads/cesiumjs/releases/1.62/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.62/Build/Cesium/Widgets/widgets.css" rel="stylesheet">复制代码
Cesium支持通过npm安装,配合webpack打包和使用import来引入模块。教程
上述的配置较复杂,也可以结合 create-react-app 脚手架快速搭建Cesium项目 教程
<script src="../Build/Cesium/Cesium.js"></script>
@import url(../Build/Cesium/Widgets/widgets.css);
<div id="cesiumContainer"></div>复制代码
var viewer = new Cesium.Viewer('cesiumContainer');
4. 通过Cesium ion可以把数据添加到用户的CesiumJS应用中,而且使用贴图和Cesium世界地形都需要ion的支持,所以在使用Cesium开发前需要申请access token。
(1)打开 cesium.com/ion/ 注册一个新的账户。
(2)登录后进入 Access Tokens page页面 ,复制 token,在页面中引入
Cesium.Ion.defaultAccessToken = '<YOUR ACCESS TOKEN HERE>';
Cesium Viewer自带的组件
//demo: 保留常用组件
var viewer = new Cesium.Viewer('cesiumContainer', {
animation: false, //动画控制不显示
timeline: false, //时间线不显示
fullscreenButton: false, //全屏按钮不显示
baseLayerPicker: false // 底图选择不显示
});
viewer._cesiumWidget._creditContainer.style.display = "none"; //不显示logo复制代码
(2)设置语言。cesium没有修改语言功能,所以需要通过组件的相关api接口,逐个修改。实在没有api可通过修改DOM结点和样式的方式修改
viewer.sceneModePicker.viewModel.tooltip3D = "三维";
viewer.sceneModePicker.viewModel.tooltip2D = "二维";
viewer.sceneModePicker.viewModel.tooltipColumbusView = "哥伦布视图";
viewer.homeButton.viewModel.tooltip = "初始位置";
viewer.geocoder.container.getElementsByClassName('cesium-geocoder-input')[0].setAttribute("placeholder","搜索");
viewer.navigationHelpButton.viewModel.tooltip = "操作指南";
var clickHelper = viewer.navigationHelpButton.container.getElementsByClassName("cesium-click-navigation-help")[0];
var touchHelper = viewer.navigationHelpButton.container.getElementsByClassName("cesium-touch-navigation-help")[0];
var button = viewer.navigationHelpButton.container.getElementsByClassName("cesium-navigation-button-right")[0];
button.innerHTML = button.innerHTML.replace(">Touch", ">手势");
button = viewer.navigationHelpButton.container.getElementsByClassName("cesium-navigation-button-left")[0];
button.innerHTML = button.innerHTML.replace(">Mouse", ">鼠标");
var click_help_pan = clickHelper.getElementsByClassName("cesium-navigation-help-pan")[0];
click_help_pan.innerHTML = "平移";
var click_help_pan_details = click_help_pan.parentNode.getElementsByClassName("cesium-navigation-help-details")[0];
click_help_pan_details.innerHTML = "按下左键 + 拖动";
var click_help_zoom = clickHelper.getElementsByClassName("cesium-navigation-help-zoom")[0];
click_help_zoom.innerHTML = "旋转";
click_help_zoom.parentNode.getElementsByClassName("cesium-navigation-help-details")[0].innerHTML = "按下右键+拖动";
click_help_zoom.parentNode.getElementsByClassName("cesium-navigation-help-details")[1].innerHTML = "";
var click_help_rotate = clickHelper.getElementsByClassName("cesium-navigation-help-rotate")[0];
click_help_rotate.innerHTML = "缩放";
click_help_rotate.parentNode.getElementsByClassName("cesium-navigation-help-details")[0].innerHTML = "滚动鼠标滚轮";
click_help_rotate.parentNode.getElementsByClassName("cesium-navigation-help-details")[1].innerHTML = "";
//触屏操作
var touch_help_pan = touchHelper.getElementsByClassName("cesium-navigation-help-pan")[0];
touch_help_pan.innerHTML = "平移";
touch_help_pan.parentNode.getElementsByClassName("cesium-navigation-help-details")[0].innerHTML = "单指拖动";
var touch_help_zoom = touchHelper.getElementsByClassName("cesium-navigation-help-zoom")[0];
touch_help_zoom.innerHTML = "缩放";
touch_help_zoom.parentNode.getElementsByClassName("cesium-navigation-help-details")[0].innerHTML = "双指捏合";
var touch_help_tilt = touchHelper.getElementsByClassName("cesium-navigation-help-rotate")[0];
touch_help_tilt.innerHTML = "俯仰";
touch_help_tilt.parentNode.getElementsByClassName("cesium-navigation-help-details")[0].innerHTML = "双指同向拖动";
var touch_help_rotate = touchHelper.getElementsByClassName("cesium-navigation-help-tilt")[0];
touch_help_rotate.innerHTML = "旋转";
touch_help_rotate.parentNode.getElementsByClassName("cesium-navigation-help-details")[0].innerHTML = "双指反向拖动";复制代码
BaseLayerPicker 组件提供了多种底图切换,但通常我们并不需要切换底图,所以可以在Viewer初始化时就配置好影像服务。在多种服务商中MapBox的地图比较清晰而且api也比较简单,能满足需求,如果要使用其他服务商影像请参考这里: 影像服务
var viewer = new Cesium.Viewer('cesiumContainer',{
imageryProvider: new Cesium.MapboxImageryProvider({
mapId:'mapbox.satellite'
})
}
// mapbox.satellite 卫星图像
// mapbox.streets 街道图像复制代码
Cesium支持全球高程投影、地形地势、水形数据,包括海洋、湖泊、河流、山峰、峡谷等地形数据。添加地形和光照后更能体现Cesium 三维地图的优势可用于虚拟场景展示。这里可以直接使用Cesium默认提供的世界地形服务(加载地形数据会导致渲染延迟)
var viewer = new Cesium.Viewer('cesiumContainer',{
imageryProvider: new Cesium.MapboxImageryProvider({
mapId:'mapbox.satellite'
}),
terrainProvider: new Cesium.createWorldTerrain({
requestWaterMask : true, // 水特效
requestVertexNormals : true // 照明特效
})
});
viewer.scene.globe.depthTestAgainstTerrain = true; //让最前面、最上面的objects可见
viewer.scene.globe.enableLighting = true; // 基于太阳位置的光照 复制代码
通过上面步骤已经生成了一个较逼真的3维场景,接下来需要定位到我们想要展示的区域。定位区域使用了viewer.scene中的camera属性,可以通过直接设置它的位置和方向来控制当前可见的域。
(1)坐标类型
(2)Camera API
var initialOrientation = new Cesium.HeadingPitchRoll.fromDegrees(7.1077496389876024807, -31.987223091598949054, 0.025883251314954971306);
viewer.scene.camera.setView({
destination : Cesium.Cartesian3.fromDegrees(114.0595699327, 22.542875036, 10000), // 位置
orientation : { // 角度
heading : initialOrientation.heading,
pitch : initialOrientation.pitch,
roll : initialOrientation.roll
}
});复制代码
现在已经实现了定位到我们想要看到的区域了,下面将会补充交互的部份~
使用Cesium的Entity API可以绘制空间数据,如点,图标,文字标注,折线,模型,图形和立体图形。创建3D地图的一个重要应用方向就是(空间)数据可视化用于更好进行数据统计和决策。如可以在地图上绘制点表示地铁站点,绘制线表示地铁线用来展示站点和线路分布信息;绘制柱状图表示各地人口数量用来展示人口分布关系等。 下面具体介绍几类实体的绘制的用法。
1. 通过viewer.entities.add(Entity对象)手动绘制
// polygon 多边形
{
hierarchy : 多边形位置,由至少三个点的坐标相连形成的多边形
height: 相对于地球表面的高度
extrudedHeight:相对于地球表面凸出的高度,用来生成立体形状
material: 填充进多边形的材料,可以是颜色、图片等
outline: 轮廓可见
outlineColor: 轮廓颜色
}
// poline 线条
{
positions : 线条位置,由至少两个点坐标相连
width : 线条宽度
arcType : 类型 默认为贴合地面
material : 填充进线条的材料
}
// point 点
绘制点的位置需要在 entity对象中定义
{
pixelSize : 点大小
color : 颜色,
outlineColor : 轮廓颜色, outlineWidth : 轮廓宽度
}
// model 3d模型
绘制点的位置需要在 entity对象中定义{
uri : 模型的资源路径
scale: 缩放,默认为 1
}
var entities1 = viewer.entities.add({
name : 'entitites1',
polygon : {
hierarchy : Cesium.Cartesian3.fromDegreesArray([
-109.080842,45.002073,
-105.91517,45.002073,
-104.058488,44.996596,
-104.053011,43.002989,
-104.053011,41.003906,
-105.728954,40.998429,
-107.919731,41.003906,
-109.04798,40.998429,
-111.047063,40.998429,
-111.047063,42.000709,
-111.047063,44.476286,
-111.05254,45.002073]),
height : 0,
material : Cesium.Color.RED.withAlpha(0.5),
outline : true,
outlineColor : Cesium.Color.BLACK
}
});复制代码
此外还有立方体、圆和椭圆、墙、球等,详见API示例。
2. 通过资源文件绘制viewer.dataSources.add(dataSource);。实际的应用多数都是加载资源文件来绘制实体,但资源文件geojson等都依赖于数据转换和资源发布,这属于专业GIS开发了。
var promise = Cesium.GeoJsonDataSource.load('./states.json'); 加载资源文件 geojson
promise.then(function(dataSource) {
viewer.dataSources.add(dataSource);
// 可以遍历各个entity进行操作,如填充颜色、设置高度等
var entities = dataSource.entities.values;
var colorHash = {};
for (var i = 0; i < entities.length; i++) {
var entity = entities[i];
//Set the polygon material to our random color.
entity.polygon.material = Color.fromRandom({ alpha : 1.0 });;
//Remove the outlines.
entity.polygon.outline = false;
//Extrude the polygon based on the state's population.
entity.polygon.extrudedHeight = entity.properties.Population / 50.0;
}
}).otherwise(function(error){ //Display any errrors encountered while loading.
window.alert(error);
});复制代码
小结:
对于小数据量和简单的实体,适合这种viewr.entities的方式,比如全国省份人口统计用柱状图展示,只需要知道每个省的一个点坐标和人口数即可;还有加入模型实体,只需准备模型文件和设置放置的点坐标即可。 对于大数据量或复杂的实体(如上图)则适合使用viewer.dataSources方式绘制。
2023.03.10
595
macOS Monterey12.3.1安装VirtualBox6.1.34后报错Kernel driver not installed (rc=-1908) 解决方法