bosombaby / cesium-tutorial

Cesium是一个用于显示三维地球的开源库,旨在释放3D数据的力量。Cesium基于WebGL技术,能够在Web平台搭建虚拟地球及场景展示应用。

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

一、前言

image.png Cesium是一个用于显示三维地球的开源库,旨在释放3D数据的力量。Cesium基于WebGL技术,能够在Web平台搭建虚拟地球及场景展示应用。

项目目录 11.png

  • libs存放一些依赖文件
  • stage_0阶段的html页面代码
  • stage_1阶段的html页面代码
  • token官网的token,记得替换成你的

开源地址:Cesium三维地图入门教程

二、环境搭建

初始化后的界面及各个控件的名称如图:image.png

// 引入token,装入容器
Cesium.Ion.defaultAccessToken='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0NmY4OGRkZS03ZTljLTQ5MDMtYmUwZC0wNmM2ZjdmM2M1MzMiLCJpZCI6MTI2MjUzLCJpYXQiOjE2NzczMTI2ODJ9.KO5KCez-xGcJBJfY8XYWAlUXHO4WWrZUm6tCZ1MfCWM'
const viewer=new Cesium.Viewer('cesium-container')

cesium主要分为下面四个核心类,后续详细介绍:

  • viewer:场景的总管理者
  • scene:加载场景的物体,所有3D图形对象的容器
  • entity:由Primitive封装而来,主要加载实体模型几何模型
  • dataSourceCollection:加载矢量数据

三、坐标系及转化

2.png

3.1 wgs84坐标系

1.png WGS-84坐标系 [1] 的几何意义是:坐标系的原点位于地球质心,z轴指向(国际时间局)BIH1984.0定义的协议地球极(CTP)方向,x轴指向BIH1984.0的零度子午面和CTP赤道的交点,y轴通过右手规则确定。

3.2 wgs84弧度计算

一般cesium使用这个计算坐标,把经纬度转变为弧度计算

  • 根据弧度创建实例:Cesium.Cartographic.fromRadians(longitude, latitude, height, result)
  • 经纬度=>弧度:Cesium.Cartographic.fromDegrees(longitude, latitude, height, result)

3.3 笛卡尔空间直角坐标系

1.png 笛卡尔空间直角坐标系:以地球中心作为原点计算坐标

3.4 平面坐标系

3.png 对于cesium来说通常用第一种坐标系

四、视图与场景

4.1 Viewer

在Cesium中Viewer是一切的开端,通过**new Cesium.Viewer(container, options)**来创建一个Viewer对象,可以把该对象理解为三维虚拟地球,在Viewer对象上的所有操作,可以看作是对三维虚拟地球的操作。 日常Cesium开发中,几乎都是围绕着这个对象展开的。

2.png

4.2 Scene

Scene为Cesium视图下的3D图形对象和状态的容器,Scene对象并不是显式创建的,而是由Viewer或CesiumWidget初始化视图时隐式创建的,通过Scene对象可以在视图下添加图形(primitive)、添加场景特效(如后处理特效postProcessStage)、添加场景事件或控制视图下的星空skyBox、大气层skyAtmosphere、地球globe、太阳sun和月亮moon。

4.3 Camera

在Cesium通过相机来操作场景的视角,从浏览器端看是场景移动,其实是相机移动,所以要注意方向。 例如:相机向左移,那么屏幕的场景就会偏右

我们通常可以使用相机的变换完成视角操作:

  • 飞行fly
  • 缩放zoom
  • 移动move
  • 视角look
  • 平面扭转twist
  • 3d旋转rotate
  • 将相机视角直接定位到某个位置setView
  • 用于将相机视角锁定到目标位置lookAt
  • 将地球或场景缩放到该实体的视图范围内viewer.zoomTo()

五、界面操作

5.1 视图控件隐藏

const viewer = new Cesium.Viewer('cesium-container',{
  timeline:false,
  fullscreenButton: false // 隐藏全屏按钮
}) 


// 隐藏版权信息
viewer._cesiumWidget._creditContainer.style.display = "none"

隐藏视图控件可以在创建视图的时候隐藏,如果一开始想要最简化的场景,可以使用下面的代码:

// 除了场景,其他控件都被隐藏
const viewer = new Cesium.CesiumWidget("cesiumContainer")

5.2 场景操作

// 场景操作
        // 显示帧率
        viewer.scene.debugShowFramesPerSecond=true
        viewer.scene.skyBox.show=false
        viewer.scene.sun.show = false  // 隐藏太阳

场景就是包含一些物体,可以通过上述的方法隐藏

六、影像和标注

6.1 影像

4.png

概述:所谓的影像就是附着在地球上面的一层贴图,有不同的供应商、创建方式、管理方式,可以叠加。 加载方式

// 引入token,装入容器
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0NmY4OGRkZS03ZTljLTQ5MDMtYmUwZC0wNmM2ZjdmM2M1MzMiLCJpZCI6MTI2MjUzLCJpYXQiOjE2NzczMTI2ODJ9.KO5KCez-xGcJBJfY8XYWAlUXHO4WWrZUm6tCZ1MfCWM'

// 1初始化添加图层,为空默认加载bingmaps
const viewer = new Cesium.Viewer('cesium-container',{
    // imageryProvider:new Cesium.ArcGisMapServerImageryProvider({
    //     url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
    // })
}) 
// 隐藏版权信息
viewer._cesiumWidget._creditContainer.style.display = "none"

//2 后续添加
const  arcGisImagery=new Cesium.ArcGisMapServerImageryProvider({
    url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
})
// viewer.imageryLayers.addImageryProvider(arcGisImagery)


//3更具ionCesium的资源库id添加,需要提前加好资源
const ionNightEarth=new Cesium.IonImageryProvider({assetId:3812})
viewer.imageryLayers.addImageryProvider(ionNightEarth)

管理方式

// 引入token,装入容器
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0NmY4OGRkZS03ZTljLTQ5MDMtYmUwZC0wNmM2ZjdmM2M1MzMiLCJpZCI6MTI2MjUzLCJpYXQiOjE2NzczMTI2ODJ9.KO5KCez-xGcJBJfY8XYWAlUXHO4WWrZUm6tCZ1MfCWM'

// 1初始化添加图层
const viewer = new Cesium.Viewer('cesium-container', {
    imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
        url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
    })
})
// 隐藏版权信息
viewer._cesiumWidget._creditContainer.style.display = "none"

//2 后续添加
const arcGisImageryLoad = new Cesium.ArcGisMapServerImageryProvider({
    url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
})
const arcGisImagery = viewer.imageryLayers.addImageryProvider(arcGisImageryLoad)


//3更具ionCesium的资源库id添加,需要提前加好资源
const ionNightEarthLoad= new Cesium.IonImageryProvider({ assetId: 3812 })
const ionNightEarth = viewer.imageryLayers.addImageryProvider(ionNightEarthLoad)

const target = viewer.imageryLayers._layers[1]
target.alpha = 0.5
target.brightness = 2.0
target.contrast = 1.0
// target.hue = 2.0
target.saturation = 1.0
target.gamma=1.0

// ImageryLayerCollection父类,资源导入无法识别,只有viewer.imageryLayers.addImageryProvider才行
const isContains=viewer.imageryLayers.contains(ionNightEarth)
console.log('是否包含',isContains);

const getImagery=viewer.imageryLayers.get(1)
console.log('下标寻找', getImagery);


// 图层移动,lower 1 - 0   raise 0 - 1
viewer.imageryLayers.lowerToBottom(ionNightEarth)


const index = viewer.imageryLayers.indexOf(ionNightEarth)
console.log('下标', index);

6.2 标注

概述:标注也是一层贴图,只不过可以显示具体的位置名称和相关信息

3.png

// 引入token,装入容器
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0NmY4OGRkZS03ZTljLTQ5MDMtYmUwZC0wNmM2ZjdmM2M1MzMiLCJpZCI6MTI2MjUzLCJpYXQiOjE2NzczMTI2ODJ9.KO5KCez-xGcJBJfY8XYWAlUXHO4WWrZUm6tCZ1MfCWM'


// 1初始化添加图层
const viewer = new Cesium.Viewer('cesium-container', {
  imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
    url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
  })
})
// 隐藏版权信息
viewer._cesiumWidget._creditContainer.style.display = "none"


//  1 高德地图标注
const guadMapLoad=new Cesium.UrlTemplateImageryProvider({
  url: "http://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8"
})
// viewer.imageryLayers.addImageryProvider(guadMapLoad)


//  2 天地图标注
const token= '374e3348e10cd75eea1440986e480412'
const webMapTileLoad=new Cesium.WebMapTileServiceImageryProvider({
  url: `http://t0.tianditu.com/cva_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cva&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${token}`,
  layer: "tdtAnnoLayer",
  style: "default",
  format: "image/jpeg",
  tileMatrixSetID: "GoogleMapsCompatible",
  show: false
})
viewer.imageryLayers.addImageryProvider(webMapTileLoad)

七、地形

Cesium默认加载的地形是没有起伏效果的,和影像加载方式一致。 外部加载

// 引入token,装入容器
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0NmY4OGRkZS03ZTljLTQ5MDMtYmUwZC0wNmM2ZjdmM2M1MzMiLCJpZCI6MTI2MjUzLCJpYXQiOjE2NzczMTI2ODJ9.KO5KCez-xGcJBJfY8XYWAlUXHO4WWrZUm6tCZ1MfCWM'

// 一个视图下地形只能加载一个,而影像图层是可以加载多个的
// 1初始化添加地形
const viewer = new Cesium.Viewer('cesium-container', {
        imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
        url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
    }),
    terrainProvider: new Cesium.ArcGISTiledElevationTerrainProvider({
        url: 'https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer',
    })
})
// 隐藏版权信息
viewer._cesiumWidget._creditContainer.style.display = "none"

// 2后期添加地形
const ArcGisTerrainProvider = new Cesium.ArcGISTiledElevationTerrainProvider({
        url: 'https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer',
})
viewer.terrainProvider = ArcGisTerrainProvider

Cesium ion 地形 6.png

const terrainProvider = Cesium.createWorldTerrain({
        requestWaterMask: true, // 请求水体效果所需要的海岸线数据
})
viewer.terrainProvider = terrainProvider

八、事件

Cesium中的事件按照类型进行分类,可以分为如下几种:

  • 鼠标键盘事件
  • 相机事件
  • 数据加载事件
  • 场景加载事件

九、实体

实体(entity)是Cesium中自带的创建图形的方法,通过该方法可以在场景中创建点、线、面、多边形、立方体、圆等基本图形,相当于three.js的物体。

7.png

const target= Cesium.Cartesian3.fromDegrees(118, 34, 0)
const boxEntity=viewer.entities.add({
    id:'123',
    name:'box-entity',
    position:target,
    box:{
        dimensions:new Cesium.Cartesian3(100,100,100),
        distanceDisplayCondition:new Cesium.DistanceDisplayCondition(0,10000),
        material:Cesium.Color.RED.withAlpha(0.5),
        fill:true,
        outline:true,
        outlineWidth:110,
        outlineColor:Cesium.Color.PINK,
        show:true
    }
})

十、图形

图形(Primitive)是Cesium中更加高阶的创建图形的方法,那么相对低阶的方法就是使用实体(Entity)定义一个图形。当创建一个图形时,两者的流程都是定义实体的尺寸大小和定义实体的材质外观。图形(Primitive)由两部分组成:

  1. 几何形状(Geometry):定义了Primitive的结构,例如三角形、线条、点等;
  2. 外观(Appearance ):定义Primitive的着色(Sharding),包括GLSL(OpenGL着色语言,OpenGL Shading Language)顶点着色器和片段着色器( vertex and fragment shaders),以及渲染状态(render state)。

8.png

十一、模型

11.1 gltf

图像库传输格式(Graphic Library Transmission Format, glTF)本质上是一种JSON文件,该文件描述包含以下内容的场景的结构和组成3D模型。 9.png

//目标位置与视角方向
const target=Cesium.Cartesian3.fromDegrees(118,34,100)
// 加载物体
const plane=viewer.entities.add({
    name:'flyingPlane',
    position:target,
    
    model:{
        uri:'../libs/Assets/models/CesiumDrone.glb',
        minimumPixelSize: 128,
        maximumScale: 20000,
    }

})

11.2 3dTitles

3dTiles三维模型使用了 glTF 规范,继承它的渲染高性能,除了嵌入的 glTF,3dTiles 自己 只记录各级Tile的空间逻辑关系(如何构成整个3dtiles)和属性信息,以及模型与属性如何挂接在一起的信息 10.png

//目标位置与视角方向
const tileset= viewer.scene.primitives.add(
    new Cesium.Cesium3DTileset({
        url: '../libs/Assets/3dTitles/tilesset/tileset.json',
    })
)

// 开始调整tileset位置和缩放大小
let params={
    // 模型中心经纬度和高度
    tx:118,
    ty:34,
    tz:0,

    // 模型旋转方向
    rx:0,
    ry:0,
    rz:0,

    // 缩放
    scale:0.5
}

// 显示3dtiles包围盒
tileset.debugShowContentBoundingVolume=true

// 开启 3D Tiles 监视器
// viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin)

// 修改 3D Tiles 的颜色和透明度
// tileset.style = new Cesium.Cesium3DTileStyle({
//     color: "color('rgba(178, 34, 34, 0.5)')", // 淡红色,透明度为0.5,半透明
// })

// 点击修改3dtiles颜色,使用坐标拾取
const handler=new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)

handler.setInputAction((target)=>{

    // 判断点击的元素
    const feature=viewer.scene.pick(target.position)
    if(feature instanceof Cesium.Cesium3DTileFeature){
        feature.color=Cesium.Color.RED
    }
    // console.log(feature.getProperty('Longitude'));
    console.log(target.position);
},Cesium.ScreenSpaceEventType.LEFT_CLICK)

// 后续修改模型
// 修改高度值大于50的3D Tiles的颜色和透明度
tileset.style = new Cesium.Cesium3DTileStyle({
    color: {
        // 条件筛选
        conditions: [
            ["${Height} > 50", "color('rgba(100,100,100, 0.5)')"],
        ]
    },
    show:'${Height} > 12'
})

资料

About

Cesium是一个用于显示三维地球的开源库,旨在释放3D数据的力量。Cesium基于WebGL技术,能够在Web平台搭建虚拟地球及场景展示应用。


Languages

Language:JavaScript 97.3%Language:CSS 2.0%Language:HTML 0.7%