示例1:
MeasureManager.js
import * as Cesium from 'cesium'
export default class MeasureManager {
constructor(viewer) {
this.viewer = viewer
}
distance() {
const viewer = this.viewer
// 存储点
const positions = []
// 存储标签
let label = null
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
// 注册鼠标左击事件
handler.setInputAction(evt => {
var cartesian = viewer.scene.pickPosition(evt.position);
if (!cartesian) return
positions.push(cartesian.clone())
if (positions.length >= 2) {
handler.destroy()
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
handler.setInputAction(evt => {
var cartesian = viewer.scene.pickPosition(evt.endPosition);
if (!cartesian) return
if (positions.length >= 2) {
positions.pop()
positions.push(cartesian.clone())
} else if (positions.length === 1) {
positions.push(cartesian.clone())
this.addLine(positions)
label = this.addLabel(positions[0], this.getLength(positions))
}
if (label) {
label.label.text.setValue(this.getLength(positions))
label.position.setValue(positions[1])
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
handler.setInputAction(evt => {
handler.destroy()
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
}
addLine(positions) {
const viewer = this.viewer
viewer.entities.add(
new Cesium.Entity({
polyline: {
positions: new Cesium.CallbackProperty(() => positions, false),
width: 2,
material: Cesium.Color.YELLOW,
clampToGround: true,
}
})
)
}
addLabel(point, text) {
const viewer = this.viewer
return viewer.entities.add(
new Cesium.Entity({
position: point,
label: {
text: text,
font: '14px sans-serif',
style: Cesium.LabelStyle.FILL_AND_OUTLINE, //FILL FILL_AND_OUTLINE OUTLINE
fillColor: Cesium.Color.YELLOW,
showBackground: true, //指定标签后面背景的可见性
backgroundColor: new Cesium.Color(0.165, 0.165, 0.165, 0.8), // 背景颜色
backgroundPadding: new Cesium.Cartesian2(6, 6), //指定以像素为单位的水平和垂直背景填充padding
pixelOffset: new Cesium.Cartesian2(0, -25),
disableDepthTestDistance: Number.POSITIVE_INFINITY
}
})
)
}
getLength(points) {
// 计算距离
var length = Cesium.Cartesian3.distance(points[0], points[1]);
if (length > 1000) {
length = `${(length / 1000).toFixed(2)}km`
} else {
length = `${length.toFixed(2)}m`
}
return length
}
}
测试:
<template>
<div class="main">
<div id="cesiumContainer"></div>
</div>
</template>
<script setup>
import * as Cesium from 'cesium';
import MeasureManager from './MeasureManager.js';
onMounted(() => {
const cesiumViewer = new Cesium.Viewer("cesiumContainer", {
terrainProvider: Cesium.createWorldTerrain(),
infoBox: false, //信息面板
timeline: false, //底部的时间轴
fullscreenButton: false, //右下角的全屏按钮
});
cesiumViewer._cesiumWidget._creditContainer.style.display = "none"; //隐藏logo版权
const measureManager = new MeasureManager(cesiumViewer)
measureManager.distance()
})
</script>
<style lang="scss" scoped>
.main {
position: relative;
height: 100vh;
width: 100vw;
#cesiumContainer {
position: absolute;
height: 100vh;
width: 100vw;
}
}
</style>
如果希望label显示在线的中间,修改如下:
// 计算中点
let centerPoint = Cesium.Cartesian3.midpoint(positions[0], positions[1], new Cesium.Cartesian3());
示例2:
<template>
<div class="main">
<div id="cesiumContainer"></div>
</div>
</template>
<script setup>
import * as Cesium from 'cesium';
//测量空间直线距离
/******************************************* */
function measureLineSpace(viewer, handler) {
// 取消双击事件-追踪该位置
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
handler = new Cesium.ScreenSpaceEventHandler(viewer.scene._imageryLayerCollection);
var positions = [];
var poly = null;
// var tooltip = document.getElementById("toolTip");
var distance = 0;
var cartesian = null;
var floatingPoint;
// tooltip.style.display = "block";
handler.setInputAction(function (movement) {
// tooltip.style.left = movement.endPosition.x + 3 + "px";
// tooltip.style.top = movement.endPosition.y - 25 + "px";
// tooltip.innerHTML = '<p>单击开始,右击结束</p>';
// cartesian = viewer.scene.pickPosition(movement.endPosition);
let ray = viewer.camera.getPickRay(movement.endPosition);
cartesian = viewer.scene.globe.pick(ray, viewer.scene);
//cartesian = viewer.scene.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid);
if (positions.length >= 2) {
if (!Cesium.defined(poly)) {
poly = new PolyLinePrimitive(positions);
} else {
positions.pop();
// cartesian.y += (1 + Math.random());
positions.push(cartesian);
}
distance = getSpaceDistance(positions);
// console.log("distance: " + distance);
// tooltip.innerHTML='<p>'+distance+'米</p>';
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.setInputAction(function (movement) {
// tooltip.style.display = "none";
// cartesian = viewer.scene.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
// cartesian = viewer.scene.pickPosition(movement.position);
let ray = viewer.camera.getPickRay(movement.position);
cartesian = viewer.scene.globe.pick(ray, viewer.scene);
if (positions.length == 0) {
positions.push(cartesian.clone());
}
positions.push(cartesian);
//在三维场景中添加Label
// var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
var textDisance = distance + "米";
// console.log(textDisance + ",lng:" + cartographic.longitude/Math.PI*180.0);
floatingPoint = viewer.entities.add({
name: '空间直线距离',
// position: Cesium.Cartesian3.fromDegrees(cartographic.longitude / Math.PI * 180, cartographic.latitude / Math.PI * 180,cartographic.height),
position: positions[positions.length - 1],
point: {
pixelSize: 5,
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
},
label: {
text: textDisance,
font: '18px sans-serif',
fillColor: Cesium.Color.GOLD,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(20, -20),
}
});
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(function (movement) {
handler.destroy(); //关闭事件句柄
positions.pop(); //最后一个点无效
// viewer.entities.remove(floatingPoint);
// tooltip.style.display = "none";
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
var PolyLinePrimitive = (function () {
function _(positions) {
this.options = {
name: '直线',
polyline: {
show: true,
positions: [],
material: Cesium.Color.CHARTREUSE,
width: 10,
clampToGround: true
}
};
this.positions = positions;
this._init();
}
_.prototype._init = function () {
var _self = this;
var _update = function () {
return _self.positions;
};
//实时更新polyline.positions
this.options.polyline.positions = new Cesium.CallbackProperty(_update, false);
viewer.entities.add(this.options);
};
return _;
})();
//空间两点距离计算函数
function getSpaceDistance(positions) {
var distance = 0;
for (var i = 0; i < positions.length - 1; i++) {
var point1cartographic = Cesium.Cartographic.fromCartesian(positions[i]);
var point2cartographic = Cesium.Cartographic.fromCartesian(positions[i + 1]);
/**根据经纬度计算出距离**/
var geodesic = new Cesium.EllipsoidGeodesic();
geodesic.setEndPoints(point1cartographic, point2cartographic);
var s = geodesic.surfaceDistance;
//console.log(Math.sqrt(Math.pow(distance, 2) + Math.pow(endheight, 2)));
//返回两点之间的距离
s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2));
distance = distance + s;
}
return distance.toFixed(2);
}
}
onMounted(() => {
const cesiumViewer = new Cesium.Viewer("cesiumContainer", {
terrainProvider: Cesium.createWorldTerrain(),
infoBox: false, //信息面板
timeline: false, //底部的时间轴
fullscreenButton: false, //右下角的全屏按钮
});
cesiumViewer._cesiumWidget._creditContainer.style.display = "none"; //隐藏logo版权
measureLineSpace(cesiumViewer)
})
</script>
<style lang="scss" scoped>
.main {
position: relative;
height: 100vh;
width: 100vw;
#cesiumContainer {
position: absolute;
height: 100vh;
width: 100vw;
}
}
</style>