目录
方法二:使用Cesium.Terrain.fromWorldTerrain()方法
1.准备
(1)安装依赖
npm install cesium
npm install vite-plugin-cesium
(2)申请token
官网网址:Cesium: The Platform for 3D Geospatial
在官网注册/登录即可创建并使用token
(3)基本实例
代码:
<template>
<div id="cesiumContainer">
</div>
</template>
<script lang="ts" setup>
import * as Cesium from 'cesium'
// 配置token
Cesium.Ion.defaultAccessToken = '你的token';
// 用于接收初始化时返回的实例 可用于访问属性或调用方法
let viewer;
// 初始化时的配置
const cesiumConfig = {
sceneMode: Cesium.SceneMode.COLUMBUS_VIEW, // 以何种模式(2D、3D等)查看地图
homeButton: false, // home按钮
geocoder: false, // 搜索框
navigationHelpButton: false, // 帮助按钮
sceneModePicker: false, // 场景模式选择按钮
baseLayerPicker: false, // 地图模式选择按钮
animation: false, // 动画按钮
timeline: false, // 时间轴
fullscreenButton: false, // 全屏按钮
// terrain: Cesium.Terrain.fromWorldTerrain(), // 使用官方的地形
}
const init = async() => {
// 创建地图
viewer = new Cesium.Viewer('cesiumContainer', cesiumConfig)
}
onMounted(() => {
init()
})
</script>
<style lang="scss" scoped>
#cesiumContainer {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
}
::v-deep(.cesium-viewer-bottom){
display: none !important;
}
</style>
运行结果:
若要展示球形世界地图的话可将上述代码中配置参数中的sceneMode属性注释掉
效果如下
此时默认展示的是北美区域,若要设置为亚洲区域可在初始函数中添加Cesium.Camera.DEFAULT_VIEW_RECTANGLE设置默认展示区
const init = async() => {
// 默认展示区域 其中4个参数分别表示矩形区域的左、下、右、上这4边的经纬度
// 第一个参数表示 矩形的左边位于东经80度
// 第二个参数表示 矩形的下边位于北纬10度
// 第三个参数表示 矩形的右边位于东经120度
// 第四个参数表示 矩形的上边位于北纬80度
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(80, 10, 120, 80);
// 创建地图
viewer = new Cesium.Viewer('cesiumContainer', cesiumConfig)
}
效果如下
2.Viewer
介绍
作用:初始化地图,生成的实例可进一步用于操作地图的位置、视角等
语法:new Cesium.Viewer(container, options)
container: 作用的元素ID
options:初始化时的配置参数
// 创建地图
viewer = new Cesium.Viewer('cesiumContainer', {})
通过访问viewer下的属性(成员)可以调用许多方法,如viewer.camera.flyTo()、viewer.entities.add()等等。
1.camera成员
初始化的实例viewer的camera属性可调用相关方法来进行地图操作,查看文档
flyTo()方法
作用:将相机从当前位置飞到新位置,即过渡性地切换视角
语法:flyTo(options)
viewer.camera.flyTo({
// 目的地
destination : Cesium.Cartesian3.fromDegrees(-122.19, 46.25, 9000.0),
// 方向
orientation : {
heading : Cesium.Math.toRadians(175.0), // 航向角
pitch : Cesium.Math.toRadians(-35.0), // 倾斜角
roll : 0.0 // 横滚角
}
});
flyHome()方法
作用:将相机视角切换到地图的默认视角
语法:flyHome(duration)
duration参数表示数据切换花费时间,可不填
const flyHome = () => {
if(!viewer) return;
viewer.camera.flyHome()
}
setView()方法
作用:设置相机的位置,用法与flyTo相似
语法:setView(options)
viewer.camera.setView({
// 目的地
destination : Cesium.Cartesian3.fromDegrees(-122.19, 46.25, 9000.0),
// 方向
orientation : {
heading : Cesium.Math.toRadians(175.0),
pitch : Cesium.Math.toRadians(-35.0), // 倾斜度
roll : 0.0
}
});
moveEnd事件
作用:用于监听相机停止移动
注:用户手动调整或调用方法调整相机视角都会在操作完成后触发此事件,注意使用场景
viewer.camera.moveEnd.addEventListener(() => {
console.log("相机已停止移动");
});
2.entities成员
实例viewer的camera属性可用于在地图中进行添加、删除实体(如3D模型)等操作,参看文档
add()方法
作用:添加实体到地图中
语法:add(options | entity)
// 构造实体的属性
const entityOption = {
// id: 3, // 不填自动生成
name: '红色立方体', // 实体的名称
position: Cesium.Cartesian3.fromDegrees(104.055013, 30.588327, 15000.0), // 实体中心点坐标
// 实体的类型
box: {
dimensions: new Cesium.Cartesian3(1000, 1000, 1000), // 实体尺寸
material: Cesium.Color.RED.withAlpha(0.5), // 实体颜色
outline: true, // 是否渲染轮廓线
outlineColor: Cesium.Color.BLACK // 轮廓线颜色
}
}
// 添加实体到地图中
function addAnEntity() {
// 1. 参数为属性选项
const returnVal= viewer.entities.add(entityOption);
// 2. 参数为实体
// const entityObj = new Cesium.Entity(entityOption);
// const returnVal= viewer.entities.add(entityObj);
// 返回值returnVal就是被添加的实体
// 可调用viewer.flyTo()或viewer.zoomTo()方法定位至此实体
viewer.flyTo(returnVal);
}
remove()方法
作用:用于删除地图中某一个具体的实体
语法:remove(entity)
// 删除实体 参数为一个实体实例
function removeEntity(entityItem) {
const result = viewer.entities.remove(entityItem);
// 返回值为布尔值 删除成功返回true 不存在此实体则返回false
if(result) console.log('此实体已删除');
}
removeById()方法
作用:删除与id对应的实体
语法:removeById(id) 其中的id是在创建实体配置的ID
removeAll()方法
作用:删除地图中所用的实体
contains()方法
作用: 判断某实体是否已经添加到了地图中
语法:contains(entity)
// 创建一个实体
const entityObj = new Cesium.Entity({
name: '红色立方体', // 实体的名称
position: Cesium.Cartesian3.fromDegrees(104.055013, 30.588327, 15000.0), // 实体中心点坐标
// 实体的类型
box: {
dimensions: new Cesium.Cartesian3(1000, 1000, 1000), // 实体尺寸
material: Cesium.Color.RED.withAlpha(0.5), // 实体颜色
outline: true, // 是否渲染轮廓线
outlineColor: Cesium.Color.BLACK // 轮廓线颜色
}
})
// 添加实体到地图中
function addAnEntity() {
// 实体集中是否有此实体,返回一个布尔值
const existObj = viewer.entities.contains(entityObj);
// 如果此实体集中已有此实体,调用add方法会报错
if(!existObj) viewer.entities.add(entityObj);
}
示例
1.将3D模型添加到地图中
方法一:访问Cesium仓库中的模型ID
首先在Cesium官网自己的仓库中上传3D模型文件,步骤如下
之后可以在仓库中查看上传的文件
具体使用代码如下
// 创建模型
async function createModel(id, height) {
viewer.entities.removeAll(); // 清除所有实体(如3D模型)
const position = Cesium.Cartesian3.fromDegrees( // 根据给定的经纬度返回一个笛卡尔3位置
-123.0744619, // 经度
44.0503706, // 纬度
height, // 高度(选填) 单位:米
);
const heading = Cesium.Math.toRadians(135); // 将度数转换为弧度
const pitch = 0;
const roll = 0;
const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll); // 得到航向、俯仰和横滚的旋转
const orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr); // 根据位置和三维旋转得到方向
const resource = await Cesium.IonResource.fromAssetId(id); // 根据实例ID获取Cesium仓库中对应的资源
const entity = viewer.entities.add({
id, // 创建的实体ID 不能重复 不填会自动生成
name: "大熊猫", // 模型名称 点击模型会显示此值
position: position,
orientation: orientation,
model: {
uri: resource,
scale: 1, // 模型放大倍数
minimumPixelSize: 128, // 模型最小的像素大小
maximumScale: 2, // 模型的最大发大倍数
},
});
viewer.trackedEntity = entity; // 相机定位至此实体并以此实体为中心观察
// viewer.zoomTo(entity); // 进定位至此实体
}
createModel方法参数说明:
id:模型文件的ID
height: 模型位置的高度
注:代码中的viewer.trackedEntity = entity;会使相机定位至实体,同时以此实体为中心进行观察(即点击鼠标左键进行拖动时会以此实体为中心进行旋转)。若不想以实体为中心,可使用viewer.zoomTo或viewer.flyTo方法使相机定位至实体。跳转参考文档
效果图如下
2.让3D模型在地图中运动
案例一:沿着轨迹循环运动
const modelMove = () => {
// 运动路径点
const pathPoints = [
{"longitude":104.055013,"latitude":30.598337,"height":0.0},
{"longitude":104.055024,"latitude":30.658342,"height":100.0},
{"longitude":104.055024,"latitude":30.758342,"height":200.0},
{"longitude":104.155024,"latitude":30.758342,"height":400.0},
{"longitude":104.155024,"latitude":30.658342,"height":150.0},
{"longitude":104.055013,"latitude":30.598337,"height":0.0}
]
const timeStepInSeconds = 100; // 两点之间的运动时间(秒)
const totalSeconds = timeStepInSeconds * (pathPoints.length - 1); // 总运动时间(秒)
const start = Cesium.JulianDate.now(); // 运动的开始时间
const stop = Cesium.JulianDate.addSeconds(start, totalSeconds, newCesium.JulianDate()); // 运动的结束时间
// 设置时间轴的时间
viewer.clock.startTime = start.clone(); // 设置开始时间
viewer.clock.stopTime = stop.clone(); // 设置结束时间
viewer.clock.currentTime = start.clone(); // 设置当前时间
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; // 循环播放运动
viewer.timeline.zoomTo(start, stop);
viewer.clock.multiplier = 2; // 设置播放速度为2倍
viewer.clock.shouldAnimate = true; // 开始播放场景
// 变量positionProperty用于存储路径点列表中每一项的位置及时间戳
const positionProperty = new Cesium.SampledPositionProperty();
pathPoints.forEach((dataPoint, dataPointIndex)=>{
// 得到此点的时间戳
const time = Cesium.JulianDate.addSeconds(start, dataPointIndex * timeStepInSeconds, new Cesium.JulianDate());
// 得到此点的位置
const position = Cesium.Cartesian3.fromDegrees(dataPoint.longitude, dataPoint.latitude, dataPoint.height);
// 存储此点的时间戳和位置
positionProperty.addSample(time, position);
// 添加此点的实体
viewer.entities.add({
description: `Location: (${dataPoint.longitude}, ${dataPoint.latitude}, ${dataPoint.height})`,
position: position,
point: { pixelSize: 10, color: Cesium.Color.RED }
});
})
// 将3D模型加载到地图中并用变量start、stop、positionProperty设置其位置及朝向等信息
loadModel(start, stop, positionProperty);
}
async function loadModel(start, stop, positionProperty) {
const airplaneUri = await Cesium.IonResource.fromAssetId('存储在Cesium Ion上的模型Id');
// 加载3D模型到地图中
const airplaneEntity = viewer.entities.add({
availability: new Cesium.TimeIntervalCollection([ new Cesium.TimeInterval({ start: start, stop: stop }) ]),
position: positionProperty,
model: { uri: airplaneUri },
orientation: new Cesium.VelocityOrientationProperty(positionProperty),
path: new Cesium.PathGraphics({ width: 3 })
})
viewer.trackedEntity = airplaneEntity;
}
3.在地图中添加3D瓦片
案例一:添加单个建筑瓦片
首先需上传3D瓦片到Cesium Ion上,并设置此瓦片的地理位置
之后即可引用此瓦片ID在地图中渲染
const renderTile = async() => {
const newBuildingTileset = await Cesium.Cesium3DTileset.fromIonAssetId('3D瓦片的ID');
viewer.scene.primitives.add(newBuildingTileset);
viewer.flyTo(newBuildingTileset);
}
案例二:使用月球3D tiles全局平铺
在Cesium Ion上下载月球的3D tiles
将初始化的代码改为以下
const init = async() => {
// 将默认椭球体设置为月球
Cesium.Ellipsoid.default = Cesium.Ellipsoid.MOON;
// 创建地图
viewer = new Cesium.Viewer('cesiumContainer', {
homeButton: false,
navigationHelpButton: false,
baseLayerPicker: false,
animation: false,
timeline: false,
fullscreenButton: false,
sceneModePicker: false, // 隐藏场景模式选择按钮
globe: false, // 隐藏地球数据
geocoder: false // 隐藏搜索部件
});
// 使用月球3D tiles
const MoonUrl = await Cesium.Cesium3DTileset.fromIonAssetId('资源ID');
viewer.scene.primitives.add(MoonUrl);
}
4.在地图中创建三维实体
案例一:创建立方体
function createCube() {
const cubeItem = viewer.entities.add({
name: 'red cube', // 实体的名称,点击实体会展示此值
position: Cesium.Cartesian3.fromDegrees(104.055013, 30.588327, 15000.0), // 实体中心点坐标
box: {
dimensions: new Cesium.Cartesian3(1000, 1000, 1000), // 实体尺寸
material: Cesium.Color.RED.withAlpha(0.5), // 实体颜色
outline: true, // 是否渲染轮廓线
outlineColor: Cesium.Color.BLACK // 轮廓线颜色
}
});
viewer.zoomTo(cubeItem); // 相机定位至此实体
}
执行方法后:
案例二:创建椭圆面柱
// 椭圆
function createEllipse() {
// 椭圆面
const twoDimension = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-103.0, 40.0), // 中心点坐标
name: '椭圆面实体',
ellipse: {
semiMinorAxis: 250000.0,
semiMajorAxis: 400000.0,
material: Cesium.Color.RED.withAlpha(0.5),
}
})
// 椭圆柱
const threeDimension = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-95.0, 40.0, 100000.0), // 中心点坐标
name: '椭圆柱实体',
ellipse: {
semiMinorAxis: 250000.0,
semiMajorAxis: 400000.0,
material: Cesium.Color.BLUE.withAlpha(0.5),
extrudedHeight: 200000, // 椭圆柱高度
rotation: Cesium.Math.toRadians(90) // 水平方向旋转角度
}
})
viewer.zoomTo(viewer.entities);
}
执行方法后:
其中的material属性除了颜色外还可换成图片地址
ellipse: {
semiMinorAxis: 250000.0,
semiMajorAxis: 400000.0,
material: 'https://img0.baidu.com/it/u=3657758641,4157505483&fm=253&fmt=auto&app=138&f=JPEG?w=892&h=500',
}
效果入下:
5.配置地形
初始化地图时可配置地形,即使用哪类地形资源来展示地图
方法一:引用Cesium Ion上的地形ID
const viewer = new Cesium.Viewer("cesiumContainer", {
terrain: new Cesium.Terrain(Cesium.CesiumTerrainProvider.fromIonAssetId('你的地形资源ID'));
});
方法二:使用Cesium.Terrain.fromWorldTerrain()方法
const viewer = new Cesium.Viewer("cesiumContainer", {
terrain: Cesium.Terrain.fromWorldTerrain()
});
库/文档
1.vue-cesium
介绍:主要用于vue3的库,含组件及API