<!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, maximum-scale=1, minimum-scale=1, user-scalable=no" />
<title>Cesium示例集--测量平面面积</title>
<script type="text/javascript" src="./cesium/Cesium.js"></script>
<script type="text/javascript" src="./libs/turf.min.js"></script>
<link rel="stylesheet" href="./cesium/Widgets/widgets.css">
<style type="text/css">
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
}
.cesium-container {
width: 100%;
height: 100%;
position: relative;
}
.opt-bar {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, .8);
padding: 5px 10px;
border-radius: 2px;
>a {
font-size: 14px;
color: #00e7ff;
cursor: pointer;
margin: 0 10px;
}
}
</style>
</head>
<body onload="load()">
<div id="cesiumContainer" class="cesium-container"></div>
<div class="opt-bar">
<a onclick="startEdit()">测量平面面积</a>
<a onclick="clearEdit()">清除</a>
</div>
<div id="toolTip" style="position: absolute;font-size: 12px;background: rgba(0,0,0,.8);color:#fff;padding: 3px 5px;"
style="display: none;"></div>
<script>
function getMapExtent () {
let camera = viewer.scene.camera;
let pos = {
position: camera.position,
heading: camera.heading,
pitch: camera.pitch,
roll: camera.roll,
};
console.log('屏幕当前范围:', pos);
}
var handler, viewer;
var labels = [], movePush = false, positions = [], floatLabel = null, polyline = null, polygon = null, controlPoints = [];
var tooltip = document.getElementById("toolTip");
function load () {
viewer = new Cesium.Viewer("cesiumContainer", {
animation: false,//是否创建动画小器件,左下角仪表
fullscreenButton: false,//是否显示全屏按钮
// geocoder: false,//是否显示geocoder小器件,右上角查询按钮
// homeButton: false,//是否显示Home按钮
infoBox: false,//是否显示信息框
// sceneModePicker: false,//是否显示3D/2D选择器
// scene3DOnly: false,//如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源
selectionIndicator: false,//是否显示选取指示器组件
timeline: false,//是否显示时间轴
// navigationHelpButton: false,//是否显示右上角的帮助按钮
baselLayerPicker: false,// 将图层选择的控件关掉,才能添加其他影像数据
shadows: false,//是否显示背影
baseLayerPicker: false,//是否显示图层选择器
imageryProvider: new Cesium.UrlTemplateImageryProvider({
url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}.png'
})
});
//去除版权信息
viewer._cesiumWidget._creditContainer.style.display = "none";
//屏蔽Cesium的默认双击追踪选中entity行为
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
);
//默认开启地形
// viewer.terrainProvider = Cesium.createWorldTerrain();
var pos = {
"position": {
"x": -2463425.8997346475,
"y": 4873855.487729879,
"z": 3288016.4618711653
},
"heading": 0.1341636770247039,
"pitch": -0.817714806133921,
"roll": 0.00001433107210147
};
viewer.camera.flyTo({
destination: new Cesium.Cartesian3(
pos.position.x,
pos.position.y,
pos.position.z
),
orientation: {
heading: pos.heading,
pitch: pos.pitch,
roll: pos.roll,
},
});
}
function clearEdit () {
positions = [];
if (polyline) {
viewer.entities.remove(polyline);
polyline = null;
}
if (polygon) {
viewer.entities.remove(polygon);
polygon = null;
}
labels = [];
for (var ind = 0; ind < controlPoints.length; ind++) {
viewer.entities.remove(controlPoints[ind]);
}
controlPoints = [];
if (floatLabel) {
viewer.entities.remove(floatLabel);
floatLabel = null;
}
floatLabel = null;
if (handler) {
handler.destroy();
handler = null;
}
movePush = false;
viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
viewer.trackedEntity = undefined;
}
function startEdit () {
clearEdit();
tooltip.style.display = "block";
handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
//左键单击,开始绘制
handler.setInputAction(function (evt) {
// tooltip.style.display = "none";
var cartesian = getCatesian3FromPX(evt.position, viewer).cartesian;
if (!cartesian) return;
if (movePush) {
positions.pop();
movePush = false;
}
var point = createPoint(cartesian.clone());
point.wz = positions.length; // 和坐标点关联
controlPoints.push(point);
positions.push(cartesian);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//鼠标移动
handler.setInputAction(function (evt) {
tooltip.style.left = evt.endPosition.x + 40 + "px";
tooltip.style.top = evt.endPosition.y + 30 + "px";
if (positions.length < 1) {
tooltip.innerHTML = '<p>单击开始绘制</p>';
return;
}
tooltip.innerHTML = '<p>双击结束,右键取消上一步</p>';
var cartesian = getCatesian3FromPX(evt.endPosition, viewer).cartesian;
if (!cartesian) return;
if (positions.length >= 1) {
if (!movePush) {
positions.push(cartesian);
movePush = true;
} else {
positions[positions.length - 1] = cartesian;
}
if (positions.length == 2) {
if (!Cesium.defined(polyline)) {
polyline = createPolyline();
}
}
if (positions.length == 3) {
if (!Cesium.defined(polygon)) {
polygon = createPolygon();
polygon.isFilter = true;
polygon.objId = Number((new Date()).getTime() + "" + Number(Math.random() * 1000).toFixed(0));
}
if (!floatLabel) {
floatLabel = createLabel(cartesian, "", {
style: Cesium.LabelStyle.FILL,
showBackground: true,
backgroundColor: Cesium.Color.fromCssColorString('#303336'),
pixelOffset: new Cesium.Cartesian2(0, -50)
});
floatLabel.label.heightReference = 1;
}
}
if (polygon) {
var areaCenter = getAreaAndCenter(positions)
var area = areaCenter.area;
var center = areaCenter.center;
var text = formateArea(area);
floatLabel.label.text = `平面面积:${text}`;
floatLabel.area = area;
if (center) floatLabel.position.setValue(center);
floatLabel.show = true;
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
//右键取消上一步
handler.setInputAction(function (evt) {
if (!polyline && !polygon) return;
if (positions.length <= 2) return; // 默认第一个不给删除
positions.splice(positions.length - 2, 1);
viewer.entities.remove(controlPoints.pop()); // 移除最后一个
if (positions.length == 2) {
if (polygon) {
viewer.entities.remove(polygon);
polygon = null;
if (polyline) polyline.show = true;
}
floatLabel.show = false;
}
if (positions.length == 1) {
if (polyline) {
viewer.entities.remove(polyline);
polyline = null;
}
tooltip.innerHTML = '<p>单击开始测量</p>';
tooltip.style.left = evt.endPosition.x + 40 + "px";
tooltip.style.top = evt.endPosition.y + 30 + "px";
movePush = false;
positions = [];
}
if (positions.length > 2) {
var areaCenter = getAreaAndCenter(positions);
var area = areaCenter.area;
var center = areaCenter.center;
var text = formateArea(area);
floatLabel.label.text = `平面面积:${text}`;
if (center) floatLabel.position.setValue(center);
floatLabel.area = area;
floatLabel.show = true;
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
//左键双击完成绘制
handler.setInputAction(function (evt) {
if (!polygon) return;
tooltip.style.display = "none";
positions.pop();
viewer.entities.remove(controlPoints.pop()); // 移除最后一个
movePush = false;
viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
viewer.trackedEntity = undefined;
var areaCenter = getAreaAndCenter(positions)
var area = areaCenter.area;
var center = areaCenter.center;
var text = formateArea(area);
floatLabel.label.text = `平面面积:${text}`;
floatLabel.area = area;
if (center) floatLabel.position.setValue(center);
if (handler) {
handler.destroy();
handler = null;
}
}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK)
}
function createPoint (position) {
if (!position) return;
return this.viewer.entities.add({
position: position,
point: {
pixelSize: 6,
color: Cesium.Color.RED,
outlineWidth: 1,
outlineColor: Cesium.Color.WHITE,
disableDepthTestDistance: Number.POSITIVE_INFINITY
},
show: false
});
}
function createPolyline () {
var ent = viewer.entities.add({
polyline: {
positions: new Cesium.CallbackProperty(function () {
var linePositions = positions.concat([positions[0]]);
return linePositions
}, false),
material: Cesium.Color.RED,
width: 2
}
});
return ent;
}
function createPolygon () {
var polygon = viewer.entities.add({
polygon: new Cesium.PolygonGraphics({
hierarchy: new Cesium.CallbackProperty(function () {
return new Cesium.PolygonHierarchy(positions);
}, false),
material: Cesium.Color.RED.withAlpha(0.4),
heightReference: Cesium.HeightReference.NONE,
perPositionHeight: true
}),
});
return polygon;
}
function getAreaAndCenter (positions, height) {
if (!positions || positions.length < 1) return;
var cartographics = [];
var turfPoints = [];
for (var i = 0; i < positions.length; i++) {
var cartesian3 = positions[i];
var cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
cartographics.push([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)]);
turfPoints.push(turf.point([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)]));
}
if (!cartographics.length) return;
cartographics = cartographics.concat([cartographics[0]]);
var polygon = turf.polygon([cartographics]);
var area = turf.area(polygon);
//获取当前范围的中心点
var features = turf.featureCollection(turfPoints);
var turfCenter = turf.center(features);
var center = turfCenter.geometry.coordinates;
let centerNum = height ? Cesium.Cartesian3.fromDegrees(center[0], center[1], height) : Cesium.Cartesian3.fromDegrees(center[0], center[1]);
return {
area: area,
center: centerNum
};
}
function formateArea (val) {
if (val == undefined) return;
let dwStr = '';
if (Number(val) > 1000000) {
dwStr += (Number(val) / 1000000).toFixed(2) + "km²";
} else {
dwStr += Number(val).toFixed(2) + "m²";
}
return dwStr;
}
function createLabel (c, text, params) {
if (!c) return;
return viewer.entities.add({
position: c,
label: {
text: text || "",
font: '14px Helvetica',
showBackground: params ? params.showBackground : false,
backgroundColor: params ? params.backgroundColor : Cesium.Color.WHITE,
backgroundPadding: new Cesium.Cartesian2(10, 8),
fillColor: params ? params.fillColor : Cesium.Color.WHITE,
outlineColor: params ? params.outlineColor : Cesium.Color.BLACK,
outlineWidth: 2,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
pixelOffset: params ? params.pixelOffset : new Cesium.Cartesian2(0, -20)
}
});
}
function getCatesian3FromPX (px, viewer) {
var picks = viewer.scene.drillPick(px);
viewer.scene.render();
var cartesian;
var isOn3dtiles = 'no';
for (var i = 0; i < picks.length; i++) {
if ((picks[i] && picks[i].primitive) && picks[i].primitive instanceof Cesium.Cesium3DTileset) { //模型上拾取
isOn3dtiles = 'yes';
break;
}
}
if (isOn3dtiles == 'yes') {
cartesian = viewer.scene.pickPosition(px);
} else {
var ray = viewer.camera.getPickRay(px);
if (!ray) return null;
cartesian = viewer.scene.globe.pick(ray, viewer.scene);
}
return { cartesian: cartesian, isOn3dtiles: isOn3dtiles };
}
</script>
</body>
</html>
测距
<!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, maximum-scale=1, minimum-scale=1, user-scalable=no" />
<title>Cesium示例集--测量平面面积</title>
<script type="text/javascript" src="./cesium/Cesium.js"></script>
<script type="text/javascript" src="./libs/turf.min.js"></script>
<link rel="stylesheet" href="./cesium/Widgets/widgets.css">
<style type="text/css">
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
user-select: none;
}
.cesium-container {
/* margin-top: 200px; */
width: 100%;
height: 100%;
position: relative;
}
.opt-bar {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, .8);
padding: 5px 10px;
border-radius: 2px;
>a {
font-size: 14px;
color: #00e7ff;
cursor: pointer;
margin: 0 10px;
}
}
#toolTip {
/* background-color: #00e7ff!important; */
}
/* 添加CSS过渡动画 */
.measure-tooltip {
transition: opacity 0.3s, transform 0.3s;
pointer-events: none;
max-width: 300px;
background: rgba(40, 40, 40, 0.9) !important;
border-radius: 4px;
padding: 8px 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
</style>
</head>
<body>
<div id="cesiumContainer" class="cesium-container"></div>
<div class="opt-bar">
<a onclick="startEdit()">测量平面面积</a>
<a onclick="clearEdit()">清除</a>
</div>
<!-- <div id="toolTip" style="position: absolute;font-size: 12px;background: rgba(0,0,0,.8);color:#fff;padding: 3px 5px;"
style="display: none;"></div> -->
<script>
class CesiumPopupClass {
constructor(viewer, options) {
this.viewer = viewer
this.position = options.position;
this.options = this.extend({}, options);
var popupContainer = document.createElement("div");
popupContainer.classList.add('popup');
var popupInner = options.content;
popupContainer.innerHTML = popupInner;
popupContainer.style.display = 'none';
viewer.cesiumWidget.container.appendChild(popupContainer);
popupContainer.style.cssText = "display: none;position: absolute;left: -100;top: -100;z-index:9999;";
this.popupContainer = popupContainer;
// 初始化
this.init();
}
init() {
if (this.position) {
this.popupContainer.style.display = 'block'
this.renderListener = this.viewer.scene.postRender.addEventListener(this.render, this)
}
}
updateContent(newContent) {
if (this.popupContainer) {
this.popupContainer.innerHTML = newContent;
}
}
render() {
var ellipsoid = this.viewer.scene.globe.ellipsoid;
var geometry = Cesium.Cartesian3.fromDegrees(
this.position[0],
this.position[1],
this.position[2] ? this.position[2] : 0,
ellipsoid
);
if (!geometry) return
var position = Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.viewer.scene, geometry)
if (!position) {
return
}
if (this.popupContainer) {
this.popupContainer.style.left = position.x - this.popupContainer.offsetWidth / 2 + 'px'
this.popupContainer.style.top = position.y - this.popupContainer.offsetHeight - 10 + 'px'
}
}
remove() {
if (this.popupContainer) {
this.popupContainer.parentNode.removeChild(this.popupContainer)
this.popupContainer = null
}
if (this.renderListener) {
this.renderListener()
this.renderListener = null
}
if (this.viewer) {
this.viewer = null
}
}
extend(obj, obj2) {
for (var k in obj2) {
obj[k] = obj2[k];
}
return obj;
}
}
let viewer = new Cesium.Viewer("cesiumContainer", {
animation: false,//是否创建动画小器件,左下角仪表
fullscreenButton: false,//是否显示全屏按钮
// geocoder: false,//是否显示geocoder小器件,右上角查询按钮
// homeButton: false,//是否显示Home按钮
infoBox: false,//是否显示信息框
// sceneModePicker: false,//是否显示3D/2D选择器
// scene3DOnly: false,//如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源
selectionIndicator: false,//是否显示选取指示器组件
timeline: false,//是否显示时间轴
// navigationHelpButton: false,//是否显示右上角的帮助按钮
baselLayerPicker: false,// 将图层选择的控件关掉,才能添加其他影像数据
shadows: false,//是否显示背影
baseLayerPicker: false,//是否显示图层选择器
imageryProvider: new Cesium.UrlTemplateImageryProvider({
url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}.png'
})
});
if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {
//判断是否支持图像渲染像素化处理
viewer.resolutionScale = window.devicePixelRatio;
}
//开启抗锯齿
viewer.scene.fxaa = true;
viewer.scene.postProcessStages.fxaa.enabled = true;
//去除版权信息
viewer._cesiumWidget._creditContainer.style.display = "none";
//屏蔽Cesium的默认双击追踪选中entity行为
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
);
//默认开启地形
// viewer.terrainProvider = Cesium.createWorldTerrain();
var pos = {
"position": {
"x": -2463425.8997346475,
"y": 4873855.487729879,
"z": 3288016.4618711653
},
"heading": 0.1341636770247039,
"pitch": -0.817714806133921,
"roll": 0.00001433107210147
};
viewer.camera.flyTo({
destination: new Cesium.Cartesian3(
pos.position.x,
pos.position.y,
pos.position.z
),
orientation: {
heading: pos.heading,
pitch: pos.pitch,
roll: pos.roll,
},
});
class AreaDraw {
constructor(viewer, id = Date.now()) {
this.viewer = viewer;
this.polyLineHeight = 0.2
this.handler = null;
this.positions = [];
this.polyline = null;
this.polygon = null;
this.controlPoints = [];
this.floatLabelAreaShow = false;
this.floatLabel = null;// 面积
this.movePush = false;
this.tooltip = null;
this.id = id;
this.popDiv = null
this.rect = this.viewer.canvas.getBoundingClientRect();
this.pointStyle = {
pixelSize: 6,
color: Cesium.Color.fromCssColorString("rgba(255,0,0,1)"),
outlineWidth: 1,
outlineColor: Cesium.Color.fromCssColorString("rgba(255,255,255,1)"),
}
this.polylineStyle = {
width: 4,
material: Cesium.Color.fromCssColorString("rgba(255,255,0,1)"),
}
this.polygonStyle = {
material: Cesium.Color.fromCssColorString("rgba(0,255,255,0.4)"),
}
}
startEdit(callback) {
// 创建一个 div 元素
let toolTip = document.createElement("div");
this.tooltip = toolTip
// 设置 div 的 ID
toolTip.id = "toolTip";
// 设置 div 的样式
toolTip.style.position = "absolute";
toolTip.style.fontSize = "14px";
toolTip.style.background = "rgba(255,255,255,.8)";
toolTip.style.color = "#000000";
toolTip.style.padding = "3px 5px";
toolTip.style.display = "none"; // 初始隐藏
// 将该 div 插入到页面中(例如插入到 body 中)
document.body.appendChild(toolTip);
toolTip.style.maxWidth = "200px";
this.tooltip.style.display = "block";
this.tooltip.style.zIndex = "9999";
this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
//左键单击,开始绘制
this.handler.setInputAction((evt) => {
// tooltip.style.display = "none";
var cartesian = this.getCatesian3FromPX(evt.position, this.viewer).cartesian;
if (!cartesian) return;
if (this.movePush) {
this.positions.pop();
this.movePush = false;
}
var point = this.createPoint(cartesian.clone());
point.wz = this.positions.length; // 和坐标点关联
this.controlPoints.push(point);
this.positions.push(cartesian);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//鼠标移动
this.handler.setInputAction((evt) => {
var rect = this.rect;
this.tooltip.style.left = rect.left + evt.endPosition.x + 40 + "px";
this.tooltip.style.top = rect.top + evt.endPosition.y + 30 + "px";
if (this.positions.length < 1) {
this.tooltip.innerHTML = '<div>单击开始绘制</div>';
return;
}
this.tooltip.innerHTML = `<div style='color:#2525F5;font-weight: 700;'>正在绘制中:</div>
<div>单击确定点位,双击结束当前绘制,右键取消上一步</div>`;
var cartesian = this.getCatesian3FromPX(evt.endPosition, this.viewer).cartesian;
if (!cartesian) return;
if (this.positions.length >= 1) {
if (!this.movePush) {
this.positions.push(cartesian);
this.movePush = true;
} else {
this.positions[this.positions.length - 1] = cartesian;
}
if (this.positions.length == 2) {
if (!Cesium.defined(this.polyline)) {
this.polyline = this.createPolyline();
}
}
if (this.positions.length == 3) {
if (!Cesium.defined(this.polygon)) {
this.polygon = this.createPolygon();
this.polygon.isFilter = true;
this.polygon.objId = Number((new Date()).getTime() + "" + Number(Math.random() * 1000).toFixed(0));
}
if (this.floatLabelAreaShow && !this.floatLabel) {
this.floatLabel = this.createLabel(cartesian, "", {
style: Cesium.LabelStyle.FILL,
showBackground: true,
backgroundColor: Cesium.Color.fromCssColorString('#303336'),
pixelOffset: new Cesium.Cartesian2(0, -50)
});
this.floatLabel.label.heightReference = 1;
}
}
if (this.floatLabelAreaShow && this.polygon) {
var areaCenter = this.getAreaAndCenter(this.positions)
var area = areaCenter.area;
var center = areaCenter.center;
var text = this.formateArea(area);
this.floatLabel.label.text = `平面面积:${text}`;
this.floatLabel.area = area;
if (center) this.floatLabel.position.setValue(center);
this.floatLabel.show = true;
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
//右键取消上一步
this.handler.setInputAction((evt) => {
if (!this.polyline && !this.polygon) return;
if (this.positions.length <= 2) return; // 默认第一个不给删除
this.positions.splice(this.positions.length - 2, 1);
this.viewer.entities.remove(this.controlPoints.pop()); // 移除最后一个
if (this.positions.length == 2) {
if (this.polygon) {
this.viewer.entities.remove(this.polygon);
this.polygon = null;
if (this.polyline) this.polyline.show = true;
}
if (this.floatLabelAreaShow) {
this.floatLabel.show = false;
}
}
if (this.positions.length == 1) {
if (this.polyline) {
this.viewer.entities.remove(this.polyline);
this.polyline = null;
}
var rect = this.rect;
this.tooltip.innerHTML = '<div>单击开始测量</div>';
this.tooltip.style.left = rect.left + evt.endPosition.x + 40 + "px";
this.tooltip.style.top = rect.top + evt.endPosition.y + 30 + "px";
this.movePush = false;
this.positions = [];
}
if (this.floatLabelAreaShow && this.positions.length > 2) {
var areaCenter = this.getAreaAndCenter(this.positions);
var area = areaCenter.area;
var center = areaCenter.center;
var text = this.formateArea(area);
this.floatLabel.label.text = `平面面积:${text}`;
if (center) this.floatLabel.position.setValue(center);
this.floatLabel.area = area;
this.floatLabel.show = true;
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
//左键双击完成绘制
this.handler.setInputAction((evt) => {
// if (!this.polygon) return;
if (this.tooltip) {
this.tooltip.parentNode.removeChild(this.tooltip);
// document.body.removeChild(this.tooltip);
this.tooltip = null;
}
this.positions.pop();
this.viewer.entities.remove(this.controlPoints.pop()); // 移除最后一个
this.movePush = false;
// this.viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
// this.viewer.trackedEntity = undefined;
if (this.floatLabelAreaShow) {
var areaCenter = this.getAreaAndCenter(this.positions)
var area = areaCenter.area;
var center = areaCenter.center;
var text = this.formateArea(area);
this.floatLabel.label.text = `平面面积:${text}`;
this.floatLabel.area = area;
if (center) this.floatLabel.position.setValue(center);
}
if (this.polyline) {
this.polyline.show = false;
}
if (this.polygon) {
this.addpop()
}
if (this.handler) {
this.handler.destroy();
this.handler = null;
typeof callback === 'function' && callback(this.positions)
}
}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK)
}
addpop() {
let cartographic = Cesium.Cartographic.fromCartesian(this.positions[this.positions.length - 1]);
let longitude = Cesium.Math.toDegrees(cartographic.longitude); // 经度 (从 -180 到 180)
let latitude = Cesium.Math.toDegrees(cartographic.latitude); // 纬度 (从 -90 到 90)
let popId = "id" + Number((new Date()).getTime() + "" + Number(Math.random() * 1000).toFixed(0));
this.popDiv = new CesiumPopupClass(this.viewer, {
position: [longitude, latitude],
content: `<div class="popup-titleCss" id="${popId}" style="
position: absolute;
top: 10px;
right: 10px;
background-color: #FFFFFF;
color: #ff0000;
font-size: 15px;
font-weight: bold;
width: 20px;
height: 20px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.2);
cursor: pointer;
border: 2px solid red;
transition: all 0.3s ease;">
X
</div>`
})
document.querySelector(`#${popId}`).addEventListener("click", () => {
this.popDiv.remove()
this.clearEdit()
})
}
clearEdit() {
if (!this.viewer) {
return
}
if (this.popDiv) {
this.popDiv.remove();
this.popDiv = null
}
if (this.tooltip) {
document.body.removeChild(this.tooltip);
this.tooltip = null;
}
this.positions = [];
if (this.polyline) {
this.viewer.entities.remove(this.polyline);
this.polyline = null;
}
if (this.polygon) {
this.viewer.entities.remove(this.polygon);
this.polygon = null;
}
for (var ind = 0; ind < this.controlPoints.length; ind++) {
this.viewer.entities.remove(this.controlPoints[ind]);
this.controlPoints[ind] = null;
}
this.controlPoints = [];
if (this.floatLabelAreaShow) {
if (this.floatLabel) {
this.viewer.entities.remove(this.floatLabel);
this.floatLabel = null;
}
this.floatLabel = null;
}
if (this.handler) {
this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
this.handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
this.handler.destroy();
this.handler = null;
}
this.movePush = false;
// this.viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
// this.viewer.trackedEntity = undefined;
this.rect = null
this.viewer = null
for (let key in this.pointStyle) {
if (this.pointStyle.hasOwnProperty(key)) {
delete this.pointStyle[key];
}
}
for (let key in this.polylineStyle) {
if (this.polylineStyle.hasOwnProperty(key)) {
delete this.polylineStyle[key];
}
}
for (let key in this.polygonStyle) {
if (this.polygonStyle.hasOwnProperty(key)) {
delete this.polygonStyle[key];
}
}
this.id = null
this.pointStyle = null
this.polylineStyle = null
this.polygonStyle = null
console.log("clearEdit---------------");
}
createPoint(position) {
if (!position) return;
return this.viewer.entities.add({
position: position,
point: {
pixelSize: this.pointStyle.pixelSize,
color: this.pointStyle.color,
outlineWidth: this.pointStyle.outlineWidth,
outlineColor: this.pointStyle.outlineColor,
disableDepthTestDistance: Number.POSITIVE_INFINITY
},
show: false
});
}
createPolyline() {
var ent = this.viewer.entities.add({
id: 'polylineDraw_' + this.id,
polyline: {
positions: new Cesium.CallbackProperty(() => {
var linePositions = this.positions.concat([this.positions[0]]);
return linePositions
}, false),
material: this.polylineStyle.material,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
width: this.polylineStyle.width,
}
});
return ent;
}
createPolygon() {
var polygon = this.viewer.entities.add({
id: 'polygonDraw_' + this.id,
polygon: new Cesium.PolygonGraphics({
hierarchy: new Cesium.CallbackProperty(() => {
return new Cesium.PolygonHierarchy(this.positions);
}, false),
material: this.polygonStyle.material,
heightReference: Cesium.HeightReference.NONE,
perPositionHeight: true
}),
});
return polygon;
}
getAreaAndCenter(positions, height) {
if (!positions || positions.length < 1) return;
var cartographics = [];
var turfPoints = [];
for (var i = 0; i < positions.length; i++) {
var cartesian3 = positions[i];
var cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
cartographics.push([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)]);
turfPoints.push(turf.point([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)]));
}
if (!cartographics.length) return;
cartographics = cartographics.concat([cartographics[0]]);
var polygon = turf.polygon([cartographics]);
var area = turf.area(polygon);
//获取当前范围的中心点
var features = turf.featureCollection(turfPoints);
var turfCenter = turf.center(features);
var center = turfCenter.geometry.coordinates;
let centerNum = height ? Cesium.Cartesian3.fromDegrees(center[0], center[1], height) : Cesium.Cartesian3.fromDegrees(center[0], center[1]);
return {
area: area,
center: centerNum
};
}
formateArea(val) {
if (val == undefined) return;
let dwStr = '';
if (Number(val) > 1000000) {
dwStr += (Number(val) / 1000000).toFixed(2) + "km²";
} else {
dwStr += Number(val).toFixed(2) + "m²";
}
return dwStr;
}
createLabel(c, text, params) {
if (!c) return;
return this.viewer.entities.add({
position: c,
label: {
text: text || "",
font: '14px Helvetica',
showBackground: params ? params.showBackground : false,
backgroundColor: params ? params.backgroundColor : Cesium.Color.WHITE,
backgroundPadding: new Cesium.Cartesian2(10, 8),
fillColor: params ? params.fillColor : Cesium.Color.WHITE,
outlineColor: params ? params.outlineColor : Cesium.Color.BLACK,
outlineWidth: 2,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
pixelOffset: params ? params.pixelOffset : new Cesium.Cartesian2(0, -20)
}
});
}
getCatesian3FromPX(px, viewer) {
// this.viewer.scene.render();
var cartesian;
var isOn3dtiles = 'no';
var ray = this.viewer.camera.getPickRay(px);
if (!ray) return null;
cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
if (this.polyLineHeight) {
// 计算当前坐标点的法线方向
let ellipsoid = this.viewer.scene.globe.ellipsoid;
let normal = ellipsoid.geodeticSurfaceNormal(cartesian);
// 增加 2 米的高度:沿法线方向偏移
let offset = this.polyLineHeight; // 增加的高度(单位:米)
let newCartesain = Cesium.Cartesian3.add(cartesian, Cesium.Cartesian3.multiplyByScalar(normal, offset, new Cesium.Cartesian3()), new Cesium.Cartesian3());
return { cartesian: newCartesain, isOn3dtiles: isOn3dtiles };
} else {
return { cartesian: cartesian, isOn3dtiles: isOn3dtiles };
}
}
}
class AreaManager {
constructor(viewer, fn) {
this.viewer = viewer;
this.idItem = null;
this.areaList = [];
this.handler = null
this.fn = typeof fn == 'function' ? fn : null
this.startEditFlag = false
// this.drawArea = this.startEdit()
}
startEditManage(callback) {
if (this.startEditFlag) return
this.startEditFlag = true
this.areaList.forEach(e => {
if (e.area.viewer && e.area.polyline) {
e.area.polyline.show = false
}
})
let id = Date.now()
this.idItem = id
this.areaList.push({
id: id,
area: new AreaDraw(this.viewer, id)
})
this.cancelHander()
console.log(this.areaList.length, 'this.areaList.length');
this.areaList[this.areaList.length - 1].area.startEdit((e) => {
console.log("完成");
this.startEditFlag = false
console.log(this.areaList, 'this.areaList');
this.AddLeftClick()
let resPosition = e.map(e => this.cartesianToLatLon(e))
typeof callback === 'function' && callback(resPosition)
});
this.drawArea = this.areaList[this.areaList.length - 1].area
return this.areaList[this.areaList.length - 1].area
}
clearEditAll() {
// 单个清除
// let areaItem = areaList.find(e=>e.id == idItem)
// console.log(areaItem.area,'area');
// areaItem.area.clearEdit();
// areaItem.area = null
// areaList.splice(areaList.findIndex(e=>e.id == idItem),1)
this.areaList.forEach(e => {
e.area.clearEdit();
e.area = null;
e = null
})
this.fn = null
this.areaList = null
this.cancelHander()
this.viewer = null
this.startEditFlag = false
}
AddLeftClick() {
this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.handler.setInputAction((evt) => {
// 获取点击位置的实体
var pickedObject = this.viewer.scene.pick(evt.position);
if (Cesium.defined(pickedObject) && Cesium.defined(pickedObject.id)) {
let list = pickedObject.id.id.split('_');
if (list[0] == 'polygonDraw') {
this.areaList.forEach(e => {
if (e.area.viewer) {
if (String(e.id) === list[1]) {
e.area.polyline.show = true
console.log(e.area.positions, 'e.area.positions');
let p = e.area.positions.map(e1 => {
let result = this.cartesianToLatLon(e1);
return result
})
if (this.fn) {
this.fn(p)
}
console.log(p, 'e.area.positions');
} else {
e.area.polyline.show = false
}
}
})
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
cancelHander() {
if (this.handler) {
this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
this.handler.destroy();
this.handler = null;
}
}
/**
* 将笛卡尔坐标转换为经纬度坐标
* @param {Cesium.Cartesian3} cartesian - 笛卡尔坐标
* @param {Cesium.Ellipsoid} [ellipsoid=Cesium.Ellipsoid.WGS84] - 参考椭球体,默认为 WGS84
* @returns {Object} 包含经度和纬度的对象,单位为度
*/
cartesianToLatLon(cartesian, ellipsoid = Cesium.Ellipsoid.WGS84) {
if (!Cesium.defined(cartesian)) {
throw new Error('cartesian 参数未定义');
}
var cartographic = ellipsoid.cartesianToCartographic(cartesian);
if (!Cesium.defined(cartographic)) {
throw new Error('无法将笛卡尔坐标转换为地理坐标');
}
var longitude = Cesium.Math.toDegrees(cartographic.longitude);
var latitude = Cesium.Math.toDegrees(cartographic.latitude);
var height = cartographic.height;
return {
longitude: longitude,
latitude: latitude,
height: height
};
}
}
let m
function startEdit() {
if (!m) {
m = new AreaManager(viewer, (e) => {
console.log(e, 'eee点击事件回调');
});
}
m.startEditManage((e) => {
console.log(e, 'drawArea完成事件回调')
});
// m.drawArea.polylineStyle.material = Cesium.Color.RED.withAlpha(0.5);
// m.drawArea.floatLabelAreaShow = true
}
function clearEdit() {
console.log(m, 'm');
if (m) {
m.clearEditAll()
m = null
}
}
</script>
</body>
</html>