cesium方法整理
一、安装依赖
// 安装cesium
npm install cesium --save
// 安装turf工具
npm install @truf/turf --save
// 安装cesium vite插件
npm install vite-plugin-cesim --save
二、项目中引用
import * as Cesium from 'cesium'
import 'cesium/Build/Cesium/Widgets/widgets.css'
import * as turf from '@turf/turf'
// 配置地图根目录
window.CESIUM_BASE_URL = '../Cesium'
三、具体方法介绍总结
1,生成地图电子底图(new Cesium.UrlTemplateImageryProvider({}))
let electronic = new Cesium.UrlTemplateImageryProvider({
url: 'url', // url 地址
fileExtension: "jpg" // 类型
})
2,生成地图卫星底图( new Cesium.ArcGisMapServerImageryProvider({}) )
let satellite = new Cesium.ArcGisMapServerImageryProvider({
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
})
3,初始实例化及相关配置( new Cesium.Viewer(id, {}) )
let viewer = new Cesium.Viewer(id, {
//需要进行可视化的数据源的集合
animation: false, //是否显示动画控件
selectionIndicator: false,
shouldAnimate: true, // 是否使用动画
homeButton: false, //是否显示Home按钮
fullscreenButton: false, //是否显示全屏按钮
baseLayerPicker: false, //是否显示图层选择控件
geocoder: false, //是否显示地名查找控件
timeline: false, //是否显示时间线控件
sceneModePicker: false, //是否显示投影方式控件
navigationHelpButton: false, //是否显示帮助信息控件
infoBox: false, //是否显示点击要素之后显示的信息
requestRenderMode: true, //启用请求渲染模式
scene3DOnly: false, //每个几何实例将只能以3D渲染以节省GPU内存
sceneMode: (config.mode == 'earth' && Cesium.SceneMode.SCENE3D) || (config.mode == '3D' && Cesium.SceneMode.COLUMBUS_VIEW) || Cesium.SceneMode.SCENE2D, //初始场景模式 1 2D模式 2 2D循环模式 3 3D模式 Cesium.SceneMode
fullscreenElement: document.body, //全屏时渲染的HTML元素 暂时没发现用处
imageryProvider: (config.baseLayer == 'satellite' && config.satellite) || config.electronic
});
//隐藏cesium左下角logo
viewer._cesiumWidget._creditContainer.style.display = 'none';
// 开启抗锯齿
viewer.scene.postProcessStages.fxaa.enabled = true
// 相机高度最大值,限制缩小级别
let cameraHeight = 1.1e7
viewer.scene.screenSpaceCameraController.maximumZoomDistance = cameraHeight * 3;
// 深度开启或关闭
viewer.scene.globe.depthTestAgainstTerrain = false;
// 取消默认的双击放大时间
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
// 引起事件监听的相机变化幅度
viewer.camera.percentageChanged = 0.02;
4, 注册地图事件(new Cesium.ScreenSpaceEventHandler())
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
// 监听地图鼠标左击
handler.setInputAction((click) => leftClickEvent(click), Cesium.ScreenSpaceEventType.LEFT_DOWN)
function leftClickEvent(click) {
// 鼠标左击回调函数
}
// 监听地图鼠标右击
handler.setInputAction((click) => rightClickEvent(click), Cesium.ScreenSpaceEventType.RIGHT_CLICK)
function rightClickEvent(click) {
// 鼠标右击回调函数
}
// 销毁句柄
handler.destroy()
5,获取鼠标点击位置(世界坐标系) (viewer.camera.getPickRay())
1、获取椭球上的点的经纬度(椭球上的点)
let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function(event) {
// 世界坐标、笛卡尔坐标
// enent.position 为屏幕坐标
let cartesian = viewer.camera.pickEllipsoid(event.position);
// 地理坐标 弧度
let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
// 地理坐标 经纬度
let lng = Cesium.Math.toDegrees(cartographic.longitude); // 经度
let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
let alt = cartographic.height; // 高度,椭球面height永远等于0
let coordinate = {
longitude: Number(lng.toFixed(6)),
latitude: Number(lat.toFixed(6)),
altitude: Number(alt.toFixed(2))
};
console.log(coordinate);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
2、获取地表面的点的经纬度(地形上的点)
let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function(event){
// 笛卡尔3 射线的位置和方向
// event.position 屏幕坐标
let ray = viewer.camera.getPickRay(event.position);
// 射线与渲染的地球表面之间的交点 世界坐标、笛卡尔坐标
let cartesian = viewer.scene.globe.pick(ray, viewer.scene);
// 地理坐标 弧度
let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
// 地理坐标 经纬度
let lng = Cesium.Math.toDegrees(cartographic.longitude); // 经度
let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
let alt = cartographic.height; // 高度
let coordinate = {
longitude: Number(lng.toFixed(6)),
latitude: Number(lat.toFixed(6)),
altitude: Number(alt.toFixed(2))
};
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
3、获取场景里的点的经纬度(模型上的点)
let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (event) {
let cartesian = viewer.scene.pickPosition(event.position);
let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
let lng = Cesium.Math.toDegrees(cartographic.longitude); // 经度
let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
let alt = cartographic.height; // 高度
let coordinate = {
longitude: Number(lng.toFixed(6)),
latitude: Number(lat.toFixed(6)),
altitude: Number(alt.toFixed(2))
};
console.log(coordinate);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
6,点击获取实体对象(viewer.scene.pick(position))
// 点击获取实体对象
// e.position 屏幕坐标
let pickedObject = viewer.scene.pick(e.position)
7,点击获取entity实体( viewer.entities.getById() )
let entity = viewer.entities.getById(id)
8.弧度角度转换
// 将角度转成弧度
Cesium.Math.toRadians(degrees)
// 将弧度转成角度
Cesium.Math.toDegrees(radians)
// 将笛卡尔坐标系中的点转换为地理坐标系中的点。
Cesium.Ellipsoid.cartesianToCartographic(cartesian)
// 将地理坐标系中的点转换为笛卡尔坐标系中的点。
Cesium.Ellipsoid.cartographicToCartesian(cartographic)
9.移动视图,设置相机飞行( viewer.camera.flyTo({}) )
// 将经纬度转成笛卡尔坐标
Cesium.Cartesian3.fromDegrees()
// 将经纬度坐标数组转成笛卡尔坐标数组
Cesium.Cartesian3.fromDegreesArray(degreesArray)
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(119.36401386990066, 31.18535721814696, 120000),
orientation: {
heading: Cesium.Math.toRadians(345.0),
pitch: Cesium.Math.toRadians(-60.0),
roll: Cesium.Math.toRadians(0.0)
}
})
10. 获取实体 具体 数据( entity.properties.data.getValue() )
// 获取实体具体数据
let data = entity.properties.data.getValue()
11.地图模式改变
// 切换到2D模式
viewer.scene.morphTo2D(1)
// 切换到3D模式
viewer.scene.morphTo3D()
// 切换到哥伦布模式
viewer.scene.morphToColumbusView()
// 获取中心视图 2D 3D
let centerPosition = getCenterPosition(),
// 哥伦布模式 记录之前的变化矩阵和距离
let originalView = getViewTransform(viewer)
/**
* @description: 获取变换矩阵和到中心点的距离
* @param {*} viewObj 地图对象
* @return {transform, distance} 变换矩阵,距离
*/
function getViewTransform(viewObj) {
let position = getCenterPosition()
if (!position) return
// 中心点
var centerPosition = Cesium.Cartesian3.fromDegrees(position.lon, position.lat, 0)
// 相机点
var endLat = Cesium.Math.toDegrees(viewObj.camera.positionCartographic.latitude)
var endlng = Cesium.Math.toDegrees(viewObj.camera.positionCartographic.longitude)
var height = viewObj.camera.positionCartographic.height;
var endPosition = Cesium.Cartesian3.fromDegrees(endlng, endLat, height)
// 距离
var distance = Cesium.Cartesian3.distance(centerPosition, endPosition)
// 矩阵
var transform = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Cartesian3.fromDegrees(position.lon, position.lat));
return {
transform: transform,
distance: distance
}
}
/**
* @description:获取地图中心点
* @return {lon, lat, height} 经度,纬度,高度
*/
function getCenterPosition() {
let centerResult = viewer.camera.pickEllipsoid(
new Cesium.Cartesian2(
viewer.canvas.clientWidth / 2,
viewer.canvas.clientHeight / 2,
),
)
let height = viewer.camera.positionCartographic.height || 10000;
if (!Cesium.defined(centerResult)) return false
let curPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(centerResult);
let curLongitude = (curPosition.longitude * 180) / Math.PI;
let curLatitude = (curPosition.latitude * 180) / Math.PI;
return {
lon: curLongitude,
lat: curLatitude,
height: height
}
}
// 监听场景转换完成事件
viewer.scene.morphComplete.addEventListener(() =>{
// 延迟相机转场
let timeout = setTimeout(() => {
if (config.mode == '2D' || config.mode == 'earth') {
if (!centerPosition) return
let position = Cesium.Cartesian3.fromDegrees(centerPosition.lon, centerPosition.lat, centerPosition.height)
viewer.camera.flyTo({
destination: position,
});
} else {
if (!originalView) return
var heading = viewer.camera.heading;
var pitch = viewer.camera.pitch;
viewer.camera.lookAtTransform(originalView.transform, new Cesium.HeadingPitchRange(heading, pitch, originalView.distance));
}
// 解除lookAtTransform的锁定
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
clearTimeout(timeout)
}, 1000)
})
12.cesium 是否定义了对象( Cesium.defined(对象) )
Cesium.defined(对象)
13.移除所有地图底图图层,添加地图底图( viewer.imageryLayers.removeAll(), viewer.imageryLayers.addImageryProvider() )
// 移除所有图层
viewer.imageryLayers.removeAll()
// 添加底图
viewer.imageryLayers.addImageryProvider(electronic)
14.卷帘图,把视图分割成两部分,每部分加载不同的底图
/**
* @description: 卷帘图:把视图分割成两部分,每部分加载不同的底图
*/
function initJuanlian() {
// 添加卷帘对比图
let layers = viewer.imageryLayers;
let leftMap = layers.addImageryProvider(config.electronic)
let rightMap = layers.addImageryProvider(config.satellite);
// 设置位置左右放置
leftMap.splitDirection = Cesium.SplitDirection.LEFT;
rightMap.splitDirection = Cesium.SplitDirection.RIGHT
// 分割占比
let slider = document.getElementById('juanlian');
slider.style.display = 'block';
viewer.scene.splitPosition = (slider.offsetLeft) / (slider.parentElement.offsetWidth);
// 事件
let handler = new Cesium.ScreenSpaceEventHandler(slider);
let moveActive = false;
handler.setInputAction(function () {
moveActive = true;
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
handler.setInputAction(function () {
moveActive = true;
}, Cesium.ScreenSpaceEventType.PINCH_START);
handler.setInputAction((e) => sliderMove(e, moveActive), Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.setInputAction((e) => sliderMove(e, moveActive), Cesium.ScreenSpaceEventType.PINCH_MOVE);
handler.setInputAction(function () {
moveActive = false;
}, Cesium.ScreenSpaceEventType.LEFT_UP);
handler.setInputAction(function () {
moveActive = false;
}, Cesium.ScreenSpaceEventType.PINCH_END);
}
/**
* @description: 分割线移动
* @param {*} movement
* @param {*} moveActive
*/
function sliderMove(movement, moveActive) {
if (!moveActive) {
return;
}
let slider = document.getElementById('juanlian');
let relativeOffset = movement.endPosition.x;
let splitPosition = (slider.offsetLeft + relativeOffset) / slider.parentElement.offsetWidth;
slider.style.left = 100.0 * splitPosition + '%';
viewer.scene.splitPosition = splitPosition;
}
15.视图放大
/**
* @description: 视图放大
*/
function zoomInView() {
var position = viewer.camera.positionCartographic;
viewer.camera.moveForward(position.height * 0.5)
}
16.视图缩小
/**
* @description: 视图缩小
*/
function zoomOutView() {
var position = viewer.camera.positionCartographic;
viewer.camera.moveBackward(position.height * 0.5)
}
17.移除实体(viewer.entities.remove(entity))
// 移除实体
viewer.entities.remove(entity)
18.创建CustomDataSource集合( new Cesium.CustomDataSource(name) )
// 创建 CustomDataSource 集合
let drawCollection = new Cesium.CustomDataSource(name)
// viewer.dataSources添加集合
viewer.dataSources.add(drawCollection)
19.添加线
/**
* @description: 添加线
* @param {*} positions
*/
function addLine(positions) {
let line = new Cesium.Entity({
name: '直线',
type: 'polyline',
polyline: {
positions: new Cesium.CallbackProperty(() => positions, false),
width: 2,
material: Cesium.Color.fromCssColorString("#1565c2").withAlpha(1),
clampToGround: true,
classificationType: Cesium.ClassificationType.BOTH
},
})
// 添加到集合
let _line = drawCollection.entities.add(line);
return _line
}
20.两点之间的距离( Cesium.Cartesian3.distance( points, points ) )
// 两点间的距离
// points 笛卡尔坐标
// distance 单位为米
let distance = Cesium.Cartesian3.distance(points,points)
21.算法 计算一个点是否在多边形里
/**
* 计算一个点是否在多边形里
* @param {Object} pt 标注点
* @param {Object} poly 多边形数组
*/
function isInsidePolygon(pt, poly) {
for (var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
((poly[i].lat <= pt.lat && pt.lat < poly[j].lat) || (poly[j].lat <= pt.lat && pt.lat < poly[i].lat)) &&
(pt.lng < (poly[j].lng - poly[i].lng) * (pt.lat - poly[i].lat) / (poly[j].lat - poly[i].lat) + poly[i].lng) &&
(c = !c);
return c;
}
22.经纬度转屏幕坐标
/**
* 经纬度转屏幕坐标
* @param {*} latlng 经纬度
* @return cartesian2-屏幕坐标
*/
function latlngToWindowCoordinates(latlng) {
let cartesian3 = Cesium.Cartesian3.fromDegrees(latlng.lon, latlng.lat, 0)
let cartesian2 = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, cartesian3);
return cartesian2
}