效果图
方法一:使用插件
cesium_measure.js
下载地址:https://github.com/zhangti0708/cesium-measure/blob/master/src/cesium-measure.js
<!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.0"><script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script><script src="https://cdn.jsdelivr.net/npm/cesium@1.86.0/Build/Cesium/Cesium.js"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cesium@1.86.0/Build/Cesium/Widgets/widgets.css"><title>测距&面积</title>
</head>
<style>.btn {z-index: 999;width: 100px;height: 30px;background-color: #fff;position: absolute;top: 30px;right: 40px;line-height: 30px;text-align: center;user-select: none;}.change {z-index: 999;width: 100px;height: 30px;position: absolute;top: 30px;right: 40px;line-height: 30px;text-align: center;color: #fff;background-color: #007acc;user-select: none;}.pointInfo {z-index: 999;position: absolute;/* top: 50%;left: 50%;transform: translate(-50%, -50%); */width: 80px;height: 40px;background-color: #fff;}
</style><body style="margin: 0;"><div id="app"><div class="pointInfo" v-show="open" ref="pointinfo" id="point"></div><div :class="change?'btn':'change'" @click="signPlace(window.viewer)">{{change?"测距":"测面积"}}</div><div id="mapcontainer"></div></div>
</body>
<script src="../js/cesium_measure.js"></script>
<script>var app = new Vue({el: '#app',data: {plane: [], //存面实例pointId: 0,change: true,open: false,openimg: false,labelname: '',objpoint: {},imgs: ["../img/0.png","../img/1.png","../img/2.png",],urlimg: "../img/0.png",point: [], //测距的点arr: [], //存放划线的点measure: null},methods: {initMap() {var viewer = new Cesium.Viewer('mapcontainer', {animation: false, //是否显示动画控件shouldAnimate: true,homeButton: false, //是否显示Home按钮fullscreenButton: true, //是否显示全屏按钮baseLayerPicker: false, //是否显示图层选择控件geocoder: false, //是否显示地名查找控件timeline: false, //是否显示时间线控件sceneModePicker: false, //是否显示投影方式控件navigationHelpButton: false, //是否显示帮助信息控件requestRenderMode: false, //启用请求渲染模式scene3DOnly: false, //每个几何实例将只能以3D渲染以节省GPU内存sceneMode: 3, //初始场景模式 1 2D模式 2 2D循环模式 3 3D模式 Cesium.SceneModeselectionIndicator: false,skyAtmosphere: false,infoBox: false});viewer._cesiumWidget._creditContainer.style.display = "none";this.measure = new Cesium.Measure(viewer);return viewer},mapFlyTo(viewer) {viewer.camera.flyTo({destination: new Cesium.Cartesian3.fromDegrees(132.02294829, 53.323929, 180000),duration: 3})},signPlace(viewer) {if (this.change) {this.change = false;this.measure.drawLineMeasureGraphics({clampToGround: true,callback: () => {},});} else {this.change = true;this.measure.drawAreaMeasureGraphics({clampToGround: true,callback: (e) => {}});}},},mounted() {window.viewer = this.initMap();this.mapFlyTo(window.viewer);// this.mapEvent(window.viewer)}})
</script></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.0"><script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script><script src="https://cdn.jsdelivr.net/npm/cesium@1.86.0/Build/Cesium/Cesium.js"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cesium@1.86.0/Build/Cesium/Widgets/widgets.css"><title>测距&面积</title>
</head>
<style>.btn {z-index: 999;width: 100px;height: 30px;background-color: #fff;position: absolute;top: 30px;right: 40px;line-height: 30px;text-align: center;user-select: none;}.change {z-index: 999;width: 100px;height: 30px;position: absolute;top: 30px;right: 40px;line-height: 30px;text-align: center;color: #fff;background-color: #007acc;user-select: none;}.pointInfo {z-index: 999;position: absolute;/* top: 50%;left: 50%;transform: translate(-50%, -50%); */width: 80px;height: 40px;background-color: #fff;}
</style><body style="margin: 0;"><div id="app"><div class="pointInfo" v-show="open" ref="pointinfo" id="point"></div><div :class="change?'btn':'change'" @click="signPlace(window.viewer)">{{change?"测距":"测面积"}}</div><div id="mapcontainer"></div></div>
</body>
<script src="../js/cesium_measure.js"></script>
<script>var app = new Vue({el: '#app',data: {plane: [], //存面实例pointId: 0,change: true,open: false,openimg: false,labelname: '',objpoint: {},imgs: ["../img/0.png","../img/1.png","../img/2.png",],urlimg: "../img/0.png",point: [], //测距的点arr: [], //存放划线的点measure: null,timeline: null},methods: {drawLineMeasureGraphics(viewer) {window.that = thisvar draw = new Cesium.CustomDataSource('measureLayer')viewer.dataSources.add(draw)var positions = [],positions_mian = [],polygon = new Cesium.PolygonHierarchy(),_lineEntity = new Cesium.Entity(),$this = this,lineObj,_handlers = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);// left_handlers.setInputAction((movement) => {var cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);// console.log("cli" + cartesian);var cartographic = Cesium.Cartographic.fromCartesian(cartesian, viewer.scene.globe.ellipsoid, new Cesium.Cartographic());var lat = Cesium.Math.toDegrees(cartographic.latitude);var lng = Cesium.Math.toDegrees(cartographic.longitude);var height = cartographic.height;var objpoint = {longitude: lng,latitude: lat}this.point.push(cartesian)if (this.point.length > 1) {var distance = this.disTance(this.point)this.labelname = distance;// this.creatLine(this.arr, viewer)}if (cartesian && cartesian.x) {if (positions.length == 0) {positions.push(cartesian.clone());}this.addpoint(objpoint, viewer)positions.push(cartesian);// 测距}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);_handlers.setInputAction((movement) => {// console.log(positions);var cartesian = viewer.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid);if (positions.length >= 2) {if (cartesian && cartesian.x) {positions.pop();positions.push(cartesian);}}}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);// right_handlers.setInputAction((movement) => {_handlers.destroy()_handlers = nulllet cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);var cartographic = Cesium.Cartographic.fromCartesian(cartesian, viewer.scene.globe.ellipsoid, new Cesium.Cartographic());var lat = Cesium.Math.toDegrees(cartographic.latitude);var lng = Cesium.Math.toDegrees(cartographic.longitude);var height = cartographic.height;var objpoint = {longitude: lng,latitude: lat}this.addpoint(objpoint, viewer)}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);_lineEntity.polyline = {width: 5,material: Cesium.Color.BLUE.withAlpha(0.8),clampToGround: false}_lineEntity.polyline.positions = new Cesium.CallbackProperty(function() {return positions}, false)lineObj = draw.entities.add(_lineEntity)},// 测面drawplane(viewer) {var draw = new Cesium.CustomDataSource('measureLayer1')viewer.dataSources.add(draw)var positions = [],polygon = new Cesium.PolygonHierarchy(),_polygonEntity = new Cesium.Entity(),polyObj = null,_label = '',_handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);// left_handler.setInputAction((movement) => {var cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);if (cartesian && cartesian.x) {if (positions.length == 0) {polygon.positions.push(cartesian.clone())positions.push(cartesian.clone());}positions.push(cartesian.clone());polygon.positions.push(cartesian.clone())// var cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);var cartographic = Cesium.Cartographic.fromCartesian(cartesian, viewer.scene.globe.ellipsoid, new Cesium.Cartographic());var lat = Cesium.Math.toDegrees(cartographic.latitude);var lng = Cesium.Math.toDegrees(cartographic.longitude);var height = cartographic.height;var objpoint = {longitude: lng,latitude: lat}this.addpoint(objpoint, viewer)if (!polyObj) {_polygonEntity.polyline = {width: 3,material: Cesium.Color.BLUE.withAlpha(0.8),clampToGround: false}_polygonEntity.polyline.positions = new Cesium.CallbackProperty(function() {return positions}, false)_polygonEntity.polygon = {hierarchy: new Cesium.CallbackProperty(function() {return polygon}, false),material: Cesium.Color.WHITE.withAlpha(0.8),clampToGround: false}polyObj = draw.entities.add(_polygonEntity)}}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);// mouse_handler.setInputAction((movement) => {var cartesian = viewer.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid);// var cartesian = $this._viewer.scene.camera.pickEllipsoid(movement.endPosition, $this._viewer.scene.globe.ellipsoid);if (positions.length >= 2) {if (cartesian && cartesian.x) {positions.pop()positions.push(cartesian);polygon.positions.pop()polygon.positions.push(cartesian);}}}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);// right_handler.setInputAction((movement) => {let cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);_handler.destroy();positions.push(positions[0]);// let cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);var cartographic = Cesium.Cartographic.fromCartesian(cartesian, viewer.scene.globe.ellipsoid, new Cesium.Cartographic());var lat = Cesium.Math.toDegrees(cartographic.latitude);var lng = Cesium.Math.toDegrees(cartographic.longitude);var height = cartographic.height;var objpoint = {longitude: lng,latitude: lat}this.addpoint(objpoint, viewer)// if (typeof options.callback === 'function') {// options.callback($this.transformCartesianArrayToWGS84Array(positions), polyObj);// }}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);},initMap() {var viewer = new Cesium.Viewer('mapcontainer', {animation: false, //是否显示动画控件shouldAnimate: true,homeButton: false, //是否显示Home按钮fullscreenButton: true, //是否显示全屏按钮baseLayerPicker: false, //是否显示图层选择控件geocoder: false, //是否显示地名查找控件timeline: false, //是否显示时间线控件sceneModePicker: false, //是否显示投影方式控件navigationHelpButton: false, //是否显示帮助信息控件requestRenderMode: false, //启用请求渲染模式scene3DOnly: false, //每个几何实例将只能以3D渲染以节省GPU内存sceneMode: 3, //初始场景模式 1 2D模式 2 2D循环模式 3 3D模式 Cesium.SceneModeselectionIndicator: false,skyAtmosphere: false,infoBox: false});viewer._cesiumWidget._creditContainer.style.display = "none";this.measure = new Cesium.Measure(viewer);return viewer},mapFlyTo(viewer) {viewer.camera.flyTo({destination: new Cesium.Cartesian3.fromDegrees(132.02294829, 53.323929, 180000),duration: 3})},signPlace(viewer) {viewer.screenSpaceEventHandler.destroy()this.point = [];this.labelname = ""if (this.change) {this.change = false;this.drawLineMeasureGraphics(viewer)} else {this.change = true;this.drawplane(viewer)}},// 两点距离//positions 包含两个点的数组disTance(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]);// console.log(point1cartographic, point2cartographic);var geodesic = new Cesium.EllipsoidGeodesic();geodesic.setEndPoints(point1cartographic, point2cartographic);var s = geodesic.surfaceDistance;distance = distance + s;}return distance.toFixed(0);},/*** 计算一组坐标组成多边形的面积* @param {*} positions */getPositionsArea: function(positions) {let result = 0if (positions) {let h = 0let ellipsoid = Cesium.Ellipsoid.WGS84positions.push(positions[0])for (let i = 1; i < positions.length; i++) {let oel = ellipsoid.cartographicToCartesian(this.transformWGS84ToCartographic(positions[i - 1]))let el = ellipsoid.cartographicToCartesian(this.transformWGS84ToCartographic(positions[i]))h += oel.x * el.y - el.x * oel.y}result = Math.abs(h).toFixed(2)}return result},// 添加点//添加图标点addpoint(pointData, viewer) {var billboards = viewer.scene.primitives.add(new Cesium.BillboardCollection());window.billboards = billboards;var labels = viewer.scene.primitives.add(new Cesium.LabelCollection());window.labels = labelsposition = Cesium.Cartesian3.fromDegrees(pointData.longitude, pointData.latitude,0);billboards.add({id: this.pointId,position: position,image: this.urlimg,verticalOrigin: Cesium.VerticalOrigin.BOTTOM,});labels.add({show: !this.change,position: position,text: this.labelname,id: this.pointId,font: '10px',pixelOffset: new Cesium.Cartesian2(-20, -30),})this.pointId++;},//面creatplane(polylineData, viewer) {var entit = this.plane[0]this.plane = [];viewer.entities.remove(entit);var polyon = viewer.entities.add({polygon: {// 获取指定属性(positions,holes(图形内需要挖空的区域))hierarchy: {positions: Cesium.Cartesian3.fromDegreesArray(polylineData)},// 边框outline: true,// 边框颜色outlineColor: Cesium.Color.WHITE,// 边框尺寸outlineWidth: 2,// 填充的颜色,withAlpha透明度material: Cesium.Color.GREEN.withAlpha(0.5),// 是否被提供的材质填充fill: true,// 显示在距相机的距离处的属性,多少区间内是可以显示的distanceDisplayCondition: new Cesium.DistanceDisplayCondition(1000, 10000000),// 是否显示show: true,// 顺序,仅当`clampToGround`为true并且支持地形上的折线时才有效。zIndex: 10}})this.plane.push(polyon)},mapEvent(viewer) {// var mapEvent = new Cesium.ScreenSpaceEventHandler(cesiumScene.canvas);viewer.screenSpaceEventHandler.setInputAction((click) => {var pick = viewer.scene.pick(click.endPosition);if (pick && typeof(pick.id) == "number") {document.body.style = "cursor: pointer;";this.infobox(viewer.scene, viewer)} else {document.body.style = "cursor: default;";}}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);},//弹框位置htmlFixed(cesiumView, htmlOverlay, lng, lat) {const domHeight = htmlOverlay.offsetHeight; // DOM的高度const domWidth = htmlOverlay.offsetWidth; // DOM的宽度const heightOffset = 20; // Y轴偏移量const widthOffset = -9; // X轴偏移量const scratch = new Cesium.Cartesian2();cesiumView.scene.preRender.addEventListener(function() {var las = lat - 0.0009;let position = Cesium.Cartesian3.fromDegrees(lng, las, 2);let canvasPosition = cesiumView.scene.cartesianToCanvasCoordinates(position,scratch);if (Cesium.defined(canvasPosition)) {htmlOverlay.style.top = canvasPosition.y -domHeight -heightOffset + 'px';htmlOverlay.style.left = canvasPosition.x -domWidth / 2 -widthOffset + 'px';}});},},mounted() {window.viewer = this.initMap();this.mapFlyTo(window.viewer);// this.mapEvent(window.viewer)}})
</script></html>