<template> <div class="drawFeature"> <div class="drawTool"> <div class="draToolElement" v-for="(toolElement, index) in drawTool" :key="index"> <div class="tool" :title="toolElement.name" @click="drawEntity(toolElement.type)"> <el-image style="width: 90%; height: 90%" :src="toolElement.url" /> </div> </div> </div> </div> <div id="lengthAndArea"></div> </template> <script> import { reactive, toRefs, onBeforeMount, onMounted, nextTick, watch } from 'vue'; import markerPoint from '@/assets/images/gisMap/Frame.png'; import drawCircle from '@/assets/images/gisMap/Frame 16.png'; import measureLength from '@/assets/images/gisMap/juli.png'; import measureArea from '@/assets/images/gisMap/cemian.png'; import clearFeature from '@/assets/images/gisMap/clearJm.png'; import marker from '@/assets/images/gisMap/in.png'; import bus from '@/utils/mitt'; export default { components: {}, props: {}, setup(props) { const allData = reactive({ drawTool: [ { type: 'point', name: '标记', url: markerPoint, }, { type: 'circle', name: '画圆', url: drawCircle, }, { type: 'polygon', name: '测面', url: measureArea, }, { type: 'polyline', name: '测距', url: measureLength, }, { type: 'clear', name: '清除', url: clearFeature, }, ], }); const drawEntity = (type, config) => { let position = []; let tempPoints = []; let tempEntities = []; let point; // 开启深度检测 newfiberMap.getMap().scene.globe.depthTestAgainstTerrain = true; let handler = new Cesium.ScreenSpaceEventHandler(newfiberMap.getMap().canvas); switch (type) { case 'point': // 监听鼠标左键 handler.setInputAction(function (movement) { // 从相机位置通过windowPosition 世界坐标中的像素创建一条射线。返回Cartesian3射线的位置和方向。 let ray = newfiberMap.getMap().camera.getPickRay(movement.position); // 查找射线与渲染的地球表面之间的交点。射线必须以世界坐标给出。返回Cartesian3对象 position = newfiberMap.getMap().scene.globe.pick(ray, newfiberMap.getMap().scene); let ellipsoid = newfiberMap.getMap().scene.globe.ellipsoid; let cartographic = ellipsoid.cartesianToCartographic(position); let lon = Cesium.Math.toDegrees(cartographic.longitude); // 经度 let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度 point = drawPoint(position, { image: marker }); tempEntities.push(point); }, Cesium.ScreenSpaceEventType.LEFT_CLICK); // 左键双击停止绘制 handler.setInputAction(function () { handler.destroy(); //取消事件句柄 handler = null; }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); // 右击单击停止绘制 handler.setInputAction(function () { handler.destroy(); //取消事件句柄 }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); break; case 'circle': point = null; let lonlatArry = []; let circleOptions = {}; let circleFeature = null; let radius; handler.setInputAction(function (click) { //clearDrawEntities('point'); //调用获取位置信息的接口 let ray = newfiberMap.getMap().camera.getPickRay(click.position); position = newfiberMap.getMap().scene.globe.pick(ray, newfiberMap.getMap().scene); tempPoints.push(position); let ellipsoid = newfiberMap.getMap().scene.globe.ellipsoid; let cartographic = ellipsoid.cartesianToCartographic(position); let lon = Cesium.Math.toDegrees(cartographic.longitude); // 经度 let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度 let lonlat = [lon, lat]; if (lonlatArry < 1) { lonlatArry.push(lonlat); // let tempLength = tempPoints.length; //调用绘制点的接口 point = drawPoint(position, { image: null }); } if (lonlatArry.length > 0) { handler.setInputAction(function (movement) { clearDrawEntities('circle'); let ellipsoid_end = newfiberMap.getMap().scene.globe.ellipsoid; let cartesian = newfiberMap.getMap().camera.pickEllipsoid(movement.endPosition, ellipsoid_end); let cartographic_end = ellipsoid_end.cartesianToCartographic(cartesian); let lon_end = Cesium.Math.toDegrees(cartographic_end.longitude); // 经度 let lat_end = Cesium.Math.toDegrees(cartographic_end.latitude); // 纬度 radius = turf.distance(turf.point(lonlatArry[0]), turf.point([lon_end, lat_end])) * 1000; circleOptions = { position: lonlatArry[0], radius: radius, }; circleFeature = drawCircle(circleOptions); }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); //双击取消绘制操作 handler.setInputAction(function (click) { let areaCircle = (Math.PI * (radius / 1000) * (radius / 1000)).toFixed(3); addLabelInfo(lonlatArry[0], { text: `${areaCircle}km²` }); let circleJson = turf.circle(lonlatArry[0], radius / 1000); console.log('circleJson', circleJson); handler.destroy(); //取消事件句柄 handler = null; lonlatArry = []; }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); break; case 'polyline': tempEntities = []; point = null; let lonlatarry = []; //鼠标移动事件 handler.setInputAction(function (movement) {}, Cesium.ScreenSpaceEventType.MOUSE_MOVE); //左键点击操作 handler.setInputAction(function (click) { //调用获取位置信息的接口 let ray = newfiberMap.getMap().camera.getPickRay(click.position); position = newfiberMap.getMap().scene.globe.pick(ray, newfiberMap.getMap().scene); tempPoints.push(position); let ellipsoid = newfiberMap.getMap().scene.globe.ellipsoid; let cartographic = ellipsoid.cartesianToCartographic(position); let lon = Cesium.Math.toDegrees(cartographic.longitude); // 经度 let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度 let lonlat = [lon, lat]; lonlatarry.push(lonlat); let tempLength = tempPoints.length; //调用绘制点的接口 point = drawPoint(tempPoints[tempPoints.length - 1], { image: null }); if (tempLength > 1) { let pointline = drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]); } else { // tooltip.innerHTML = "请绘制下一个点,右键结束"; } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); //双击取消绘制操作 handler.setInputAction(function (click) { let lineJson = { type: 'LineString', coordinates: lonlatarry, //获取线的geojson }; let lengthLine = turf.length(lineJson, { units: 'kilometers' }).toFixed(3); //计算路线长度 // let roadline = { // line: Terraformer.WKT.convert(lineJson), // length: lengthLine, // }; // bus.emit('roadObj', roadline); let center = turf.center(lineJson).geometry.coordinates; //计算线的中心点 addLabelInfo(center, { text: `${lengthLine}km` }); handler.destroy(); //取消事件句柄 handler = null; }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); break; case 'polygon': point = null; let lonlatList = []; //鼠标移动事件 handler.setInputAction(function (movement) {}, Cesium.ScreenSpaceEventType.MOUSE_MOVE); //左键点击操作 handler.setInputAction(function (click) { //调用获取位置信息的接口 let ray = newfiberMap.getMap().camera.getPickRay(click.position); position = newfiberMap.getMap().scene.globe.pick(ray, newfiberMap.getMap().scene); tempPoints.push(position); let ellipsoid = newfiberMap.getMap().scene.globe.ellipsoid; let cartographic = ellipsoid.cartesianToCartographic(position); let lon = Cesium.Math.toDegrees(cartographic.longitude); // 经度 let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度 let lonlat = [lon, lat]; lonlatList.push(lonlat); let tempLength = tempPoints.length; //调用绘制点的接口 point = drawPoint(position, { image: null }); //tempEntities.push(point); if (tempLength > 1) { let pointline = drawPolyline([tempPoints[tempPoints.length - 2], tempPoints[tempPoints.length - 1]]); //tempEntities.push(pointline); } else { // tooltip.innerHTML = "请绘制下一个点,右键结束"; } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); //双击取消绘制操作 handler.setInputAction(function (click) { let cartesian = newfiberMap.getMap().camera.pickEllipsoid(click.position, newfiberMap.getMap().scene.globe.ellipsoid); if (cartesian) { let tempLength = tempPoints.length; if (tempLength < 3) { alert('请选择3个以上的点再执行闭合操作命令'); } else { //闭合最后一条线 let pointline = drawPolyline([tempPoints[tempPoints.length - 1], tempPoints[0]]); //tempEntities.push(pointline); drawPolygon(tempPoints); tempEntities.push(tempPoints); let polygonJson = { type: 'Polygon', coordinates: [lonlatList], //获取面的geojson }; let areaPolygon = (turf.area(polygonJson) / 1000000).toFixed(3); //计算路线长度 let center = turf.center(polygonJson).geometry.coordinates; //计算线的中心点 addLabelInfo(center, { text: `${areaPolygon}km²` }); handler.destroy(); //取消事件句柄 handler = null; } } }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); break; case 'clear': clearDrawEntities(); break; } function drawPoint(position, config) { let config_ = config ? config : {}; return newfiberMap.getMap().entities.add({ name: '点几何对象', position: position, point: config_ && config_.image ? {} : { color: new Cesium.Color.fromCssColorString('rgb(186,24,222)'), pixelSize: 4, outlineColor: new Cesium.Color.fromCssColorString('rgb(186,24,222)'), outlineWidth: 2, disableDepthTestDistance: Number.POSITIVE_INFINITY, }, billboard: { show: config_ && config_.image ? true : false, image: config_ && config_.image ? config_.image : null, width: 30, height: 30, disableDepthTestDistance: Number.POSITIVE_INFINITY, heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, }, }); } function drawCircle(options, config_) { return newfiberMap.getMap().entities.add({ name: '圆几何对象', position: Cesium.Cartesian3.fromDegrees(options.position[0], options.position[1]), ellipse: { semiMinorAxis: options.radius, // 半短轴 semiMajorAxis: options.radius, // 半长轴 outline: true, outlineWidth: config_ && config_.width ? config_.width : 5.0, outlineColor: new Cesium.Color.fromCssColorString('rgb(255, 130, 255)'), material: new Cesium.Color.fromCssColorString('rgba(166,64,202,0.6)'), }, }); } function drawPolyline(positions, config_) { if (positions.length < 1) return; let config = config_ ? config_ : {}; return newfiberMap.getMap().entities.add({ name: '线几何对象', polyline: { positions: positions, width: config.width ? config.width : 5.0, material: new Cesium.PolylineGlowMaterialProperty({ color: config.color ? new Cesium.Color.fromCssColorString(config.color) : new Cesium.Color.fromCssColorString('rgb(186,24,222)'), }), depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({ color: config.color ? new Cesium.Color.fromCssColorString(config.color) : new Cesium.Color.fromCssColorString('rgb(186,24,222)'), }), clampToGround: true, }, }); } function drawPolygon(positions, config_) { if (positions.length < 2) return; let config = config_ ? config_ : {}; return newfiberMap.getMap().entities.add({ name: '面几何对象', polygon: { hierarchy: positions, material: config.color ? new Cesium.Color.fromCssColorString(config.color).withAlpha(0.2) : new Cesium.Color.fromCssColorString('rgba(166,64,202,0.6)'), }, }); } function addLabelInfo(position, config) { let config_ = config ? config : {}; return newfiberMap.getMap().entities.add({ name: '几何标注', position: Cesium.Cartesian3.fromDegrees(position[0], position[1], 0), label: { text: config_.text, font: '15px sans-serif', pixelOffset: new Cartesian2(10, 10), disableDepthTestDistance: Number.POSITIVE_INFINITY, }, }); } }; /**清除绘制 * */ const clearDrawEntities = type => { // 清除之前的实体 const entitys = newfiberMap.getMap().entities._entities._array; let length = entitys.length; if (type && type == 'circle') { for (let f = length - 1; f >= 0; f--) { if (entitys[f]._name && entitys[f]._name === '圆几何对象') { newfiberMap.getMap().entities.remove(entitys[f]); } } } else if (type == 'point') { for (let f = length - 1; f >= 0; f--) { if (entitys[f]._name && entitys[f]._name === '点几何对象') { newfiberMap.getMap().entities.remove(entitys[f]); } } } else { // 倒叙遍历防止实体减少之后entitys[f]不存在 for (let f = length - 1; f >= 0; f--) { if ( entitys[f]._name && (entitys[f]._name === '点几何对象' || entitys[f]._name === '线几何对象' || entitys[f]._name === '面几何对象' || entitys[f]._name === '圆几何对象' || entitys[f]._name === '几何标注') ) { newfiberMap.getMap().entities.remove(entitys[f]); } } } }; //地图移动,更新标注位置 onBeforeUnmount(() => { bus.off('roadObj'); }); return { ...toRefs(allData), drawEntity, clearDrawEntities, }; }, }; </script> <style lang="scss"> .drawFeature { display: flex; position: absolute; right: 470px; top: 20px; z-index: 20; background: transparent; .draToolElement { width: 35px; height: 35px; margin: 10px; cursor: pointer; } } #lengthAndArea { position: absolute; .featureChild { position: absolute; z-index: 110; } } </style>