直接贴代码吧,cesium版本1.99,turf版本7.0.0
<template>
<div id="appp" style="width: 100%;height: 100%;position: relative;">
<div id="cesiumContainer"></div>
<div class="btnContainer">
<button @click="draw('Polyline')">标点测距</button>
<button @click="draw('Polygon')">标点测面</button>
<button @click="clearAllDrawn()">清空数据</button>
<div class="tip">
<p>点击按钮后,在场景内单击左键标点,单击右键结束测量。</p>
<p>点击“标点测距”按钮后在场景内单击鼠标左键加点,在两点间显示距离,单击右键结束测量。</p>
<p>点击“标点测面”按钮后在场景内单击鼠标左键加点,单击右键在勾出的范围中显示面积。</p>
<p>点击“清空数据”按钮删除所有数据。</p>
</div>
</div>
</div>
</template>
<script setup name="cesiumMap">
import { onMounted, ref, onBeforeUnmount, reactive } from 'vue';
import * as Cesium from 'cesium';
import 'cesium/Build/Cesium/Widgets/widgets.css';
import * as turf from '@turf/turf';
const tiandituTk = '天地图的Key'
let TDT_YX = new Cesium.WebMapTileServiceImageryProvider({
url: `http://{s}.tianditu.gov.cn/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${tiandituTk}`,
layer: 'img',
style: 'default',
format: 'tiles',
tileMatrixSetID: 'w',
subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
credit: new Cesium.Credit('天地图影像'),
maximumLevel: 18
});
let TDT_SL = new Cesium.WebMapTileServiceImageryProvider({
url: `http://{s}.tianditu.gov.cn/vec_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=vec&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${tiandituTk}`,
layer: 'vec',
style: 'default',
format: 'tiles',
tileMatrixSetID: 'w',
subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
credit: new Cesium.Credit('天地图矢量'),
maximumLevel: 18
});
let wmtsImageryProvider = new Cesium.WebMapTileServiceImageryProvider({
url: 'http://222.71.165.235:8088/geoserver/gwc/service/wmts',
layer: 'land-survey:gtxz_wgs84_new',
style: '',
format: 'image/png',
tileMatrixSetID: 'EPSG:4326',
tileMatrixLabels: ['EPSG:4326:0', 'EPSG:4326:1', 'EPSG:4326:2', 'EPSG:4326:3', 'EPSG:4326:4', 'EPSG:4326:5', 'EPSG:4326:6', 'EPSG:4326:7', 'EPSG:4326:8', 'EPSG:4326:9', 'EPSG:4326:10', 'EPSG:4326:11', 'EPSG:4326:12', 'EPSG:4326:13', 'EPSG:4326:14', 'EPSG:4326:15', 'EPSG:4326:16', 'EPSG:4326:17', 'EPSG:4326:18', 'EPSG:4326:19', 'EPSG:4326:20', 'EPSG:4326:21'],
maximumLevel: 21,
tilingScheme: new Cesium.GeographicTilingScheme(),
});
let TDT_ZJ = new Cesium.WebMapTileServiceImageryProvider({
url: `http://t0.tianditu.gov.cn/cia_w/wmts?tk=${tiandituTk}`,
layer: 'cia',
style: 'default',
tileMatrixSetID: 'w',
format: 'tiles',
credit: new Cesium.Credit('天地注记'),
maximumLevel: 18
});
const viewer = ref(null);
const pointNum = ref(0)
const floatingPoint = ref(undefined)
const activeShape = ref(undefined)
let tempEntities = reactive([]);
function getLength(start, end) {
let startCartographic = Cesium.Cartographic.fromCartesian(start)
let endCartographic = Cesium.Cartographic.fromCartesian(end)
let geodesic = new Cesium.EllipsoidGeodesic()
geodesic.setEndPoints(startCartographic, endCartographic)
return (geodesic.surfaceDistance).toFixed(2)
}
function getMidpoint(start, end) {
let startPoint = Cesium.Cartographic.fromCartesian(start)
let endPoint = Cesium.Cartographic.fromCartesian(end)
let geodesic = new Cesium.EllipsoidGeodesic()
geodesic.setEndPoints(startPoint, endPoint)
let geoPoint = geodesic.interpolateUsingFraction(0.5)
return Cesium.Ellipsoid.WGS84.cartographicToCartesian(geoPoint)
}
function addLabel(midPoint, labelLength) {
return viewer.value.entities.add({
name: '中点',
position: midPoint,
label: {
text: labelLength + 'm',
font: '12px sans-serif',
fillColor: Cesium.Color.WHITE,
outlineWidth: 2,
backgroundColor: Cesium.Color.BLACK,
showBackground: true,
style: Cesium.LabelStyle.FILL,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
disableDepthTestDistance: Number.POSITIVE_INFINITY
}
})
}
function getArea(positions) {
console.log(positions)
let wgs84Coordinates = positions.map(cartesian => {
let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
return [
Cesium.Math.toDegrees(cartographic.longitude),
Cesium.Math.toDegrees(cartographic.latitude)
];
});
let geoJsonPolygon = {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [wgs84Coordinates.concat([wgs84Coordinates[0]])]
}
}
]
};
console.log(geoJsonPolygon);
let area = turf.area(geoJsonPolygon.features[0]);
console.log(`Area: ${area} square meters`);
const center = turf.center(geoJsonPolygon);
const [longitude, latitude] = center.geometry.coordinates;
const cartesian3 = Cesium.Cartesian3.fromDegrees(longitude, latitude);
console.log(cartesian3);
return [area.toFixed(2),cartesian3]
}
function addArea(area, position) {
return viewer.value.entities.add({
name: '多边形面积',
position: position,
label: {
text: area + 'm²',
font: '12px sans-serif',
fillColor: Cesium.Color.WHITE,
outlineWidth: 2,
backgroundColor: Cesium.Color.BLACK,
showBackground: true,
style: Cesium.LabelStyle.FILL,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
disableDepthTestDistance: Number.POSITIVE_INFINITY
}
})
}
function drawPointLabel(position, pointNum) {
return viewer.value.entities.add({
name: '点几何对象',
position: position,
point: {
color: Cesium.Color.WHEAT,
pixelSize: 5,
outlineWidth: 3,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
}
})
}
function drawPoint(position) {
return viewer.value.entities.add({
position: position,
point: {
color: Cesium.Color.WHEAT,
pixelSize: 5,
outlineWidth: 3,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
}
})
}
function drawPolyline(positions) {
if (positions.length < 1) return
return viewer.value.entities.add({
name: '线几何对象',
polyline: {
positions: positions,
width: 5.0,
material: new Cesium.PolylineGlowMaterialProperty({
color: Cesium.Color.WHEAT
}),
depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({
color: Cesium.Color.WHEAT
}),
clampToGround: true
}
})
}
function drawPolygon(positions) {
if (positions.length < 2) return
return viewer.value.entities.add({
name: '面几何对象',
polygon: {
hierarchy: positions,
material: new Cesium.ColorMaterialProperty(
Cesium.Color.WHEAT.withAlpha(0.4)
)
}
})
}
function clearAllDrawn() {
tempEntities = []
pointNum.value = 0
viewer.value.entities.removeAll()
}
function draw(type) {
switch (type) {
case 'Polyline':
drawPolylineHandler();
break;
case 'Polygon':
drawPolygonHandler();
break;
}
}
function drawPolylineHandler() {
let tempPoints = [];
let activeShapeLine;
let activeShapeLabel;
let drawing = false;
let handler = new Cesium.ScreenSpaceEventHandler(viewer.value.scene.canvas);
handler.setInputAction(function (click) {
let ray = viewer.value.camera.getPickRay(click.position);
let pickedPosition = viewer.value.scene.globe.pick(ray, viewer.value.scene);
if (Cesium.defined(pickedPosition)) {
if (!drawing) {
tempPoints = [pickedPosition];
drawing = true;
pointNum.value += 1;
let point = drawPointLabel(pickedPosition, JSON.stringify(pointNum.value));
tempEntities.push(point);
} else {
tempPoints.push(pickedPosition);
let point = drawPointLabel(pickedPosition, JSON.stringify(pointNum.value));
tempEntities.push(point);
let lastPoint = tempPoints[0];
activeShapeLine = drawPolyline([lastPoint, pickedPosition]);
tempEntities.push(activeShapeLine);
let pointLength = getLength(lastPoint, pickedPosition);
let midPosition = getMidpoint(lastPoint, pickedPosition);
activeShapeLabel = addLabel(midPosition, pointLength);
tempEntities.push(activeShapeLabel);
tempPoints = [pickedPosition];
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(function (movement) {
if (drawing && tempPoints.length > 0) {
let ray = viewer.value.camera.getPickRay(movement.endPosition);
let pickedPosition = viewer.value.scene.globe.pick(ray, viewer.value.scene);
if (Cesium.defined(pickedPosition)) {
if (activeShapeLine) {
viewer.value.entities.remove(activeShapeLine);
}
let lastPoint = tempPoints[0];
activeShapeLine = drawPolyline([lastPoint, pickedPosition]);
tempEntities.push(activeShapeLine);
if (activeShapeLabel) {
viewer.value.entities.remove(activeShapeLabel);
}
let pointLength = getLength(lastPoint, pickedPosition);
let midPosition = getMidpoint(lastPoint, pickedPosition);
activeShapeLabel = addLabel(midPosition, pointLength);
tempEntities.push(activeShapeLabel);
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.setInputAction(function (click) {
if (drawing) {
if (tempPoints.length > 1) {
if (activeShapeLine) {
viewer.value.entities.remove(activeShapeLine);
}
if (activeShapeLabel) {
viewer.value.entities.remove(activeShapeLabel);
}
tempPoints.pop();
if (tempPoints.length > 1) {
let lastPoint = tempPoints[tempPoints.length - 2];
let currentPoint = tempPoints[tempPoints.length - 1];
activeShapeLine = drawPolyline([lastPoint, currentPoint]);
tempEntities.push(activeShapeLine);
let pointLength = getLength(lastPoint, currentPoint);
let midPosition = getMidpoint(lastPoint, currentPoint);
activeShapeLabel = addLabel(midPosition, pointLength);
tempEntities.push(activeShapeLabel);
}
} else {
drawing = false;
tempPoints = [];
if (activeShapeLine) {
viewer.value.entities.remove(activeShapeLine);
}
if (activeShapeLabel) {
viewer.value.entities.remove(activeShapeLabel);
}
if (floatingPoint.value) {
viewer.value.entities.remove(floatingPoint.value);
}
handler.destroy();
handler = null;
floatingPoint.value = undefined;
activeShape.value = undefined;
activeShapeLine = undefined;
activeShapeLabel = undefined;
}
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
function drawPolygonHandler() {
let activeShapePoints = [];
let activeShapeLines = [];
let activeShape;
let floatingPoint = { value: undefined };
let drawing = false;
let handler = new Cesium.ScreenSpaceEventHandler(viewer.value.scene.canvas);
handler.setInputAction(function (movement) {
if (drawing && activeShapePoints.length > 0) {
let ray = viewer.value.camera.getPickRay(movement.endPosition);
let pickedPosition = viewer.value.scene.globe.pick(ray, viewer.value.scene);
if (Cesium.defined(pickedPosition)) {
if (activeShapeLines.length > activeShapePoints.length - 1) {
let lastLine = activeShapeLines.pop();
viewer.value.entities.remove(lastLine);
}
let lastPoint = activeShapePoints[activeShapePoints.length - 1];
let newLine = drawPolyline([lastPoint, pickedPosition]);
activeShapeLines.push(newLine);
tempEntities.push(newLine);
if (activeShape) {
viewer.value.entities.remove(activeShape);
}
activeShape = drawPolygon(new Cesium.CallbackProperty(() => new Cesium.PolygonHierarchy(activeShapePoints.concat([pickedPosition])), false));
tempEntities.push(activeShape);
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.setInputAction(function (click) {
let ray = viewer.value.camera.getPickRay(click.position);
let earthPosition = viewer.value.scene.globe.pick(ray, viewer.value.scene);
if (Cesium.defined(earthPosition)) {
if (!drawing) {
drawing = true;
activeShapePoints.push(earthPosition);
floatingPoint.value = drawPoint(earthPosition);
tempEntities.push(floatingPoint.value);
activeShape = drawPolygon(new Cesium.CallbackProperty(() => new Cesium.PolygonHierarchy(activeShapePoints), false));
tempEntities.push(activeShape);
} else {
activeShapePoints.push(earthPosition);
if (activeShapePoints.length > 1) {
let lastPoint = activeShapePoints[activeShapePoints.length - 2];
let newLine = drawPolyline([lastPoint, earthPosition]);
activeShapeLines.push(newLine);
tempEntities.push(newLine);
}
if (activeShape) {
viewer.value.entities.remove(activeShape);
}
activeShape = drawPolygon(new Cesium.CallbackProperty(() => new Cesium.PolygonHierarchy(activeShapePoints), false));
tempEntities.push(activeShape);
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(function (click) {
if (drawing) {
if (activeShapeLines.length > 0) {
let lastLine = activeShapeLines.pop();
viewer.value.entities.remove(lastLine);
}
if (activeShape) {
viewer.value.entities.remove(activeShape);
activeShape = undefined;
}
if (activeShapePoints.length > 2) {
let lastPoint = activeShapePoints[activeShapePoints.length - 1];
let firstPoint = activeShapePoints[0];
let closingLine = drawPolyline([lastPoint, firstPoint]);
activeShapeLines.push(closingLine);
tempEntities.push(closingLine);
let pointArea = getArea(activeShapePoints);
addArea(pointArea[0], pointArea[1]);
} else {
alert('闭合操作需要至少3个点');
}
activeShape = drawPolygon(new Cesium.CallbackProperty(() => new Cesium.PolygonHierarchy(activeShapePoints), false));
tempEntities.push(activeShape);
if (floatingPoint.value) {
viewer.value.entities.remove(floatingPoint.value);
}
floatingPoint.value = undefined;
activeShape = undefined;
handler.destroy();
handler = null;
drawing = false;
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
onMounted(() => {
Cesium.Ion.defaultAccessToken = 'CesiumToken';
viewer.value = new Cesium.Viewer('cesiumContainer', {
infoBox: false,
imageryProvider: TDT_YX,
shouldAnimate: true,
geocoder: false,
shadows: false,
terrainProvider: new Cesium.EllipsoidTerrainProvider(),
animation: false,
baseLayerPicker: false,
fullscreenButton: false,
vrButton: false,
homeButton: false,
sceneModePicker: false,
selectionIndicator: false,
timeline: false,
navigationHelpButton: false,
creditContainer: document.createElement('div'),
contextOptions: {
webgl: {
alpha: true,
depth: true,
stencil: true,
antialias: true,
premultipliedAlpha: true,
preserveDrawingBuffer: true,
failIfMajorPerformanceCaveat: true
},
allowTextureFilterAnisotropic: true
}
})
viewer.value.camera.lookAt(
Cesium.Cartesian3.fromDegrees(121.37200, 31.66248, 1000),
new Cesium.Cartesian3(0, 0.0, 1000.0)
)
viewer.value.camera.lookAtTransform(Cesium.Matrix4.IDENTITY)
});
onBeforeUnmount(() => {
if (viewer) {
viewer.value.destroy();
}
});
</script>
<style>
#cesiumContainer {
overflow: hidden;
}
#appp,
#cesiumContainer {
font-family: "Avenir", Helvetica, Arial, sans-serif;
width: 100%;
height: 100%;
overflow: hidden;
}
.btnContainer {
position: absolute;
left: 15px;
top: 80px;
padding: 10px 15px;
border-radius: 5px;
border: 1px solid rgba(128, 128, 128, 0.5);
color: #ffffff;
background: rgba(0, 0, 0, 0.4);
box-shadow: 0 4px 8px rgb(128 128 128 / 50%);
max-width: 300px;
}
button {
background: transparent;
border: 1px solid #00d0ffb8;
color: white;
padding: 7px 9px;
border-radius: 3px;
cursor: pointer;
}
.tip p {
margin: 2px 0px;
padding: 5px 1px;
}
</style>