学习Cesiumjs
cesium在vite项目中使用
npm i vite-plugin-cesium cesium -D
离线使用cesium
const viewer = new Viewer(document.querySelector("#root"), {
imageryProvider: false,//在cesium1.128版本中已经移出了这个配置项,默认施加在cesium自己的底图,我们现在要使用离线的cesium,为来控制台不报错,设置false
baseLayerPicker: false,
}); Cesium.Ion.defaultAccessToken = undefined;
let viewer;
async function initCesium() {
viewer = new Cesium.Viewer('cesiumContainer', {
animation: false,
baseLayerPicker: false,
fullscreenButton: false,
vrButton: false,
geocoder: false,
homeButton: false,
infoBox: false,
sceneModePicker: false,
selectionIndicator: false,
timeline: false,
navigationHelpButton: false,
skyBox: false,
skyAtmosphere: false,
contextOptions: {
webgl: {
alpha: true,
failIfMajorPerformanceCaveat: false,
},
},
imageryProvider: false, //让控制台不报错 默认状态会加载cesium的底图
});
viewer.cesiumWidget.creditContainer.style.display = 'none';
// 添加底图
const provider = await Cesium.SingleTileImageryProvider.fromUrl(
'http://127.0.0.1:8004/blue.jpg'
);
viewer.scene.imageryLayers.addImageryProvider(provider);
viewer.scene.imageryLayers.addImageryProvider(
new Cesium.TileMapServiceImageryProvider({
url: 'http://127.0.0.1:8004/map/{z}/{x}/{reverseY}.jpg',
fileExtension: 'jpg',
tilingScheme: new Cesium.GeographicTilingScheme(),
})
// new Cesium.UrlTemplateImageryProvider({
// url: 'http://192.168.5.228:8004/map/{z}/{x}/{reverseY}.jpg',
// fileExtension: 'jpg',
// tilingScheme: new Cesium.GeographicTilingScheme(),
// })
);
}
initCesium();在 Cesium 1.128 版本中,主要有以下几种 TilingScheme:
GeographicTilingScheme (地理坐标切片方案):
- 基于地理坐标系(经纬度)
- 适用于全球范围的数据展示
- 经度范围:-180° 到 180°
- 纬度范围:-90° 到 90°
- 在高纬度地区变形较小
WebMercatorTilingScheme (墨卡托投影切片方案):
- 基于墨卡托投影
- 是最常用的网络地图切片方案
- 适用于 Google Maps、OpenStreetMap 等常见地图服务
- 在高纬度地区会产生较大变形
- 不能完全显示极地区域 这两种切片方案的主要区别:
投影方式:
- GeographicTilingScheme 使用等经纬度投影
- WebMercatorTilingScheme 使用墨卡托投影
使用场景:
GeographicTilingScheme 适合:
- 全球范围数据展示
- 需要精确经纬度的场景
- 极地区域的显示
WebMercatorTilingScheme 适合:
- 常见的网络地图服务
- 中低纬度地区的显示
- 与主流地图服务对接
创建视口容器
const viewer = new Cesium.Viewer('cesiumContainer', {
terrain: Cesium.Terrain.fromWorldTerrain(), //地形
baseLayerPicker: false, //右上角底图选择
fullscreenButton: false,
homeButton: false, //右上角小房子按钮
infoBox: false, //右上角信息框
sceneModePicker: false, //右上角地图3d/2d切换
navigationHelpButton: false, //右上角帮助按钮
navigationInstructionsInitiallyVisible: false, //右上角指南
selectionIndicator: false, //选中指示器
shadows: true, //阴影
timeline: false, //时间轴
animation: false,
geocoder: false, //搜索框
})更新渲染器和场景视图
//建议配合防抖一起使用
import _ from 'lodash';
window.addEventListener('resize',debounceResize);
const debounceResize = _.debounce(function(){
viewer.resize();//viewer.resize()方法会更新 Cesium 渲染器以适应新的窗口尺寸。它会重新分配 WebGL 资源,确保场景能够正确地渲染在新的尺寸下。
// viewer.scene对象也可以进行其他必要的更新操作,比如更新相机视角等
// 例如,根据新的窗口尺寸调整相机的纵横比
var canvas = viewer.scene.canvas;
var width = canvas.clientWidth;
var height = canvas.clientHeight;
viewer.camera.aspectRatio = width / height;
viewer.camera.updateProjectionMatrix();
})创建地形
方式1(异步):
const viewer = new Cesium.Viewer('cesiumContainer')
viewer.terrainProvider = await Cesium.createWorldTerrainAsync()//添加地形-解决加载3dtiles悬浮的问题方式2:
const viewer = new Cesium.Viewer("cesiumContainer", {
terrain: Cesium.Terrain.fromWorldTerrain(),
});隐藏cesiun的logo(隐藏版权)
viewer.cesiumWidget.creditContainer.style.display = 'none'// 隐藏版权Cesium 中用于创建边缘检测
Cesium.PostProcessStageLibrary.createEdgeDetectionStage() 是 Cesium 中用于创建边缘检测后处理阶段的方法。边缘检测是一种图像处理技术,旨在识别图像中的边界或边缘,使得图像的结构更加清晰,通常用于增强图像的视觉效果。
主要作用和参数:
目的:
- 增强场景的视觉效果,突出显示对象的边缘,以便于观察和分析。
- 边缘检测可以帮助用户更好地理解场景中的几何形状和结构。
使用:
- 在 Cesium 中,可以将边缘检测作为后处理效果添加到渲染管道中。通过这种方式,您可以在渲染场景时应用边缘检测效果。
基本参数:
createEdgeDetectionStage()方法可以接受一些可选的参数来定制效果,例如:
- edgeColor: 边缘的颜色。
- edgeWidth: 边缘的宽度。
- backgroundColor: 背景颜色。
使用示例:
jsconst viewer = new Cesium.Viewer('cesiumContainer'); // 创建边缘检测后处理阶段 const edgeDetectionStage = Cesium.PostProcessStageLibrary.createEdgeDetectionStage({ edgeColor: Cesium.Color.RED, // 设置边缘颜色 edgeWidth: 2.0 // 设置边缘宽度 }); // 将边缘检测后处理阶段添加到渲染管道中 viewer.scene.postProcessStages.add(edgeDetectionStage);
注意事项:
- 边缘检测效果可能会对性能产生影响,特别是在处理大型场景时。因此,建议根据实际需求谨慎使用。
- 可以与其他后处理效果结合使用,如模糊、亮度调整等,以达到更好的视觉效果。
通过使用 createEdgeDetectionStage(),您可以显著增强场景中对象的可见性和可理解性,特别是在复杂的环境中。
将世界坐标转换为地图上的经纬度高度
let cartographic = Cesium.Cartographic.fromCartesian(cartesianPosition)// 将世界坐标转换为地图上的经纬度高度
let longitude = Cesium.Math.toDegrees(cartographic.longitude)
let latitude = Cesium.Math.toDegrees(cartographic.latitude)
let height = cartographic.height使用Cesium的``或Label来创建动态信息框
function createInfoBox(longitude: any, latitude: any, height: any) {
// 创建新的信息标签
currentInfoLabel = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(longitude, latitude, height + 50), // 提高一点高度避免遮挡
label: {
text: `
Longitude: ${longitude.toFixed(6)}<br>
Latitude: ${latitude.toFixed(6)}<br>
Height: ${height.toFixed(2)} m<br>
`,
font: '14px sans-serif',
fillColor: Cesium.Color.BLACK,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -20), // 调整垂直偏移量
},
})
// 刷新视图
viewer.scene.requestRender()
}viewer.entities介绍
viewer.entities 是 Cesium 中用于管理和操作场景中各种实体(如点、线、多边形、标签、图标等)的一个集合。通过 viewer.entities,你可以轻松地添加、删除和修改这些实体,从而在 Cesium 场景中展示各种地理信息和标注。
主要功能
添加实体:
jsvar entity = viewer.entities.add({ position: Cesium.Cartesian3.fromDegrees(longitude, latitude, height), point: { color: Cesium.Color.RED, pixelSize: 10 }, label: { text: 'Hello, World!', font: '14px sans-serif', fillColor: Cesium.Color.BLACK, outlineColor: Cesium.Color.WHITE, outlineWidth: 2, style: Cesium.LabelStyle.FILL_AND_OUTLINE, verticalOrigin: Cesium.VerticalOrigin.BOTTOM } });获取实体:
var entity = viewer.entities.getById('entityId');删除实体:
viewer.entities.remove(entity);清空所有实体:
viewer.entities.removeAll();遍历所有实体:
viewer.entities.values.forEach(function(entity) { console.log(entity); });
示例:添加一个带有标签的点
var viewer = new Cesium.Viewer('cesiumContainer');
// 添加一个带有标签的点
var entity = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03925, 100.0),
point: {
color: Cesium.Color.RED,
pixelSize: 10
},
label: {
text: 'Philadelphia',
font: '14px sans-serif',
fillColor: Cesium.Color.BLACK,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM
}
});
// 刷新视图
viewer.scene.requestRender();cesium 改写默认鼠标事件 平移 缩放 旋转
1、修改鼠标中键为缩放
viewer.scene.screenSpaceCameraController.zoomEventTypes = [Cesium.CameraEventType.WHEEL, Cesium.CameraEventType.PINCH];2、修改鼠标右键旋转
viewer.scene.screenSpaceCameraController.tiltEventTypes = [Cesium.CameraEventType.PINCH, Cesium.CameraEventType.RIGHT_DRAG];相机控制
1.飞到某个地点
const destination = Cesium.Cartesian3.fromDegrees(config.center[0], config.center[1], config.height);
viewer.camera.flyTo({
destination: destination,
duration: 3.0, // 动画持续时间,单位为秒
orientation: {
heading: 0.0,
pitch: -Cesium.Math.PI_OVER_TWO,
roll: 0.0,
},
}) /**
* ## 加载舟山边界
*/
function loadBoundary() {
// 加载GeoJSON数据并设置边界样式
Cesium.GeoJsonDataSource.load(zhoushan, {
stroke: Cesium.Color.RED, // 边界线颜色
strokeWidth: 3, // 边界线宽度
fill: Cesium.Color.fromAlpha(Cesium.Color.BLUE, 0), // 填充颜色和透明度
})
.then((dataSource) => {
// 将GeoJSON数据添加到地图中
viewer.dataSources.add(dataSource);
GeoJsonDataSource = dataSource;
// 让视图聚焦到GeoJSON区域
if (!isint) {
viewer.flyTo(dataSource, {
duration: 2, // 飞行持续时间(秒)
offset: new Cesium.HeadingPitchRange(
0, // heading(航向角):0 表示朝北
Cesium.Math.toRadians(-70), // pitch(俯仰角):负值表示向下看,-45度
500000 // range(距离):米
),
});
isint = true;
} else {
viewer.zoomTo(dataSource);
}
})
.catch((error) => {
console.error('加载GeoJSON失败:', error);
});
}2.移动到某一个点
viewer.zoomTo(dataSource);限制相机的俯仰角度
const viewer = new Cesium.Viewer('cesiumContainer');
// 获取 ScreenSpaceCameraController
const cameraController = viewer.scene.screenSpaceCameraController;
// 设置俯仰角度限制(例如限制为 45 度)
cameraController.maximumTiltAngle = Cesium.Math.toRadians(45);关于Cesium.GeoJsonDataSource.load()加载geojson,设置边界的宽度不生效的问题
Cesium.GeoJsonDataSource.load(zhoushan, {
stroke: Cesium.Color.fromCssColorString('#00203f'), // 边界线颜色
strokeWidth: 2, // 边界线宽度
fill: Cesium.Color.fromAlpha(Cesium.Color.BLUE, 0), // 填充颜色和透明度
})
.then((dataSource) => {
viewer.dataSources.add(dataSource);
}使用上述的方法加载geojson,绘制边界线发现设置strokeWidth边界线的粗细不生效的。
原因是你的geojson文件

如果你加载的是MultiPolygon类型的话 代表是个多边形的 所以strokeWidth无效,将MultiPolygon转换成MultiLineString即可

如果不想转换的话也可以实现,通过给entity.polygon添加材质实现边界线的线条粗细
function loadBoundary() {
// 加载GeoJSON数据并设置边界样式
Cesium.GeoJsonDataSource.load(zhoushan, {
stroke: Cesium.Color.fromCssColorString('#00203f'), // 边界线颜色
strokeWidth: 2, // 边界线宽度
fill: Cesium.Color.fromAlpha(Cesium.Color.BLUE, 0), // 填充颜色和透明度
})
.then((dataSource) => {
// 将GeoJSON数据添加到地图中
dataSource.entities.values.forEach(function (entity) {
if (entity.polygon) {
entity.polygon.outline = false;
var positions = entity.polygon.hierarchy._value.positions;
entity.polyline = {
positions: positions,
width: 2,
material: Cesium.Color.fromCssColorString('#00203f'),
};
}
});
viewer.dataSources.add(dataSource);
})
.catch((error) => {
console.error('加载GeoJSON失败:', error);
});
}材质
电子围墙
/*
动态墙材质
color 颜色
duration 持续时间 毫秒
trailImage 贴图地址
*/
import * as Cesium from 'cesium'
export default class DynamicWallMaterialProperty {
constructor(options) {
// 默认参数设置
this._definitionChanged = new Cesium.Event() // 材质定义变更事件
this._color = undefined // 颜色属性
this._colorSubscription = undefined // 颜色变化订阅
this.color = options.color // 从选项中获取颜色
this.duration = options.duration // 持续时间
this.trailImage = options.trailImage // 路径图像
this._time = new Date().getTime() // 当前时间戳
this._viewer = options.viewer // Cesium 视图对象
}
// 返回材质类型
getType(time) {
return MaterialType // 返回材质类型名称
}
getValue(time, result) {
if (!Cesium.defined(result)) {
result = {} // 如果结果未定义,则初始化为空对象
}
result.color = Cesium.Property.getValueOrClonedDefault(
this._color, // 获取颜色值
time, // 当前时间
Cesium.Color.WHITE, // 默认颜色为白色
result.color // 结果对象中的颜色属性
)
// 使用自定义的路径图像
result.image = this.trailImage
// 计算时间进度
if (this.duration) {
result.time =
((new Date().getTime() - this._time) % this.duration) / this.duration
}
this._viewer.scene.requestRender() // 请求重新渲染场景
return result
}
// 比较两个 DynamicWallMaterialProperty 对象是否相等
equals(other) {
return (
this === other || // 判断是否为同一对象
(other instanceof DynamicWallMaterialProperty && // 判断是否为 DynamicWallMaterialProperty 的实例
Cesium.Property.equals(this._color, other._color)) // 比较颜色属性
)
}
}
/**
* 带方向的墙体
* @param {*} options.get:true/false
* @param {*} options.count:数量
* @param {*} options.freely:vertical/standard
* @param {*} options.direction:+/-
*/
function _getDirectionWallShader(options) {
if (options && options.get) {
// 定义了一个函数 czm_getMaterial,输入参数为 materialInput,返回值为 czm_material 类型的材质。
var materail = `czm_material czm_getMaterial(czm_materialInput materialInput)
{
// 调用 czm_getDefaultMaterial 函数获取一个默认的材质实例,并将其存储在 material 变量中
czm_material material = czm_getDefaultMaterial(materialInput);
// 获取纹理坐标(st)的二维向量
vec2 st = materialInput.st;`
// 垂直方向动态效果
if (options.freely == 'vertical') {
//(由下到上)
// texture(image, vec2(u,v)),st.s 是水平方向上的纹理坐标,st.t 是垂直方向上的纹理坐标。
// 如果要实现上下垂直滚动的效果,就要设置st.t随时间的动态,而st.s值不变。
// 如果要实现左右水平滚动的效果,就要设置st.s随时间的动态,而st.t值不变。
materail +=
// 纹理采样,依据时间动态变化,fract 函数用于计算余数,使纹理坐标在[0, 1)范围内循环。
'vec4 colorImage = texture(image, vec2(fract(st.s), fract(float(' +
options.count +
')*st.t' +
options.direction +
' time)));\n '
} else {
// 水平方向的动态效果
//(逆时针)
materail +=
'vec4 colorImage = texture(image, vec2(fract(float(' +
options.count +
')*st.s ' +
options.direction +
' time), fract(st.t)));\n '
console.log('materail2: ', materail)
}
//泛光
materail += `vec4 fragColor;
fragColor.rgb = (colorImage.rgb+color.rgb) / 1.0;
fragColor = czm_gammaCorrect(fragColor);
material.diffuse = colorImage.rgb;
material.alpha = colorImage.a;
material.emission = fragColor.rgb;
return material;
}`
return materail
}
}
// 定义属性
Object.defineProperties(DynamicWallMaterialProperty.prototype, {
isConstant: {
get: function () {
return false // 返回材质是否是常量(动态材质返回 false)
},
},
definitionChanged: {
get: function () {
return this._definitionChanged // 返回定义变更事件
},
},
color: Cesium.createPropertyDescriptor('color'), // 创建颜色属性描述符
})
// 定义一个变量MaterialType,其值为字符串'wallType'加上一个随机数
var MaterialType = 'wallType' + parseInt(Math.random() * 1000)
// 定义默认图像路径
let DynamicWallImage = '/src/assets/col.png'
// 将材质添加到缓存中
Cesium.Material._materialCache.addMaterial(MaterialType, {
fabric: {
type: MaterialType, // 设置材质类型
uniforms: {
color: new Cesium.Color(1.0, 0.0, 0.0, 0.5), // 设置颜色属性
image: DynamicWallImage, // 设置图像路径
time: -20, // 设置时间属性
},
source: _getDirectionWallShader({
get: true,
count: 3.0,
freely: 'vertical', //或者standard
direction: '+',
}),
},
translucent: function (material) {
return true // 确定材质是否是半透明的
},
})调用:
import DynamicWallMaterialProperty from '../../utils/cesium/WallDiffuseDymaticMaterial.js'
let positions = Cesium.Cartesian3.fromDegreesArray([
113.8236839, 22.528061, 113.9236839, 22.628061, 114.0236839, 22.528061,
113.9236839, 22.428061, 113.8236839, 22.528061,
])
// 绘制墙体
const wall = viewer.entities.add({
name: '立体墙效果',
wall: {
positions: positions,
// 设置高度
maximumHeights: new Array(positions.length).fill(600),
minimumHeights: new Array(positions.length).fill(0),
material: new DynamicWallMaterialProperty({
viewer,
// trailImage: '/src/assets/vertical.png',
trailImage: '/src/assets/standard.png',
color: Cesium.Color.RED,
duration: 1500,
}),
},
})
viewer.zoomTo(wall)1.垂直方向
- 往下滚动
vec4 colorImage = texture(image, vec2(fract(st.s), fract(float(3)*st.t + time)));
source: _getDirectionWallShader({
get: true,
count: 3.0,
freely: 'vertical', //或者standard
direction: '+',
}),- 往上滚动
vec4 colorImage = texture(image, vec2(fract(st.s), fract(float(3)*st.t - time)));
source: _getDirectionWallShader({
get: true,
count: 3.0,
freely: 'vertical', //或者standard
direction: '-',
}),2.水平方向
- 顺时针
php 代码解读复制代码vec4 colorImage = texture(image, vec2(fract(float(8)*st.s - time), fract(st.t)));
source: _getDirectionWallShader({
get: true,
count: 20.0,
freely: 'standard', //或者standard
direction: '-',
}),- 逆时针
php 代码解读复制代码vec4 colorImage = texture(image, vec2(fract(float(8)*st.s + time), fract(st.t)));
source: _getDirectionWallShader({
get: true,
count: 20.0,
freely: 'standard', //或者standard
direction: '+',
}),