测距实现总结
开发过程中,有一个需求是测距实时让文本居中显示。参考cesium的API总结如下代码实现测距显示距离。
文本API
动态绘制API
在编写的时候,需要理解的是CallbackProperty这个回调函数,建议去看看api文档或技术网站文章对它有个大概认识。在集成两个API代码遇到最大的问题就是销毁模型问题。大概率就是我这边个人原因,经常报错,经过多次调试,发现是自己通过常用的移除并不能移除模型所导致的。当一个模型被销毁时,该回调函数也跟着销毁。如果销毁模型失败,建议使用removeById去销毁。
/*
@activeShape 动态线
@floatingPoint 点模型
@startPog 开始点坐标 用于计算距离
@labels 动态文本模型
*/
var activeShapePoints = [];
var activeShape;
var floatingPoint;
let startPog;
var scratch = new Cesium.Cartographic();
var geodesic = new Cesium.EllipsoidGeodesic();
let isConstant = false;
var labels;
//创建点
function createP(worldPosition) {
var point = viewer.entities.add({
position: worldPosition,
point: {
color: Cesium.Color.WHITE,
pixelSize: 5,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
});
return point;
}
//划线
function drawShape(positionData) {
var shape;
shape = viewer.entities.add({
polyline: {
positions: positionData,
clampToGround: true,
width: 3,
},
});
return shape;
}
// 动态获取距离
function getLength(time, result) {
// Get the end position from the polyLine's callback.
let endPog = Cesium.Cartographic.fromCartesian(activeShapePoints[1]);
geodesic.setEndPoints(startPog, endPog);
var lengthInMeters = Math.round(geodesic.surfaceDistance);
console.log('持续触发中')
return (lengthInMeters / 1000).toFixed(1) + " km";
}
// 动态取中间值
function getMidpoint(time, result) {
// Get the end position from the polyLine's callback.
let endPog = Cesium.Cartographic.fromCartesian(activeShapePoints[1]);
geodesic.setEndPoints(startPog, endPog);
var midpointCartographic = geodesic.interpolateUsingFraction(
0.5,
scratch
);
return Cesium.Cartesian3.fromRadians(
midpointCartographic.longitude,
midpointCartographic.latitude
);
}
// 添加文本显示文字
function addlabel() {
var text;
text = viewer.entities.add({
// id: '距离文本',
position: new Cesium.CallbackProperty(getMidpoint, isConstant),
label: {
// This callback updates the length to print each frame.
text: new Cesium.CallbackProperty(getLength, isConstant),
font: "20px sans-serif",
pixelOffset: new Cesium.Cartesian2(0.0, 20),
},
});
return text;
}
// 固定文本
function bindlabel() {
var text;
text = viewer.entities.add({
// id: '距离文本2',
position: getMidpoint(),
label: {
// This callback updates the length to print each frame.
text: getLength(),
font: "20px sans-serif",
pixelOffset: new Cesium.Cartesian2(0.0, 20),
},
});
return text;
}
// 鼠标左键
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
//pickPosition 不能没有很好的随鼠标的移动
// var earthPosition = viewer.scene.pickPosition(movement.position);
var earthPosition = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
if (Cesium.defined(earthPosition)) {
if (activeShapePoints.length === 0) { // 数组为0时,创建起点
floatingPoint = createP(earthPosition);
activeShapePoints.push(earthPosition);
// 设置起始点
startPog = Cesium.Cartographic.fromCartesian(activeShapePoints[0]);
// 构建回调函数点
var dynamicPositions = new Cesium.CallbackProperty(function () {
return activeShapePoints;
}, false);
// 创建动态文本
labels = addlabel();
// 创建动态线条
activeShape = drawShape(dynamicPositions);
}
// 点击固定文本
if (activeShapePoints.length >= 2) {
activeShapePoints.push(earthPosition);
terminateShape();
}
activeShapePoints.push(earthPosition);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
// 鼠标移动监听
handler.setInputAction(function (event) {
if (Cesium.defined(floatingPoint)) {
// var newPosition = viewer.scene.pickPosition(event.endPosition);
var newPosition = viewer.camera.pickEllipsoid(event.endPosition, viewer.scene.globe.ellipsoid);
if (Cesium.defined(newPosition)) {
floatingPoint.position.setValue(newPosition);
activeShapePoints.pop();
activeShapePoints.push(newPosition);
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// Redraw the shape so it's not dynamic and remove the dynamic shape.
function terminateShape() {
viewer.entities.remove(floatingPoint);
viewer.entities.remove(activeShape);
viewer.entities.remove(labels);
// viewer.entities.removeById('距离文本');
labels = undefined;
floatingPoint = undefined;
activeShape = undefined;
activeShape = drawShape(activeShapePoints);
labels = bindlabel();
// _this.linesdata.push(activeShape)
// _this.linesdata.push(labels)
activeShapePoints = [];
handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
handler.setInputAction(function (event) {
viewer.entities.remove(activeShape);
// viewer.entities.removeById('距离文本2');
viewer.entities.remove(labels);
handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
handler.destroy();
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
遇到的bug图:
此笔记仅仅为了记录自己在项目中所学到的知识,如果有问题,可以提出,我们可以共同探讨。