cesium学习笔记

news2024/12/23 23:24:12

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>

代码执行效果:
3d地形

水纹波动

七、建筑体添加和使用

代码如下,都有详细注释:

<!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

未完待续…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/644883.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python中变量与字符串详解!!

❄️作者介绍&#xff1a;奇妙的大歪❄️ &#x1f380;个人名言&#xff1a;但行前路&#xff0c;不负韶华&#xff01;&#x1f380; &#x1f43d;个人简介&#xff1a;云计算网络运维专业人员&#x1f43d; 前言 初学者经常会遇到的困惑是&#xff0c;看书上或者是听课都懂…

数据库:mysqldump用法详解

目录 一、命令格式详解 1.1 语法格式 1.2 常用参数 1.3 完整参数 二、mysqldump常见的几个错误 2.1、提示命令未找到 -bash: mysqldump: 未找到命令 2.2、 the command line interface can be insecure 2.3、Gotpacket bigger than ‘max_allowed_packet‘ bytes 一、命令格式详…

GPT-4官方使用经验都在里面;Stability AI联合Clipdrop推出一键改变图像比例

&#x1f989; AI新闻 &#x1f680; Stability AI联合Clipdrop推出扩图工具Uncrop&#xff0c;一键改变图像比例 摘要&#xff1a;Stability AI联合Clipdrop推出的Uncrop Clipdrop是一个终极图像比例编辑器。它可以补充任何现有照片或图像&#xff0c;来更改任何图像的比例。…

apple pencil二代平替笔哪个好用?ipad平替笔合集

现在很多人都在用IPAD记录&#xff0c;或者用IPAD画图。还有就是&#xff0c;大部分的IPAD用户&#xff0c;都是以实用为主&#xff0c;他们觉得&#xff0c;要想让IPAD更加实用&#xff0c;就一定要有一款好用的电容笔。其实&#xff0c;如果只是用来做笔记&#xff0c;或者只…

43从零开始学Java之一文详解初学者难以理解的多态

作者&#xff1a;孙玉昌&#xff0c;昵称【一一哥】&#xff0c;另外【壹壹哥】也是我哦 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 我们知道&#xff0c;面向对象有三大特征&#xff1a;封装、继承和多态。现在我们已经了解了封装和继…

IBM Spectrum LSF 针对要求苛刻、任务关键型计算环境的全面工作负载管理

IBM Spectrum LSF 针对要求苛刻、任务关键型计算环境的全面工作负载管理 亮点 通过卓越的可重复性能加快求解时间; 使用可靠且可扩展的架构管理大量作业; 面向管理员和用户的直观界面提高工作效率; IBM Spectrum LSF 系列是一套完整的工作负载管理解决方案组合 &#xff0…

由于找不到msvcr120.dll,无法继续执行代码,多种解决方法修复这个故障

在使用电脑时&#xff0c;我们常常会遇到各种各样的问题。其中一个比较常见的问题是“由于找不到msvcr120.dll,无法继续执行代码”。这个问题可能会让一些用户感到困惑和无助。那么&#xff0c;究竟什么是msvcr120.dll&#xff1f;它缺失了会有什么后果&#xff1f;如何修复这个…

“拓界·创变”——2023K+全球软件研发行业创新峰会上海站圆满收官

众望所归&#xff01;6月9-10日&#xff0c;为期两天的K全球软件研发行业创新峰会&#xff0c;于上海明捷万丽大酒店成功举办。本届峰会吸引了来自金融、通信、互联网、消费电子、企服等各行业逾千位技术从业者的参与&#xff0c;活动现场大咖云集、座无虚席&#xff0c;同时也…

10. WebGPU 旋转变换

单位圆是半径为 1.0 的圆。 下图是一个单位圆。 [注释1] 在上图中&#xff0c;当围绕圆拖动蓝色手柄时&#xff0c;X 和 Y 位置会发生变化&#xff0c;代表该点在圆上的位置。且在顶部&#xff0c;Y 为 1&#xff0c;X 为 0。在右侧&#xff0c;X 为 1&#xff0c;Y 为 0。 …

互联网JAVA工程师必背面试题和项目面试通关要点(带答案)

前言 大家好&#xff0c;前几天我将各个大厂的高频考点以及 Java 岗需掌握的核心知识整理出的 Java 核心知识大全分享给了大家&#xff0c;今天为了能让看过这份资料的小伙伴更加好地去理解和灵活运用。小编今天将把前段时间和那份资料一块儿收集的 1100 道 Java 岗大厂面试真…

你知道Unity IoC Container是如何创建对象的吗?

ty是微软P&P推出的一个开源的IoC框架&#xff0c;最新的官方版本是2.0。Unity之前的版本建立在一个称为ObjectBuild的组件上&#xff0c;熟悉EnterLib的读者&#xff0c;相信对ObjectBuild不会感到陌生。对于EnterLib 5.0之前的版本&#xff0c;ObjectBuild可以说是所有App…

Linux:初识

1 诞生 创始人&#xff1a;林纳斯 托瓦兹 时 间&#xff1a;1991年&#xff0c;上大学期间 2 Linux的组成 linux主要由内核、系统级应用程序组成 图2-1 Linux系统结构&#xff08;图自黑马程序员课程&#xff09; 内核&#xff1a;对硬件进行调度&#xff0c;比如调度CPU、内…

CSDN原力值解析:功能作用、获取方法、积分对应等级关系详解

开篇声明&#xff1a;本博主非官方人员&#xff0c;也是非所谓的 CSDN 内容合伙人&#xff0c;所以本文博主站在一个中立的角度、以博主自身的主观观点的角度来解答 CSDN 的一个叫做 “原力值” 东西&#xff0c;本文欢迎随时在留言区讨论&#xff0c;但是拒绝硬杠&#xff0c;…

推挽电路应用

1. 推挽电路&#xff0c;常用上N下P型 2. 输出与输入同相&#xff1a; 输入低电平&#xff0c;输出低电平&#xff0c;输出受输入限制&#xff0c;输入输出同相 输入高电平&#xff0c;输出低电平&#xff0c;输出受输入限制&#xff0c;输入输出同相 3. N管烧坏原因分析 当…

华为诺亚极简网络,靠13层就拿下83%精度(附源代码)

点击蓝字 关注我们 关注并星标 从此不迷路 计算机视觉研究院 公众号ID&#xff5c;计算机视觉研究院 学习群&#xff5c;扫码在主页获取加入方式 论文地址&#xff1a;https://arxiv.org/pdf/2305.12972.pdf 项目代码&#xff1a;https://github.com/huawei-noah/VanillaNet ht…

【裸机开发】系统时钟分路 PLL2_PFDx、PLL3_PFDx 配置实验(二)—— 寄存器分析篇

上一篇介绍了 系统时钟的来源、时钟树 以及 PLL1 分路的配置步骤。我们注意到&#xff0c;PLL2、PLL3是固定倍频&#xff0c;无法修改&#xff0c;但是他们下分的 PFDx 分路是可以修改的。只不过我们在初始化的时候&#xff0c;依然按照官方给定的频率进行初始化。 目录 一、了…

2023年,程序员如何构建持续增长的被动收入?

大家好&#xff0c;我是晓衡&#xff01; 我致力于帮助开发者通过技术&#xff0c;实现被动收入&#xff0c;并利用复利效应获得收益最大化。 经过 6 年的探索和实践&#xff0c;取得了一定的成效。 01 起点 我是从 2018 年 7 月份开始全职做这个 Cocos 内容公众号&#xff0c;…

room数据库升级

直接添加表字段&#xff0c;不升级会报异常如上图。 1.表字段或减少表字段 2.增加表 如上等情况需要升级数据库 方法如下&#xff08;以添加表字段为例&#xff09;&#xff1a; Database( entities [XXInfo::class], version 2 // 旧版本为1 ) init { …

Linux:grep、wc命令和管道符

1、grep命令&#xff1a;从文件中根据关键词过滤文件行&#xff0c;语法&#xff1a; grep [-n] 关键词 文件路径 选项-n是可选的&#xff0c;表示在结果中输出匹配到的行的行号关键词&#xff1a;必填&#xff0c;表示要过滤的关键词文件路径&#xff1a;必填&#xff0c;表示…

海思如何编译驱动

一、安装海思的SDK 这一步在海思的说明文档中有&#xff0c;运行sdk.unpack 二、配置内核 进入osdrv/opensource/kernel/ 根据里面的说明文档&#xff0c;没有内核就去下载内核&#xff0c;如果在www.kernel.org网站下载内核十分慢&#xff0c;推荐使用镜像列表下载&#xff0c…