cesium入门笔记
- 一、下载源码,源码介绍
- 二、html案例体验
- 三、cesium中的类介绍
- 1.它们分别是:
- 2.四大类的完整演示代码:
- 四、cesium的坐标与转换
- 五、相机系统介绍
- 六、地图、地形的加载
- 七、建筑体添加和使用
- 八、空间数据加载
- 1、加载数据
- 2、对加载的空间数据进行管理
- 3、空间数据加载的整体代码如下:
- 九、鼠标交互,数据查询
- 1、鼠标左键点击图片后提示弹框
- 2、自定义弹框
- 十、三维数据3dtiles
- 十一、时间系统、粒子系统
- 1、时间系统
- 2、粒子系统
- 十二、动态数据格式CZML
学习视频参考: 1、Cesium.JS从入门到精通
一、下载源码,源码介绍
官网下载:cesium.js官方网站源码包下载
如果下载较慢,可使用已经下好的:cesium1.89官网源码
下面所有案例的每一课的代码:cesium学习笔记代码
二、html案例体验
1、新建一个工程,下面包含libs和src两个目录,libs下面放cesium的源码build的整个cesium文件夹,如下图
2、新建html,编写以下内容,用Live server 打开即可看到效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=s, initial-scale=1.0">
<title>cesium第一课</title>
//cesium.js引入
<script src="../libs/Cesium/Cesium.js"></script>
//cesium样式引入
<link href="../libs/Cesium/Widgets/widgets.css" rel="stylesheet">
//导入cesium的类型声明,有这个才会有快捷智能提示
<script src="../libs/Cesium/Cesium.d.ts"></script>
<style>
html,
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="puiedu-cesiumContainer"></div>
<script>
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5MWVkMjllNy03ZjY4LTQ3YmQtOTgxOC05NGQ5YTU0ZjM5ZGEiLCJpZCI6MzU5Nywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTUzODE5MTUyM30.dtS2F3-q2fGoA93N7cFl-LCikK-Rjk7v01WWA-RqCxg'
const viewer = new Cesium.Viewer('puiedu-cesiumContainer');
</script>
</body>
</html>
3、运行后如下图:
三、cesium中的类介绍
1.它们分别是:
1、Viewer查看器类
(1)、它是cesium展示三维要素内容的主要窗口,它不仅仅是包含三维地球的视窗,还包含了一些基础控件,在定义Viewer对象的同时需要设定基础部件、图层等的初始化状态
(2)、Viewer创建代码:new Cesium.Viewer(cesiumContainer,options);
。
参数说明:第一个参数cesiumContainer我们用于指定地图主窗口diy的id,第二个参数options是Viewer的可选设置参数,我们可以对基础地理环境进行设置。
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5MWVkMjllNy03ZjY4LTQ3YmQtOTgxOC05NGQ5YTU0ZjM5ZGEiLCJpZCI6MzU5Nywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTUzODE5MTUyM30.dtS2F3-q2fGoA93N7cFl-LCikK-Rjk7v01WWA-RqCxg';
const viewer = new Cesium.Viewer('puiedu-cesiumContainer', {
animation: false,//动画小组件
timeline: false,//左下角仪表
});
viewer.scene.globe.show = true//地图显示,默认是true
2、Scene场景类
(1)、它是Cesium中Scene是非常重要的类,是所有3D图形对象的容器,是在viewer内部隐式创建的,也可以对基础地理环境进行设置,包括地图、地形等。
(2)、需要注意的是在viewer中设置图层等价于在scene中设置图层,代码验证:console.log(viewer.imgerLaters == viewer.scene.imgerLaters);//输出true
(3)、还可以对场景数据进行设置,cesium底层空间数据绘制方法是依赖Primitive API,可以根据图形学原理绘制灵活的高级图形
(4)、还可以对场景进行交互,比如鼠标事件对场景的控制、相机事件,可以修改场景环境,比如修改地图显示隐藏、光照强度、图层样式、地形数据、在图层上绘制点、线、面、体
viewer.scene.camera.setView({//通过scene控制相机对视口进行切换
destination: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 1000)//设置经纬度和高度
})
3、Entity实体类
(1)、Entity是由Primitive封装而来的,Entity不是属于Scene,它封装程度高、构造简单、使用便捷使得开发者专注于数据的呈现,不必关心底层的可视化机制,还提供了用于构建复杂的、时间动态可视化的结构,与静态数据自然的结合在一起;EntityAPI 能够提供灵活的、高性能的可视化,同时提供一致性的、易于学习、易于使用的接口。
(2)、代码示例了解Entity
const entity = viewer.entities.add({//创建一个Entity点对象
position: Cesium.Cartesian3.fromDegrees(116.39, 39.9, 400),//设置经纬度和高度
point: {
pixelSize: 100,//设置点大小
color: new Cesium.Color(0, 1, 0, 1)//设定点颜色
}
})
viewer.trackedEntity = entity;//将摄像头设置在圆点处(track跟踪)
4、DataSourceCollection数据源集合类
(1)、它是cesium中加载矢量数据的最主要方式之一,最大的特点是支持矢量数据集和外部文件的调用,主要有三种调用方法,分别为CzmlDataSource加载Czml、KmlDataSource加载Kml、GeoJsonDataSource加载GeoJson格式数据,在gis开发中加载矢量数据是必不可少的功能。将矢量数据转化为以上任何一种方式,便可以在cesium中实现矢量数据的加载和存取。
(2)、示例演示:geojson数据获取:geojson数据获取
//DataSource用于将任意数据转换为EntityCollection,这里调用的是geojson数据
viewer.dataSources.add(
Cesium.GeoJsonDataSource.load(
"./data/hubei.json"
)
)
2.四大类的完整演示代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>cesium第一课</title>
<!-- cesium.js引入 -->
<script src="../libs/Cesium/Cesium.js"></script>
<!-- cesium样式引入 -->
<link href="../libs/Cesium/Widgets/widgets.css" rel="stylesheet">
<!-- 导入cesium的类型声明,有这个才会有快捷智能提示(已屏蔽,无效) -->
<!-- <script src="../libs/Cesium/Cesium.d.ts"></script> -->
<!-- <reference path="../libs/Cesium/Cesium.d.ts" /> -->
<style>
html,
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="puiedu-cesiumContainer"></div>
<script>
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5MWVkMjllNy03ZjY4LTQ3YmQtOTgxOC05NGQ5YTU0ZjM5ZGEiLCJpZCI6MzU5Nywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTUzODE5MTUyM30.dtS2F3-q2fGoA93N7cFl-LCikK-Rjk7v01WWA-RqCxg';
const viewer = new Cesium.Viewer('puiedu-cesiumContainer', {
animation: false,//动画小组件
timeline: false,//左下角仪表
});
viewer.scene.globe.show = true//地图显示,默认是true
console.log(viewer.imgerLaters == viewer.scene.imgerLaters);//输出true
viewer.scene.camera.setView({//通过scene控制相机对视口进行切换
destination: Cesium.Cartesian3.fromDegrees(113.37377, 31.717497, 1000000)//设置经纬度和高度
})
const entity = viewer.entities.add({//创建一个Entity点对象
position: Cesium.Cartesian3.fromDegrees(113.37377, 31.717497, 1000000),//设置经纬度和高度
point: {
pixelSize: 100,//设置点大小
color: new Cesium.Color(0, 1, 0, 1)//设定点颜色
}
})
viewer.trackedEntity = entity;//将摄像头设置在圆点处(track跟踪)
//DataSource用于将任意数据转换为EntityCollection,这里调用的是geojson数据
viewer.dataSources.add(
Cesium.GeoJsonDataSource.load(
"./data/hubei.json"
)
)
</script>
</body>
</html>
代码运行效果如下:
四、cesium的坐标与转换
1、cesium具用真实地理坐标的三维球体,用户通过二维屏幕与cesium进行操作,我们要把三维模型绘制到三维球体上,就需要在地理坐标和屏幕坐标之间做转换,下面介绍下cesium的主要坐标系:
(1)、WGS84经纬度坐标系 (没有实际的对象)。
(2)、WGS84弧度坐标系 (Cartographic)
(3)、笛卡尔空间直角坐标系 (Cartesian3)
(4)、平面坐标系,也叫屏幕坐标系 (Cartesian2)
(5)、4D笛卡尔坐标系 (Cartesian4)
2、坐标系详解:
(1)、首先前两个都是WGS84坐标系,WGS84:World Geodetic System 1984,是为GPS全球定位系统使用而建立的坐标系统。坐标原点为地球质心
在cesium中没有实际的对象来描述WGS84经纬度坐标系的,都是以弧度的方式进行运用的,也就是当前的这个对象类new Cesium.Cartographic(longitude, latitude, height)
,这个类有三个构造参数,经度、纬度、高度,这个函数内部的弧度计算采用:弧度=Π/180*经纬度
(2)、笛卡尔空间直角坐标系,以空间中O点为原点,建立三条两两垂直的数轴X、Y、Z
笛卡尔直角坐标系的原点就是椭球的中心,我们通过new Cesium.Cartesian3(x,y,z)
来构建Cartesian3的类对象,三个参数xyz分别代表三根数轴上的值
(3)、平面坐标系,也叫屏幕坐标系。它是一个二维的笛卡尔坐标系。屏幕左上角为原点水平方向为x,垂直方向为y,向下为正。
构造对象new Cesium.Cartesian2(x,y)
3、坐标转换
(1)、经纬度和WGS84弧度的相互转换:弧度= Π/180*经纬度角度
、经纬度角度=180/Π*弧度
。在cesium中可以用两种方式实现转换:
- 构造函数法生成WGS84弧度坐标对象
new Cesium.Cartographic(longitude弧度,latitude弧度,height米)
, - 静态函数法构建WGS84弧度坐标对象
var cartographic= Cesium.Cartographic.fromDegrees(longitude经度,latitude纬度,height米)
、var cartographic= Cesium.Cartographic.fromRadians(longitude弧度, latitude弧度,height米)
(2)、笛卡尔空间直角坐标系转换为WGS84坐标系:在cesium中可以使用var cartographic= Cesium.Cartographic.fromCartesian(cartesian3)
、var cartographic= Cesium.Ellipsoid.WGS84.cartesianToCartographic(cartesian3)
、或者批量传入数组转 var cartographics=Cesium.Elipsoid.WGS84.cartesianArrayToCartographicArray([cartesian1,cartesian2,cartesian3])
(3)、平面坐标系转笛卡尔空间直角坐标系、屏幕坐标转WGS84坐标,这里的场景坐标是包含了地形、倾斜、模型的坐标var cartesian3= viewer.scene.pickPosition(Cartesian2)
(4)、屏幕坐标转地表坐标var cartesian3=viewer.scene.globe.pick(viewer.camera.getPickRay(Cartesian2),viewer.scene);
这里是地球表面的WGS84坐标,包含地形,不包括模型、倾斜摄影表面
(5)、平面坐标转椭球面坐标var cartesian3=viewer.scene.camera.pickEllipsoid(Cartesian2)
,这里的椭球面坐标是参考椭球的WGS84坐标,不包含地形、模型、倾斜摄影表面
(6)、笛卡尔空间直角坐标系转平面坐标系var cartesian2=Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene,cartesian3)
,这个静态函数需要传入场景与笛卡尔空间坐标2个参数,执行成功后返回平面坐标的数值
五、相机系统介绍
官方文档api参考:Cesium.Camera
在二维地图中,如果我们要查看某个地方,只需要定位经纬度即可,但是三维地图不仅仅需要经纬度确定视点位置,还需要视线方向,例如观察某物体找到了物体位置,但是视线方向反了,那么在视域中是看不到物体的,所以相机的存在就是为了控制场景中的视域。
1、相机系统方法介绍
(1)、setView():setView通过定义相机飞行目的地的三维坐标和视线方向,将视角直接切换到所设定的视域范围内,设置一个常量,用于存储飞行的目的地的坐标
(2)、flyTo():视角跳转,过渡跳转,有过程
(3)、lookAt():lookAt将视角设置到跳转的设置的目的地上,但是用鼠标任意旋转视角方向,是不会改变其位置的,一般用于锁定某个场景的视角
(4)、viewBoundingSphere() 视角切换效果和setView一样,没有飞行过渡,直接切换,但是它可以给一个指定的目标点,从多个角度更好的观测物体样式和状态,也就是说相机围绕目标点旋转而不是地球,比如加载glb
六、地图、地形的加载
代码有详细注释
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>cesium第二课,加载自定义地图</title>
<!-- cesium.js引入 -->
<script src="../libs/Cesium/Cesium.js"></script>
<!-- cesium样式引入 -->
<link href="../libs/Cesium/Widgets/widgets.css" rel="stylesheet">
<!-- 导入cesium的类型声明,有这个才会有快捷智能提示(已屏蔽,无效) -->
<!-- <script src="../libs/Cesium/Cesium.d.ts"></script> -->
<!-- <reference path="../libs/Cesium/Cesium.d.ts" /> -->
<style>
html,
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="puiedu-cesiumContainer"></div>
<script>
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5MWVkMjllNy03ZjY4LTQ3YmQtOTgxOC05NGQ5YTU0ZjM5ZGEiLCJpZCI6MzU5Nywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTUzODE5MTUyM30.dtS2F3-q2fGoA93N7cFl-LCikK-Rjk7v01WWA-RqCxg';
let esri = new Cesium.ArcGisMapServerImageryProvider({
url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"
})//用一个变量存储新地图的信息,这里我们使用的是arcgis地图服务
const viewer = new Cesium.Viewer('puiedu-cesiumContainer', {
animation: false,//动画小组件
timeline: false,//左下角仪表,
baseLayerPicker: false,//默认的地图按钮设置为隐藏
imageryProvider: esri,//viewer内的imageryProvider属性用于设置地图,这里加载arcgis的地图
terrainProvider: new Cesium.CesiumTerrainProvider({//此时地球表面是没有比如山脉3d地形的,所以下面加载地形数据放入引入的地形;CesiumTerrainProvider方法是将地形数据,转换为Cesium可以访问的格式
url:Cesium.IonResource.fromAssetId(1),//url 属性用于放入地形服务器的地址
requestVertexNormals:true,//requestVertexNormals属性设置为true,可以增加法线,用于提高光照效果
requestWaterMask:true,//可以增加水面特效
}),
});
viewer.scene.globe.show = true//地图显示,默认是true
// var layer=viewer.imageryLayers.addImageryProvider(
// new Cesium.IonImageryProvider({assetId:3812})
// )//测试夜晚地图
</script>
</body>
</html>
代码执行效果:
七、建筑体添加和使用
代码如下,都有详细注释:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>cesium第二课,加载自定义地图</title>
<!-- cesium.js引入 -->
<script src="../libs/Cesium/Cesium.js"></script>
<!-- cesium样式引入 -->
<link href="../libs/Cesium/Widgets/widgets.css" rel="stylesheet">
<!-- 导入cesium的类型声明,有这个才会有快捷智能提示(已屏蔽,无效) -->
<!-- <script src="../libs/Cesium/Cesium.d.ts"></script> -->
<!-- <reference path="../libs/Cesium/Cesium.d.ts" /> -->
<style>
html,
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="puiedu-cesiumContainer"></div>
<script>
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5MWVkMjllNy03ZjY4LTQ3YmQtOTgxOC05NGQ5YTU0ZjM5ZGEiLCJpZCI6MzU5Nywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTUzODE5MTUyM30.dtS2F3-q2fGoA93N7cFl-LCikK-Rjk7v01WWA-RqCxg';
//----------------------- 地图、地形的添加--------------------------
let esri = new Cesium.ArcGisMapServerImageryProvider({
url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"
})//用一个变量存储新地图的信息,这里我们使用的是arcgis地图服务
const viewer = new Cesium.Viewer('puiedu-cesiumContainer', {
animation: false,//动画小组件
timeline: false,//左下角仪表,
baseLayerPicker: false,//默认的地图按钮设置为隐藏
imageryProvider: esri,//viewer内的imageryProvider属性用于设置地图
terrainProvider: new Cesium.CesiumTerrainProvider({//此时地球表面是没有比如山脉3d地形的,所以下面加载地形数据放入引入的地形;CesiumTerrainProvider方法是将地形数据,转换为Cesium可以访问的格式
url:Cesium.IonResource.fromAssetId(1),//url 属性用于放入地形服务器的地址
requestVertexNormals:true,//requestVertexNormals属性设置为true,可以增加法线,用于提高光照效果
requestWaterMask:true,//可以增加水面特效
}),
});
viewer.scene.globe.show = true//地图显示,默认是true
// var layer=viewer.imageryLayers.addImageryProvider(
// new Cesium.IonImageryProvider({assetId:3812})
// )//测试夜晚地图
//----------------------- 地图、地形的添加结束--------------------------
//----------------------- 建筑物的添加使用--------------------------
let tileset=viewer.scene.primitives.add(//Viewer中的scene是Cesium虚拟场景中所有3D图形对象和状态的容器,它的primitives属性用于获取大量的基元集合,add方法用于加载数据
new Cesium.Cesium3DTileset({//这里使用的CesiumBDTileset方法,是Cesium用于传输海量异构3D地理空间数据集
url:Cesium.IonResource.fromAssetId(96188)//添加建筑物
})
)
viewer.camera.setView({//添加相机信息
destination:Cesium.Cartesian3.fromDegrees(121.49,31.23,3000),
orientation:{
heading:0,
pitch:-90,
roll:0
}
})
//模型加样式,这里先添加一个单一样式
tileset.style= new Cesium.Cesium3DTileStyle({//需要使用Cesium的Cesium3DTileStyle方法
color:"color('pink',0.5)",//color属性用于设定模型的颜色和透明度,可以设置颜色根据楼层高度进行变化
show:true
})//因为3d模型的样式过于单调,这里我们对一个模型数据样式进行修改,就是修改它的style
// //模型加样式,根据高度添加不同样式
// tileset.style = new Cesium.Cesium3DTileStyle({//需要使用Cesium的Cesium3DTileStyle方法
// color: {//给不同的高度的建筑物体设置不同的颜色
// conditions:[
// ["${Height} >= 300", "rgba(45,0,75,0.5)"],
// ["${Height} >= 200", "rgb(102,0,75)"],
// ["${Height} >= 100", "rgb(170,0,75)"],
// ["${Height} >= 50", "rgb(224,0,75)"],
// ["${Height} >= 20", "rgb(1,0,75)"],
// ["${Height} >= 10", "rgb(100,0,75)"],
// ["${Height} >= 5", "rgb(200,0,75)"],
// ["true", "rgb(127,59,8)"]
// ]
// },//color属性用于设定模型的颜色和透明度,可以设置颜色根据楼层高度进行变化
// show: '${Height} >= 0'//show属性设置的是高度大于等于0的建筑物才可以显示出来
// })//因为3d模型的样式过于单调,这里我们对一个模型数据样式进行修改,就是修改它的style
//----------------------- 建筑物的添加使用结束--------------------------
</script>
</body>
</html>
执行效果如下:
八、空间数据加载
1、加载数据
在cesium中一般使用到的空间数据分为矢量数据和栅格数据,前几课我们学习的地形和地图数据的加载,就属于栅格数据。矢量数据则包括几何体的加载,模型、标签等
(1)、加载点线面示例代码
//地球加载一个圆点
const entity_point = viewer.entities.add({//创建一个Entity点对象
position:new Cesium.Cartesian3.fromDegrees(113.37377, 31.717497, 1000),//设置经纬度和高度
point: {
pixelSize: 50,//设置点大小
color: new Cesium.Color(0, 1, 0, 1)//设定点颜色
}
})
//地球加载一条线
const entity_line = viewer.entities.add({//创建一个Entity点对象
polyline: {
show:true,
positions:new Cesium.Cartesian3.fromDegreesArray([113.37377, 31.717497, 113.37577, 31.717597]),//线经纬度
width:5,//线宽
material:new Cesium.Color(0,0,1,1),//设置颜色
}
})
//地球加载一个面
const entity_plane = viewer.entities.add({//创建一个Entity点对象
position: Cesium.Cartesian3.fromDegrees(113.37377, 31.717497, 1000),//设置经纬度和高度
plane: {//用于绘制一个面
plane:new Cesium.Plane(Cesium.Cartesian3.UNIT_Z,0),//确认面的朝向,这里我们设置它朝Z轴平铺
dimensions:new Cesium.Cartesian2(400,300),//设置面的长度和宽度
color: new Cesium.Color(0, 1, 0, 1),//设定点颜色
material: Cesium.Color.RED.withAlpha(0.5),//颜色为红色,透明度0.5
outline:true,//是否显示边框
outlineColor:Cesium.Color.BLACK//边框线为黑色
}
})
效果展示:
(2)、加载模型,代码如下:
const position = Cesium.Cartesian3.fromDegrees(113.37377, 31.717497, 10000) //定义常量,用于存储飞行目的地的坐标
const orientation= Cesium.Transforms.headingPitchRollQuaternion(position,new Cesium.HeadingPitchRoll(-90,0,0))//定义模型朝向变量:参数一:位置信息,参数二:旋转角度
const entity=viewer.entities.add({//使用Entities加载一个glb模型用于观察
position:position,//模型位置
orientation:orientation,//模型朝向
model:{//模型信息
uri:"./data/car.glb",//模型路径
minimumPixelSize:100,//模型最小的大小
maxmumScale:10000,//模型缩放最大比例
show:true,//模型的显示
}
})
执行效果:
(3)、加载文字说明(标签的加载),代码如下:
//地球加载一个文本标签
const entity_txt = viewer.entities.add({//使用Entities加载一个glb模型用于观察
position: position,//文字位置
label:{
text:"我是一段文字",//设置文字内容
font:"50px Helvetica",//字体
fillColor:Cesium.Color.YELLOW//字体颜色
}
})
效果如下:
(4)、总结:要建立起一个概念,在Cesium中无论载入几何体还是文字都是基于空间位置的。
2、对加载的空间数据进行管理
空间数据管理是三维场景开发的主要内容,其包含对数据的创建、增加、修改、删除等。这里主要学习cesium api的Entity方法,它让开发者专注于数据的呈现,而不必担心底层的可视化机制。
(1)、用Entity方法创建一个多边形,代码如下:
//地球加载一个多边形
const entity_polygon = viewer.entities.add({//创建一个Entity对象
polygon: {//用于绘制一个多边形,一个多边形由多个点连接组成的
hierarchy: Cesium.Cartesian3.fromDegreesArray([113.3777, 31.717497, 113.9007, 31.717797, 113.3007, 31.617797]),//fromDegreesArray方法就是让我们录入多个点的位置信息,Cesium则在底层将各个点连接起来,组成一个多边形,这里通过录入三个经纬度坐标位置,绘制一个三角形
material:Cesium.Color.PINK,//设置颜色
}
})
效果如下:
(2)、加载一个图片,这里把图片的朝向指向x轴,可以立起来,代码如下:
//地球加载一个图片
const entity_image = viewer.entities.add({//创建一个Entity点对象
position: Cesium.Cartesian3.fromDegrees(113.37377, 31.717497, 100),//设置经纬度和高度
plane: {//用于绘制一个面
plane: new Cesium.Plane(Cesium.Cartesian3.UNIT_X, 0),//确认面的朝向,这里我们设置它朝X轴平铺
dimensions: new Cesium.Cartesian2(200, 150),//设置面的长度和宽度
material: "./data/a.png",//引入图片
outline: true,//是否显示边框
outlineColor: Cesium.Color.GREEN//边框线为黑色
}
})
效果如下:
(3)、将绘制好的多边形在垂直方向拉伸,代码如下:
//地球加载一个多边形并拉伸
const entity_polygon_stretch = viewer.entities.add({//创建一个Entity对象
polygon: {//用于绘制一个多边形,一个多边形由多个点连接组成的
hierarchy: Cesium.Cartesian3.fromDegreesArray([113.3777, 31.7174, 113.9007, 31.7177, 113.3007, 31.6177]),//fromDegreesArray方法就是让我们录入多个点的位置信息,Cesium则在底层将各个点连接起来,组成一个多边形,这里通过录入三个经纬度坐标位置,绘制一个三角形
material: Cesium.Color.YELLOW,//设置颜色
extrudedHeight: 200,//将绘制好的多边形在垂直方向进行拉升,此属性在绘制多边形的时候可以使用,如果绘制的本身是平面则不可以使用
}
})
效果如下:
(4)、除了修改样式以外,还常需对它们进行增、删、改 ,比如 :五秒后将上面的多面体颜色设置为白色,十秒后删除拉伸模型,代码如下:
/** 除了修改样式以外,还常需对它们进行增、删、改 **/
//五秒后颜色设置为白色
setTimeout(() => {
viewer.entities.getById("polygon_stretch_id").polygon.material = Cesium.Color.WHITE
}, 5000);
setTimeout(() => {//十秒后删除拉伸模型
viewer.entities.remove(entity_polygon_stretch)
}, 10000);
效果如下:
移除场景内的所有实体,使用removeAll()方法,代码如下:viewer.entities.removeAll()
,效果如下:
3、空间数据加载的整体代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>cesium第三课,空间实体</title>
<!-- cesium.js引入 -->
<script src="../libs/Cesium/Cesium.js"></script>
<!-- cesium样式引入 -->
<link href="../libs/Cesium/Widgets/widgets.css" rel="stylesheet">
<!-- 导入cesium的类型声明,有这个才会有快捷智能提示(已屏蔽,无效) -->
<!-- <script src="../libs/Cesium/Cesium.d.ts"></script> -->
<!-- <reference path="../libs/Cesium/Cesium.d.ts" /> -->
<style>
html,
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="puiedu-cesiumContainer"></div>
<script>
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5MWVkMjllNy03ZjY4LTQ3YmQtOTgxOC05NGQ5YTU0ZjM5ZGEiLCJpZCI6MzU5Nywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTUzODE5MTUyM30.dtS2F3-q2fGoA93N7cFl-LCikK-Rjk7v01WWA-RqCxg';
const viewer = new Cesium.Viewer('puiedu-cesiumContainer', {
animation: false,//动画小组件
timeline: false,//左下角仪表
});
//----------------------------空间数据加载,---------------------------
const position=Cesium.Cartesian3.fromDegrees(113.37377, 31.717497, 1000) //定义常量,用于存储飞行目的地的坐标
//setView 直接跳转,没有过程
viewer.camera.setView({//通过相机系统设置视角
destination:position,//设置相机目的地
orientation:{//设置相机视口的方向
heading:Cesium.Math.toRadians(0),//控制视口的水平旋转,也就是沿着y轴旋转,当数值为0时,代表正北方向
pitch:Cesium.Math.toRadians(-90),//控制视口的上下旋转,即沿x轴进行旋转,当数值为-90,代表俯视地面
roll:0,//控制视口的反转角度,即沿着z轴进行旋转,数值为0表示不翻转
},
})
//地球加载一个圆点
const entity_point = viewer.entities.add({//创建一个Entity点对象
position:new Cesium.Cartesian3.fromDegrees(113.37377, 31.717497, 1000),//设置经纬度和高度
point: {
pixelSize: 50,//设置点大小
color: new Cesium.Color(0, 1, 0, 1)//设定点颜色
}
})
//地球加载一条线
const entity_line = viewer.entities.add({//创建一个Entity点对象
polyline: {
show:true,
positions:new Cesium.Cartesian3.fromDegreesArray([113.37377, 31.717497, 113.37577, 31.717597]),//线经纬度
width:5,//线宽
material:new Cesium.Color(0,0,1,1),//设置颜色
}
})
//地球加载一个面
const entity_plane = viewer.entities.add({//创建一个Entity点对象
position: Cesium.Cartesian3.fromDegrees(113.37377, 31.717497, 1000),//设置经纬度和高度
plane: {//用于绘制一个面
plane:new Cesium.Plane(Cesium.Cartesian3.UNIT_Z,0),//确认面的朝向,这里我们设置它朝Z轴平铺
dimensions:new Cesium.Cartesian2(400,300),//设置面的长度和宽度
color: new Cesium.Color(0, 1, 0, 1),//设定点颜色
material: Cesium.Color.RED.withAlpha(0.5),//颜色为红色,透明度0.5
outline:true,//是否显示边框
outlineColor:Cesium.Color.BLACK//边框线为黑色
}
})
//地球加载一个多边形
const entity_polygon = viewer.entities.add({//创建一个Entity对象
polygon: {//用于绘制一个多边形,一个多边形由多个点连接组成的
hierarchy: Cesium.Cartesian3.fromDegreesArray([113.3777, 31.717497, 113.9007, 31.717797, 113.3007, 31.617797]),//fromDegreesArray方法就是让我们录入多个点的位置信息,Cesium则在底层将各个点连接起来,组成一个多边形,这里通过录入三个经纬度坐标位置,绘制一个三角形
material:Cesium.Color.PINK,//设置颜色
//通常除了简单的图形、颜色加载以外,更多时候需要定制化的样式,通过代码看下他的可选配置项
}
})
/** 通常除了简单的图形、颜色加载以外,更多时候需要定制化的样式,通过代码看下他的可选配置项 **/
//地球加载一个图片
const entity_image = viewer.entities.add({//创建一个Entity点对象
position: Cesium.Cartesian3.fromDegrees(113.37377, 31.717497, 100),//设置经纬度和高度
plane: {//用于绘制一个面
plane: new Cesium.Plane(Cesium.Cartesian3.UNIT_X, 0),//确认面的朝向,这里我们设置它朝X轴平铺
dimensions: new Cesium.Cartesian2(200, 150),//设置面的长度和宽度
material: "./data/a.png",//引入图片
outline: true,//是否显示边框
outlineColor: Cesium.Color.GREEN//边框线为黑色
}
})
//地球加载一个多边形并拉伸
const entity_polygon_stretch = viewer.entities.add({//创建一个Entity对象
id:"polygon_stretch_id",//给几何体加一个id号
polygon: {//用于绘制一个多边形,一个多边形由多个点连接组成的
hierarchy: Cesium.Cartesian3.fromDegreesArray([113.3777, 31.7174, 113.9007, 31.7177, 113.3007, 31.6177]),//fromDegreesArray方法就是让我们录入多个点的位置信息,Cesium则在底层将各个点连接起来,组成一个多边形,这里通过录入三个经纬度坐标位置,绘制一个三角形
material: Cesium.Color.YELLOW,//设置颜色
extrudedHeight: 200,//将绘制好的多边形在垂直方向进行拉升,此属性在绘制多边形的时候可以使用,如果绘制的本身是平面则不可以使用
}
})
/** 除了修改样式以外,还常需对它们进行增、删、改 **/
//五秒后颜色设置为白色
// setTimeout(() => {
// viewer.entities.getById("polygon_stretch_id").polygon.material = Cesium.Color.WHITE
// }, 5000);
// setTimeout(() => {//十秒后删除拉伸模型
// viewer.entities.remove(entity_polygon_stretch)
// }, 10000);
//移除场景内的所有实体,使用removeAll()方法
setTimeout(() => {//五秒后清除所有实体
viewer.entities.removeAll()
}, 5000);
//地球加载一个glb模型
const orientation = Cesium.Transforms.headingPitchRollQuaternion(position, new Cesium.HeadingPitchRoll(-90, 0, 0))//定义模型朝向变量:参数一:位置信
const entity_glb = viewer.entities.add({//使用Entities加载一个glb模型用于观察
position: position,//模型位置
orientation: orientation,//模型朝向
model: {//模型信息
uri: "./data/car.glb",//模型路径
minimumPixelSize: 100,//模型最小的大小
maxmumScale: 10000,//模型缩放最大比例
show: true,//模型的显示
}
})
//地球加载一个文本标签
const entity_txt = viewer.entities.add({//使用Entities加载一个glb模型用于观察
position: position,//文字位置
label:{
text:"我是一段文字",//设置文字大小和样式
font:"50px Helvetica",//字体
fillColor:Cesium.Color.YELLOW//字体颜色
}
})
// viewer.trackedEntity = entity;//将摄像头设置在圆点处(track跟踪)
//------------------------------空间数据加载演示结束------------------------------
</script>
</body>
</html>
九、鼠标交互,数据查询
1、鼠标左键点击图片后提示弹框
代码如下:
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)//使用Cesium的ScreenSpaceEventHandler方法,创建了一个屏幕控制实例,其中viewer.scene.canvas获取scene下的所有canvas创建的元素
handler.setInputAction(function (movement){//再使用setInputAction方法进行监听,可以监听鼠标相关事件,第一个参数放入回调函数,第二个参数是监听的具体是鼠标的哪个事件
var pick = viewer.scene.pick(movement.position);//创建一个变量,通过viewer.scene.pick可以获取到点击的对象的位置信息
if(Cesium.defined(pick) && pick.id.id==="image_id"){
alert("点击了图片!")
} //并对其判断,并要同时满足,当前获取对象的id号是否和之前绑定的image_id一致
},Cesium.ScreenSpaceEventType.LEFT_CLICK)
/**
补充说明:Cesium给我们提供了好几种获取不同对象的方法
//scene.pick返回的是包含给定窗口位置基元的对象,
//scene.drillpick返回的是给定窗口位置所有对象的列表,
//Globe.pick返回的是给定光线和地形的交点,
//际此以外 Cesium还提供了多种鼠标监听可供我们选择:
//鼠标中键点击事件: Cesium.ScreenSpaceEventType.MIDDLE_CLICK
//鼠标移入事件: Cesium.ScreenSpaceEventType.MOUSE_MOVE
//鼠标右击事件: Cesium.ScreenSpaceEventType.RIGHT_CLICK
**/
效果如下:
2、自定义弹框
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>cesium第四课,鼠标交互,数据查询</title>
<!-- cesium.js引入 -->
<script src="../libs/Cesium/Cesium.js"></script>
<!-- cesium样式引入 -->
<link href="../libs/Cesium/Widgets/widgets.css" rel="stylesheet">
<!-- 导入cesium的类型声明,有这个才会有快捷智能提示(已屏蔽,无效) -->
<!-- <script src="../libs/Cesium/Cesium.d.ts"></script> -->
<!-- <reference path="../libs/Cesium/Cesium.d.ts" /> -->
<style>
html,
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="puiedu-cesiumContainer"></div>
<script>
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5MWVkMjllNy03ZjY4LTQ3YmQtOTgxOC05NGQ5YTU0ZjM5ZGEiLCJpZCI6MzU5Nywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTUzODE5MTUyM30.dtS2F3-q2fGoA93N7cFl-LCikK-Rjk7v01WWA-RqCxg';
const viewer = new Cesium.Viewer('puiedu-cesiumContainer', {
animation: false,//动画小组件
timeline: false,//左下角仪表
});
//----------------------------空间数据加载,---------------------------
const position=Cesium.Cartesian3.fromDegrees(113.37377, 31.717497, 1000) //定义常量,用于存储飞行目的地的坐标
//setView 直接跳转,没有过程
viewer.camera.setView({//通过相机系统设置视角
destination:position,//设置相机目的地
orientation:{//设置相机视口的方向
heading:Cesium.Math.toRadians(0),//控制视口的水平旋转,也就是沿着y轴旋转,当数值为0时,代表正北方向
pitch:Cesium.Math.toRadians(-90),//控制视口的上下旋转,即沿x轴进行旋转,当数值为-90,代表俯视地面
roll:0,//控制视口的反转角度,即沿着z轴进行旋转,数值为0表示不翻转
},
})
/** 通常除了简单的图形、颜色加载以外,更多时候需要定制化的样式,通过代码看下他的可选配置项 **/
//地球加载一个图片
const entity_image = viewer.entities.add({//创建一个Entity点对象
id:"image_id",//id标识
position: Cesium.Cartesian3.fromDegrees(113.37377, 31.717497, 100),//设置经纬度和高度
plane: {//用于绘制一个面
plane: new Cesium.Plane(Cesium.Cartesian3.UNIT_X, 0),//确认面的朝向,这里我们设置它朝X轴平铺
dimensions: new Cesium.Cartesian2(200, 150),//设置面的长度和宽度
material: "./data/a.png",//引入图片
outline: true,//是否显示边框
outlineColor: Cesium.Color.GREEN//边框线为黑色
},
description:`<div>
<img width="100%" height:"300px" src="./data/a.png" />
<h3>自定义点击弹框</h3>
</div>`,//description属性用于设置选定对象的显示信息,在其中我们可以直接用HTML标签,将其包裹后,可以直接传到页面中,不需要额外设定样式,封装事件
})
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)//使用Cesium的ScreenSpaceEventHandler方法,创建了一个屏幕控制实例,其中viewer.scene.canvas获取scene下的所有canvas创建的元素
handler.setInputAction(function (movement){//再使用setInputAction方法进行监听,可以监听鼠标相关事件,第一个参数放入回调函数,第二个参数是监听的具体是鼠标的哪个事件
var pick = viewer.scene.pick(movement.position);//创建一个变量,通过viewer.scene.pick可以获取到点击的对象的位置信息
if(Cesium.defined(pick) && pick.id.id==="image_id"){
alert("点击了图片!")
} //并对其判断,并要同时满足,当前获取对象的id号是否和之前绑定的image_id一致
},Cesium.ScreenSpaceEventType.LEFT_CLICK)
/**
补充说明:Cesium给我们提供了好几种获取不同对象的方法
//scene.pick返回的是包含给定窗口位置基元的对象,
//scene.drillpick返回的是给定窗口位置所有对象的列表,
//Globe.pick返回的是给定光线和地形的交点,
//际此以外 Cesium还提供了多种鼠标监听可供我们选择:
//鼠标中键点击事件: Cesium.ScreenSpaceEventType.MIDDLE_CLICK
//鼠标移入事件: Cesium.ScreenSpaceEventType.MOUSE_MOVE
//鼠标右击事件: Cesium.ScreenSpaceEventType.RIGHT_CLICK
**/
//------------------------------空间数据加载演示结束------------------------------
</script>
</body>
</html>
效果如下:
总结:其实弹窗显示数据,本质上就是一种空间信息数据的查询,是用户与客户端信息交互的最典型功能
十、三维数据3dtiles
(1)、它是Cesium于2016年3月定义的一种三维模型瓦片数据结构。它将海量的三维数据用分块、分层的形式组织起来,这样就很大程度上减轻了浏览器的负担,除此以外还提供了细节层次的LOD功能。在远观时,降低模型的面数和精度,拉近后再将细节加载出来,大大增强了页面的加载速度,更可以用于跨桌面使用,使得Web端和移动应用程序共享。
(2)、那么3D Tiles与其他数据对比叉有什么特点呢?
其一,它是一个开放式的数据规范,我们可以根据实际需求设定三维模型的大小和范围,此外还能适配多种空间分区方案,如普通网格、四叉树、八叉树等;
这里简单了解一下四叉树和八又树的数据结构:
四叉树是一种树形数据结构,它的每个节点可以有四个子节点,通常把二维空间细分为四个区域,并把该区域里的相关信息存入到四叉树节点中,四叉树的每一个节点代表一个矩形区域,每一个矩形区域叉可划分为四个小矩形区域
较之四叉树,八又树将场景从二维空间延伸到了三维空间
树中的子节点只会有八个或者零个,每一个节点同样用于存储数据。
其二,它的异质性支持,可以将不同类型的号维模型数据,如普通模型数据加倾斜摄影数据加自绘几何数据放在一起,转化为同一标准的数据集,让它们可以在同一场景下显示出来。
其三,它是专门为三维可视化设计的,并在其中引入了图形领域的技术,在不满足特定条件的情况下,并不会对场景内的模型做整个渲染,而是只会渲染个轮廓,大大降低了计算量,使得浏览器请求到数据以后,渲染的流程也更加的简单。同时。因为三维模型预先处理成了分块的三维瓦片格式,所以也减少了WebGL绘制请求的数量。
其四,它的可交互性,其支持对加载模型的拾取,和样式的修改,大量加载以后,可以对其中的单独模型进行交互。如高亮显示鼠标悬停处的模型、或进行删除等;也可根据建筑模型的高度和年代,设置不同的显示效果而不需要重新更新代码。
(3)、接下来我们来了解一下,3DTiles的代码究竟是如何构成的
一个简单的3dtiles文件夹结构如下:
可以看到除了json文件以外,还有三个b3dm格式的文件,它就是我们用于渲染数据的文件。
如上图:3DTiles的格式是由两个部分组成的,其一就是现在看到的tileset.json格式的数据,我们先来了解一下它的格式。
这里的asset是一个包含整体tileset元素属性的对象,其中的version属性是定义3DTiles版本的字符串,此外这里还可以选填一个
tilesetVersion属性,它可以用于定义特定应用中的版本号。
geometricError:其定义了一个非误差单位,低于这个误差值,瓦片集不会被渲染,这里设定的500,它的单位是米。
root属性用于定义根瓦片,它的子项transform也是一个可选项,它的作用是在加载大量模型或者建筑物的情况下,单个模型的点云瓦片集能在它自己的坐标系中定义,其内的数据是一个4X4的仿射变换矩阵,以列主序存储,用来实现从瓦片局部坐标系到父瓦片或根瓦片坐标系的变换。
root内部也有一个同样的属性,前者是整个瓦片集不被渲染的误差,后者只是当前瓦片集被渲染的误差。content属性通过ur引入文件,这里引入的文件就是瓦片的内容,它的数据是二进制的,其支持的二进制文件格式有:.b3dm、.i3dm、.pnts等。甚至可以在其中再放入一个3DTiles文件,前提是不可以自己引用给自己,content上方的refine属性定义的是LOD细化的方法,简单来说就是瓦片是如何切换的。
下方的children属性比较好理解,因为3DTiles是分级别的,所以每个Tile还会有子Tile、子子Tile。构成3D Tiles的第二个部分就是其引用的瓦片数据文件了。
(4)、来通过代码看一下3dtiles是如何引用的:此模型使用的是b3dm格式的瓦片集,主要用于加载批量的模型,除此以外还有pnts格式瓦片集,用于加载点云数据模型;cmpt格式瓦片集,允许一个cmpt文件内嵌多个其他类型的瓦片
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>cesium第五课,加载3dtiles</title>
<!-- cesium.js引入 -->
<script src="../libs/Cesium/Cesium.js"></script>
<!-- cesium样式引入 -->
<link href="../libs/Cesium/Widgets/widgets.css" rel="stylesheet">
<!-- 导入cesium的类型声明,有这个才会有快捷智能提示(已屏蔽,无效) -->
<!-- <script src="../libs/Cesium/Cesium.d.ts"></script> -->
<!-- <reference path="../libs/Cesium/Cesium.d.ts" /> -->
<style>
html,
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="puiedu-cesiumContainer"></div>
<script>
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5MWVkMjllNy03ZjY4LTQ3YmQtOTgxOC05NGQ5YTU0ZjM5ZGEiLCJpZCI6MzU5Nywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTUzODE5MTUyM30.dtS2F3-q2fGoA93N7cFl-LCikK-Rjk7v01WWA-RqCxg';
const viewer = new Cesium.Viewer('puiedu-cesiumContainer', {
animation: false,//动画小组件
timeline: false,//左下角仪表
});
//----------------------------加载3dtiles,---------------------------
var tileset=viewer.scene.primitives.add(//发现这里的加载方法并不是之前常用的entities,这是因为3DTiles并不是Entity的一部分,而是属于更加底层的primitives
new Cesium.Cesium3DTileset({
url:"./data/dtiles/tileset.json",//模型地址
maximumScreenSpaceError:2,//最大的屏幕空间误差,数字越低,视觉效果越好
maximumNumberOfLoadedTiles:1000,//最大加载瓦片个数,用于给定一定的限制,防止数据量过大,占用内存过高
})
)
tileset.readyPromise.then((tileset) => {//模型加载完毕后的回调
viewer.zoomTo(tileset);
});
//------------------------------加载3dtiles------------------------------
</script>
</body>
</html>
十一、时间系统、粒子系统
1、时间系统
其在动态数据可视化中发挥了重要的作用,在三维场景的基础上增加了时间维度信息,Cesium初始化是自带时间控件的,默认是会显示当前的时间;Cesium的时间控件Clock由两部分构成,第一部分是Animation控件,控制时间的启动和暂停,第二部分是Timeline控件,控制时间线,如果我们不想显示两个控件,可以在Viewer初始化中将其都设置成false{animation: false,//动画小组件timeline: false,//左下角仪表}
;我们知道操控时间的Animation控件默认是暂停状态;下面来看一下,如何使用代码修改它们的状态:
viewer.clock.shouldAnimate=true;//设置其clock属性下的shouldAnimate为true,实现初始化页面自动循环播放的效果
viewer.clock.multiplier=1000;//使用它的multiplier属性,设定时间速率为1000,默认时间线是当前时间的24小时
let start=Cesium.JulianDate.fromIso8601('2022-01-05')//给他们设置一个新的时间线,用一个变量存储起始时间,使用JulianDate计算时间差,再通过fromIso8601转换成对应的格式
let end = Cesium.JulianDate.fromIso8601('2022-01-20')//同样的方法设置结束时间
viewer.timeline.zoomTo(start,end)//最后使用timeline的zoomTo方法将时间设置上去
效果如下:时间在自动播放
2、粒子系统
除了动效以外,Cesium为了实现更加逼真的学维仿真模拟,还加入了粒子系统,用于实现各种特效,如烟花燃放特效、天气效果车辆尾气的特效。Cesium的粒子系统是一种模拟复杂物理效应的图形技术,是由很多的小图像组成的集合,形成一个模糊对象,从而产生特效。
如果我们加载的是粒子类的数据,就需要使用primitives用于加载数据,因为其更接近底层的图形开发,Cesium为我们提供了这个对象用于创建粒子系统,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>cesium第六课,粒子系统的演示</title>
<!-- cesium.js引入 -->
<script src="../libs/Cesium/Cesium.js"></script>
<!-- cesium样式引入 -->
<link href="../libs/Cesium/Widgets/widgets.css" rel="stylesheet">
<!-- 导入cesium的类型声明,有这个才会有快捷智能提示(已屏蔽,无效) -->
<!-- <script src="../libs/Cesium/Cesium.d.ts"></script> -->
<!-- <reference path="../libs/Cesium/Cesium.d.ts" /> -->
<style>
html,
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="puiedu-cesiumContainer"></div>
<script>
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5MWVkMjllNy03ZjY4LTQ3YmQtOTgxOC05NGQ5YTU0ZjM5ZGEiLCJpZCI6MzU5Nywic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTUzODE5MTUyM30.dtS2F3-q2fGoA93N7cFl-LCikK-Rjk7v01WWA-RqCxg';
let esri = new Cesium.ArcGisMapServerImageryProvider({
url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"
})//用一个变量存储新地图的信息,这里我们使用的是arcgis地图服务
const viewer = new Cesium.Viewer('puiedu-cesiumContainer', {
animation: true,//动画小组件
timeline: true,//左下角仪表,
baseLayerPicker: false,//默认的地图按钮设置为隐藏
imageryProvider: esri,//viewer内的imageryProvider属性用于设置地图
terrainProvider: new Cesium.CesiumTerrainProvider({//此时地球表面是没有比如山脉3d地形的,所以下面加载地形数据放入引入的地形;CesiumTerrainProvider方法是将地形数据,转换为Cesium可以访问的格式
url: Cesium.IonResource.fromAssetId(1),//url 属性用于放入地形服务器的地址
requestVertexNormals: true,//requestVertexNormals属性设置为true,可以增加法线,用于提高光照效果
requestWaterMask: true,//可以增加水面特效
}),
});
//注意:粒子系统是依赖于时间系统的,是根据时间来变换的,所以这里设置下自动播放时间
viewer.clock.shouldAnimate = true;//设置其clock属性下的shouldAnimate为true,实现初始化页面自动循环播放的效果
viewer.clock.multiplier = 1000;//使用它的multiplier属性,设定时间速率为1000,默认时间线是当前时间的24小时
let start = Cesium.JulianDate.fromIso8601('2022-01-05')//给他们设置一个新的时间线,用一个变量存储起始时间,使用JulianDate计算时间差,再通过fromIso8601转换成对应的格式
let end = Cesium.JulianDate.fromIso8601('2022-01-20')//同样的方法设置结束时间
viewer.timeline.zoomTo(start, end)//最后使用timeline的zoomTo方法将时间设置上去
//----------------------------粒子特效,---------------------------
//地球加载一个glb模型
const position = Cesium.Cartesian3.fromDegrees(113.37377, 31.717497, 100) //定义常量,用于存储飞行目的地的坐标
const orientation = Cesium.Transforms.headingPitchRollQuaternion(position, new Cesium.HeadingPitchRoll(-90, 0, 0))//定义模型朝向变量:参数一:位置信
const entity_glb = viewer.entities.add({//使用Entities加载一个glb模型用于观察
position: position,//模型位置
orientation: orientation,//模型朝向
model: {//模型信息
uri: "./data/car.glb",//模型路径
minimumPixelSize: 100,//模型最小的大小
maxmumScale: 10000,//模型缩放最大比例
show: true,//模型的显示
}
})
viewer.camera.viewBoundingSphere(new Cesium.BoundingSphere(position, 20), new Cesium.HeadingPitchRange(0, 0, 0)) //视角绑定实体,参数一:设置视点位置BoundingSphere,参数二,相机的朝向HeadingPitchRange。其中new Cesium.BoundingSphere参数一:位置,参数二,和物体的距离
viewer.scene.primitives.add(
new Cesium.ParticleSystem({
image: "./data/fire.png", //这里的image中放置的就是粒子的样式,通常使用路径的方式引用
imageSize: new Cesium.Cartesian2(20,20),//imageSize用于设置粒子图片的大小
startScale: 1.0,//startScale设置的是初始大小的倍数,它是与endScale相关联的
endScale: 4.0,//这两个属性控制的是,粒子从生成到消亡整个周期,从初始大小,逐渐变化到原来尺寸的四倍,也可以根据需求设置初始很大,然后逐渐缩小
particleLife: 1.0,//这里设置的是每一个粒子存在的时间,使得粒子随机生成生命周期
speed:3.0,//粒子速度
emitter: new Cesium.CircleEmitter(1),//粒子系统发射器,这里设置的是圆形发射器,0.5设置的是圆的半径,粒子将会在圆的范围内随机向上发射粒子,在半径以内随机生成
// emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(10,10,10)),//粒子系统发射器,这里设置的是盒体发射器,并在其中设置了盒子的大小,粒子在盒子范围内随机生成
emissionRate: 5.0,//每秒钟发射粒子的数量,数值越大,性能消耗越大
lifetime: 16.0,//使用lifetime指定持续时间,这里设置为16秒
modelMatrix: entity_glb.computeModelMatrix(viewer.clock.startTime, new Cesium.Matrix4()),//设置粒子系统的位置,它将粒子系统从模型转换为世界坐标的 4x4 转换矩阵,这里需要绑定到glb模型上,并用它的这个方法,在指定时间计算实体变换的模型矩阵,其中clock.startTime获取的就是时间控件中的起始时间
})
);
//------------------------------粒子特效结束------------------------------
</script>
</body>
</html>
效果如下:
十二、动态数据格式CZML
未完待续…