├── env.d.ts ├── public └── favicon.ico ├── src ├── assets │ └── start.png ├── main.ts ├── js │ ├── prompt │ │ ├── prompt.css │ │ └── prompt.js │ ├── util.js │ └── plot │ │ ├── createPoint.js │ │ ├── createBillboard.js │ │ ├── createGltfModel.js │ │ ├── createRectangle.js │ │ ├── createLabel.js │ │ ├── createPolyline.js │ │ ├── createPolygon.js │ │ ├── createRectgon.js │ │ ├── basePlot.js │ │ ├── createCircle.js │ │ └── drawTool.js └── Index.vue ├── tsconfig.json ├── tsconfig.node.json ├── tsconfig.app.json ├── vite.config.ts ├── .gitignore ├── index.html ├── package.json └── README.md /env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitgitczl/cesiumExp-plot/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitgitczl/cesiumExp-plot/HEAD/src/assets/start.png -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "./tsconfig.node.json" 6 | }, 7 | { 8 | "path": "./tsconfig.app.json" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './Index.vue' 3 | import Antd from "ant-design-vue"; 4 | import "ant-design-vue/dist/antd.css"; 5 | const app = createApp(App) 6 | app.use(Antd); 7 | app.mount('#app') 8 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node18/tsconfig.json", 3 | "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"], 4 | "compilerOptions": { 5 | "composite": true, 6 | "module": "ESNext", 7 | "types": ["node"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.dom.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 4 | "exclude": ["src/**/__tests__/*"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "baseUrl": ".", 8 | "paths": { 9 | "@/*": ["./src/*"] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [vue()], 9 | resolve: { 10 | alias: { 11 | '@': fileURLToPath(new URL('./src', import.meta.url)) 12 | } 13 | } 14 | }) 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 三维案例共享 11 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cesium-example", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "run-p type-check build-only", 8 | "preview": "vite preview", 9 | "build-only": "vite build", 10 | "type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false" 11 | }, 12 | "dependencies": { 13 | "ant-design-vue": "^3.2.20", 14 | "vue": "^3.3.2", 15 | "vue-router": "^4.2.0" 16 | }, 17 | "devDependencies": { 18 | "@tsconfig/node18": "^2.0.1", 19 | "@types/node": "^18.16.8", 20 | "@vitejs/plugin-vue": "^4.2.3", 21 | "@vue/tsconfig": "^0.4.0", 22 | "npm-run-all": "^4.1.5", 23 | "typescript": "~5.0.4", 24 | "vite": "^4.3.5", 25 | "vue-tsc": "^1.6.4" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/js/prompt/prompt.css: -------------------------------------------------------------------------------- 1 | .easy3d-prompt { 2 | position: absolute; 3 | top: -9999px; 4 | left: -9999px; 5 | } 6 | 7 | .prompt-close { 8 | position: absolute; 9 | top: 0; 10 | right: 0; 11 | padding: 4px 4px 0 0; 12 | border: none; 13 | text-align: center; 14 | width: 18px; 15 | height: 14px; 16 | font: 16px/14px Tahoma, Verdana, sans-serif; 17 | color: #c3c3c3; 18 | text-decoration: none; 19 | font-weight: bold; 20 | background: transparent; 21 | } 22 | 23 | .prompt-content-container { 24 | /* 不给padding撑不开div */ 25 | max-width: 400px; 26 | border-radius: 4px; 27 | padding: 1px; 28 | background: white; 29 | color: #333; 30 | box-shadow: 0 3px 14px rgb(0 0 0 / 40%); 31 | 32 | } 33 | 34 | .prompt-content { 35 | margin: 13px 19px; 36 | } 37 | 38 | .prompt-anchor-container { 39 | 40 | position: absolute; 41 | width: 40px; 42 | 43 | height: 20px; 44 | left: 50%; 45 | margin-left: -20px; 46 | overflow: hidden ; 47 | pointer-events: none; 48 | } 49 | 50 | .prompt-anchor { 51 | margin: -10px auto 0; 52 | background: white; 53 | width: 17px; 54 | height: 17px; 55 | -webkit-transform: rotate(45deg); 56 | transform: rotate(45deg); 57 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cesium标绘插件 2 | ### [在线体验地址1(三维框架内)](http://mapgl.com/shareCode/#/PopupTooltip?downUrl=) 3 | ### [在线体验地址2](http://mapgl.com/shareCode/#/Plot?downUrl=) 4 | gitee:https://gitee.com/caozl1132/CesiumExp-plot 5 | github:https://github.com/gitgitczl/CesiumExp-plot 6 | 7 | ps:如果可以的话,希望大家能给我个star,好让我有更新下去的动力; 8 | 9 | *** 10 | 实现原理:
11 | - 其中实现动态绘制的原理主要是利用了callbackproperty([property总结](https://zhuanlan.zhihu.com/p/50534090)),核心的难点是处理好标绘对象的状态管理,我在类中使用了一个state属性来进行了管理,用其控制何时开始绘制、何时结束绘制、何时开始编辑等。 12 | 此类库提供了多种方法,如转geojson、加载geojson等。 13 | - 整个类库我分为了三个部分:basePlot(所有标绘的父类)、createxxx(单个标绘)、drawTool(我称之为标绘管理工具)。 14 | 假设我现在想绘制一个线对象,那么我有以下两种方式: 15 | 1. 通过引入单个createXXX.js,然后new此对象即可。 16 | ``` 17 | import Polyline from "./js/plot/CreatePolyline.js"; 18 | let line = new Polyline(viewer,{}); 19 | line.start(); 20 | ``` 21 | 2. 通过引入drawTool,然后new DrawTool ,然后调用其start方法,传入不同的参数(推荐此种方法,因为可以通过on进行状态监听)。 22 | ``` 23 | import Tool from "./js/plot/drawTool.js" 24 | plotDrawTool = new Tool(viewer, { 25 | canEdit: true, 26 | }); 27 | // 监听不同的状态:如开始标绘、标绘结束、开始编辑等 28 | plotDrawTool.on("endCreate", function (entObj, ent) { 29 | // 标绘结束时执行 30 | ...... 31 | }); 32 | plotDrawTool.start({ 33 | "name": "线", 34 | "type": "polyline", 35 | "iconImg": "./easy3d/images/plot/polyline.png", 36 | "styleType": "polyline", 37 | "style": { 38 | "clampToGround": true, 39 | "color": "#ffff00" 40 | } 41 | }); 42 | ``` 43 | 以上是此库一个大致的介绍,具体调用和开发请参考开发文档。 44 | *** 45 | 其它: 46 | qq群:606645466(GIS之家共享交流群) 47 | 48 | [更多案例地址](http://mapgl.com/shareCode/)    [更多免费数据](http://mapgl.com/shareData/)    [开发文档说明](http://mapgl.com/3dapi/) 49 | 50 | [其它源码下载(标绘、量算、动态材质、漫游、地图分析等)](http://mapgl.com/introduce/) 51 | -------------------------------------------------------------------------------- /src/Index.vue: -------------------------------------------------------------------------------- 1 | 9 | 126 | 127 | 145 | -------------------------------------------------------------------------------- /src/js/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 三维基础方法 3 | * @example util.getCameraView(viewer); 4 | * @exports util 5 | * @alias util 6 | */ 7 | let util = {}; 8 | /** 9 | * 世界坐标转经纬度 10 | * @param {Cesium.Cartesian3 } cartesian 世界坐标 11 | * @param {Cesium.Viewer} viewer 当前viewer对象 12 | * @returns { Array } 经纬度坐标s 13 | */ 14 | util.cartesianToLnglat = function (cartesian, viewer) { 15 | if (!cartesian) return []; 16 | viewer = viewer || window.viewer; 17 | var lnglat = Cesium.Cartographic.fromCartesian(cartesian); 18 | var lat = Cesium.Math.toDegrees(lnglat.latitude); 19 | var lng = Cesium.Math.toDegrees(lnglat.longitude); 20 | var hei = lnglat.height; 21 | return [lng, lat, hei]; 22 | } 23 | 24 | util.getViewCenter = (viewer) => { 25 | if (!viewer) return; 26 | var rectangle = viewer.camera.computeViewRectangle(); 27 | var west = rectangle.west / Math.PI * 180; 28 | var north = rectangle.north / Math.PI * 180; 29 | var east = rectangle.east / Math.PI * 180; 30 | var south = rectangle.south / Math.PI * 180; 31 | return [(east + west) / 2, (north + south) / 2] 32 | } 33 | 34 | /** 35 | * 世界坐标数组转经纬度数组 36 | * @param {Cesium.Cartesian3[]} cartesians 世界坐标数组 37 | * @param {Cesium.Viewer} viewer 当前viewer对象 38 | * @returns { Array } 经纬度坐标数组 39 | */ 40 | util.cartesiansToLnglats = function (cartesians, viewer) { 41 | if (!cartesians || cartesians.length < 1) return; 42 | viewer = viewer || window.viewer; 43 | if (!viewer) { 44 | console.log('util.cartesiansToLnglats方法缺少viewer对象'); 45 | return; 46 | } 47 | var arr = []; 48 | for (var i = 0; i < cartesians.length; i++) { 49 | arr.push(util.cartesianToLnglat(cartesians[i], viewer)); 50 | } 51 | return arr; 52 | } 53 | 54 | /** 55 | * 经纬度坐标数组转世界坐标数组 56 | * @param {Array[]} lnglats 经纬度坐标数组 57 | * @returns {Cesium.Cartesian3[]} cartesians 世界坐标数组 58 | * @example util.lnglatsToCartesians([[117,40],[118.41]]) 59 | */ 60 | util.lnglatsToCartesians = function (lnglats) { 61 | if (!lnglats || lnglats.length < 1) return; 62 | var arr = []; 63 | for (var i = 0; i < lnglats.length; i++) { 64 | var c3 = Cesium.Cartesian3.fromDegrees(lnglats[i][0], lnglats[i][1], lnglats[i][2] || 0); 65 | arr.push(c3); 66 | } 67 | return arr; 68 | } 69 | 70 | /** 71 | * 视角定位方法 72 | * @param {Object} opt 定位参数 73 | * @param {Cartesian3|Array} opt.center 当前定位中心点 74 | * @param {Number} opt.heading 当前定位偏转角度 默认为0 75 | * @param {Number} opt.pitch 当前定位仰俯角 默认为-60 76 | * @param {Number} opt.range 当前定位距离 默认为1000米 77 | * @param {Cesium.Viewer} viewer 当前viewer对象 78 | */ 79 | util.flyTo = function (opt, viewer) { 80 | if (!viewer) { 81 | console.log('util.flyTo缺少viewer对象'); 82 | return; 83 | } 84 | opt = opt || {}; 85 | let center = opt.center; 86 | if (!center) { 87 | console.log("缺少定位坐标!"); 88 | return; 89 | } 90 | if (center instanceof Cesium.Cartesian3) { 91 | viewer.camera.flyToBoundingSphere(new Cesium.BoundingSphere(center), { 92 | offset: new Cesium.HeadingPitchRange( 93 | Cesium.Math.toRadians(opt.heading || 0), 94 | Cesium.Math.toRadians(opt.pitch || -60), 95 | opt.range || 10000 96 | ) 97 | }); 98 | } 99 | if (center instanceof Array) { 100 | var boundingSphere = new Cesium.BoundingSphere(Cesium.Cartesian3.fromDegrees(center[0], center[1], center[2])); 101 | viewer.camera.flyToBoundingSphere(boundingSphere, { 102 | offset: new Cesium.HeadingPitchRange( 103 | Cesium.Math.toRadians(opt.heading || 0), 104 | Cesium.Math.toRadians(opt.pitch || -60), 105 | opt.range || 10000 106 | ) 107 | }); 108 | } 109 | } 110 | 111 | /** 112 | * 获取当相机姿态 113 | * @param {Cesium.Viewer} viewer 当前viewer对象 114 | * @returns {Object} cameraView 当前相机姿态 115 | */ 116 | util.getCameraView = function (viewer) { 117 | viewer = viewer || window.viewer; 118 | if (!viewer) { 119 | console.log('util.getCameraView缺少viewer对象'); 120 | return; 121 | } 122 | var camera = viewer.camera; 123 | var position = camera.position; 124 | var heading = camera.heading; 125 | var pitch = camera.pitch; 126 | var roll = camera.roll; 127 | var lnglat = Cesium.Cartographic.fromCartesian(position); 128 | 129 | var cameraV = { 130 | "x": Cesium.Math.toDegrees(lnglat.longitude), 131 | "y": Cesium.Math.toDegrees(lnglat.latitude), 132 | "z": lnglat.height, 133 | "heading": Cesium.Math.toDegrees(heading), 134 | "pitch": Cesium.Math.toDegrees(pitch), 135 | "roll": Cesium.Math.toDegrees(roll) 136 | }; 137 | return cameraV; 138 | } 139 | 140 | /** 141 | * 设置相机姿态 一般和getCameraView搭配使用 142 | * @param {Object} cameraView 相机姿态参数 143 | * @param {Number} cameraView.duration 定位所需时间 144 | * @param {Cesium.Viewer} viewer 当前viewer对象 145 | */ 146 | util.setCameraView = function (obj, viewer) { 147 | viewer = viewer || window.viewer; 148 | if (!viewer) { 149 | console.log('util.setCameraView缺少viewer对象'); 150 | return; 151 | } 152 | if (!obj) return; 153 | var position = obj.destination || Cesium.Cartesian3.fromDegrees(obj.x, obj.y, obj.z); // 兼容cartesian3和xyz 154 | viewer.camera.flyTo({ 155 | destination: position, 156 | orientation: { 157 | heading: Cesium.Math.toRadians(obj.heading || 0), 158 | pitch: Cesium.Math.toRadians(obj.pitch || 0), 159 | roll: Cesium.Math.toRadians(obj.roll || 0) 160 | }, 161 | duration: obj.duration === undefined ? 3 : obj.duration, 162 | complete: obj.complete 163 | }); 164 | } 165 | 166 | /** 167 | * 计算当前三角形面积 168 | * @param {Cesium.Cartesian3 } pos1 当前点坐标1 169 | * @param {Cesium.Cartesian3 } pos2 当前点坐标2 170 | * @param {Cesium.Cartesian3 } pos3 当前点坐标3 171 | * @returns {Number} area,面积 172 | */ 173 | util.computeAreaOfTriangle = function (pos1, pos2, pos3) { 174 | if (!pos1 || !pos2 || !pos3) { 175 | console.log("传入坐标有误!"); 176 | return 0; 177 | } 178 | var a = Cesium.Cartesian3.distance(pos1, pos2); 179 | var b = Cesium.Cartesian3.distance(pos2, pos3); 180 | var c = Cesium.Cartesian3.distance(pos3, pos1); 181 | var S = (a + b + c) / 2; 182 | return Math.sqrt(S * (S - a) * (S - b) * (S - c)); 183 | } 184 | 185 | export default util; 186 | 187 | -------------------------------------------------------------------------------- /src/js/plot/createPoint.js: -------------------------------------------------------------------------------- 1 | import '../prompt/prompt.css' 2 | import Prompt from '../prompt/prompt.js' 3 | import BasePlot from './basePlot'; 4 | import util from "../util"; 5 | 6 | /** 7 | * 点标绘类 8 | * @class 9 | * @augments BasePlot 10 | * @alias BasePlot.CreatePoint 11 | */ 12 | class CreatePoint extends BasePlot { 13 | constructor(viewer, style) { 14 | super(viewer, style); 15 | this.type = "point"; 16 | this.viewer = viewer; 17 | let defaultStyle = { 18 | color: Cesium.Color.AQUA, 19 | pixelSize: 10, 20 | outlineWidth: 1 21 | } 22 | this.style = Object.assign(defaultStyle, style || {}); 23 | 24 | /** 25 | * @property {Cesium.Cartesian3} 坐标 26 | */ 27 | this.position = null; 28 | } 29 | 30 | start(callback) { 31 | if (!this.prompt && this.promptStyle.show) this.prompt = new Prompt(this.viewer, this.promptStyle); 32 | this.state = "startCreate"; 33 | let that = this; 34 | if (!this.handler) this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 35 | this.handler.setInputAction(function (evt) { //单击开始绘制 36 | let cartesian = that.getCatesian3FromPX(evt.position, that.viewer); 37 | if (!cartesian) return; 38 | that.entity = that.createPoint(cartesian); 39 | that.position = cartesian; 40 | if (that.handler) { 41 | that.handler.destroy(); 42 | that.handler = null; 43 | } 44 | if (that.prompt) { 45 | that.prompt.destroy(); 46 | that.prompt = null; 47 | } 48 | that.state = "endCreate"; 49 | if (callback) callback(that.entity); 50 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 51 | this.handler.setInputAction(function (evt) { //单击开始绘制 52 | that.prompt.update(evt.endPosition, "单击新增"); 53 | that.state = "creating"; 54 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 55 | } 56 | 57 | endCreate() { 58 | let that = this; 59 | if (that.handler) { 60 | that.handler.destroy(); 61 | that.handler = null; 62 | } 63 | if (that.prompt) { 64 | that.prompt.destroy(); 65 | that.prompt = null; 66 | } 67 | that.state = "endCreate"; 68 | } 69 | 70 | /** 71 | * 当前步骤结束 72 | */ 73 | done() { 74 | if (this.state == "startCreate") { 75 | this.destroy(); 76 | } else if (this.state == "creating") { 77 | this.destroy(); 78 | } else if (this.state == "startEdit" || this.state == "editing") { 79 | this.endEdit(); 80 | } else { 81 | 82 | } 83 | } 84 | 85 | createByPositions(lnglatArr, callback) { 86 | if (!lnglatArr) return; 87 | this.state = "startCreate"; 88 | let position = (lnglatArr instanceof Cesium.Cartesian3) ? lnglatArr : Cesium.Cartesian3.fromDegrees(lnglatArr[0], lnglatArr[1], lnglatArr[2]); 89 | this.position = position; 90 | if (!position) return; 91 | this.entity = this.createPoint(position); 92 | if (callback) callback(this.entity); 93 | this.state = "endCreate"; 94 | } 95 | 96 | // 设置相关样式 97 | setStyle(style) { 98 | if (!style) return; 99 | if (style.color) { 100 | let color = Cesium.Color.fromCssColorString(style.color || "#ffff00"); 101 | color = color.withAlpha(style.colorAlpha); 102 | this.entity.point.color = color; 103 | } 104 | this.entity.point.outlineWidth = Number(style.outlineWidth); 105 | if (style.outlineColor) { 106 | let outlineColor = Cesium.Color.fromCssColorString(style.outlineColor || "#000000"); 107 | outlineColor = outlineColor.withAlpha(style.outlineColorAlpha) 108 | this.entity.point.outlineColor = outlineColor; 109 | } 110 | this.entity.point.heightReference = Number(style.heightReference); 111 | this.entity.point.pixelSize = Number(style.pixelSize); 112 | this.style = Object.assign(this.style, style); 113 | } 114 | // 获取相关样式 115 | getStyle() { 116 | let obj = {}; 117 | let point = this.entity.point; 118 | 119 | let color = point.color.getValue(); 120 | obj.colorAlpha = color.alpha; 121 | obj.color = new Cesium.Color(color.red, color.green, color.blue, 1).toCssHexString(); 122 | 123 | obj.outlineWidth = point.outlineWidth._value; 124 | let outlineColor = point.outlineColor.getValue(); 125 | obj.outlineColorAlpha = outlineColor.alpha; 126 | obj.outlineColor = new Cesium.Color(outlineColor.red, outlineColor.green, outlineColor.blue, 1).toCssHexString(); 127 | 128 | if (point.heightReference != undefined) obj.heightReference = point.heightReference.getValue(); 129 | obj.pixelSize = Number(point.pixelSize); 130 | return obj; 131 | } 132 | getPositions(isWgs84) { 133 | return isWgs84 ? util.cartesianToLnglat(this.position) : this.position 134 | } 135 | 136 | getLnglats(){ 137 | return this.getPositions(true); 138 | } 139 | 140 | startEdit(callback) { 141 | if (this.state == "startEdit" || this.state == "editing" || !this.entity) return; 142 | this.state = "startEdit"; 143 | if (!this.modifyHandler) this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 144 | let that = this; 145 | let editPoint; 146 | this.modifyHandler.setInputAction(function (evt) { 147 | let pick = that.viewer.scene.pick(evt.position); 148 | if (Cesium.defined(pick) && pick.id) { 149 | editPoint = pick.id; 150 | that.forbidDrawWorld(true); 151 | } 152 | }, Cesium.ScreenSpaceEventType.LEFT_DOWN); 153 | this.modifyHandler.setInputAction(function (evt) { 154 | if (!editPoint) return; 155 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 156 | if (!cartesian) return; 157 | if (that.entity) { 158 | that.entity.position.setValue(cartesian); 159 | that.position = cartesian; 160 | that.state = "editing"; 161 | } 162 | if(callback) callback(); 163 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 164 | 165 | this.modifyHandler.setInputAction(function (evt) { 166 | if (!editPoint) return; 167 | that.forbidDrawWorld(false); 168 | if (that.modifyHandler) { 169 | that.modifyHandler.destroy(); 170 | that.modifyHandler = null; 171 | that.state = "editing"; 172 | } 173 | }, Cesium.ScreenSpaceEventType.LEFT_UP); 174 | } 175 | endEdit(callback) { 176 | if (this.modifyHandler) { 177 | this.modifyHandler.destroy(); 178 | this.modifyHandler = null; 179 | if (callback) callback(this.entity); 180 | } 181 | this.forbidDrawWorld(false); 182 | this.state = "endEdit"; 183 | } 184 | createPoint(cartesian) { 185 | if (!cartesian) return; 186 | let point = this.viewer.entities.add({ 187 | position: cartesian, 188 | point: { 189 | color: this.style.color instanceof Cesium.Color ? this.style.color : (this.style.color ? Cesium.Color.fromCssColorString(this.style.color).withAlpha(this.style.colorAlpha || 1) : Cesium.Color.WHITE), 190 | outlineColor: this.style.outlineColor instanceof Cesium.Color ? this.style.outlineColor : (this.style.outlineColor ? Cesium.Color.fromCssColorString(this.style.outlineColor).withAlpha(this.style.outlineColorAlpha || 1) : Cesium.Color.BLACK), 191 | outlineWidth: this.style.outlineWidth || 4, 192 | pixelSize: this.style.pixelSize || 20, 193 | disableDepthTestDistance: Number.MAX_VALUE 194 | } 195 | }) 196 | point.objId = this.objId; 197 | return point; 198 | } 199 | 200 | } 201 | 202 | 203 | export default CreatePoint; -------------------------------------------------------------------------------- /src/js/plot/createBillboard.js: -------------------------------------------------------------------------------- 1 | import Prompt from '../prompt/prompt.js' 2 | import util from '../util.js' 3 | import BasePlot from './basePlot'; 4 | /** 5 | * 图标标绘类 6 | * @class 7 | * @augments BasePlot 8 | * @alias BasePlot.CreateBillboard 9 | */ 10 | class CreateBillboard extends BasePlot { 11 | constructor(viewer, style) { 12 | super(viewer, style); 13 | 14 | this.type = "billboard"; 15 | this.viewer = viewer; 16 | let defaultStyle = { 17 | verticalOrigin: Cesium.VerticalOrigin.BOTTOM, 18 | scale: 1 19 | } 20 | this.style = Object.assign({}, defaultStyle, style || {}); 21 | 22 | this.entity = null; 23 | if (!this.style.hasOwnProperty("image")) { 24 | console.log("未设置billboard的参数!"); 25 | } 26 | 27 | /** 28 | * @property {Cesium.Cartesian3} 图标坐标 29 | */ 30 | this.position = null; 31 | } 32 | 33 | /** 34 | * 开始绘制 35 | * @param {Function} callback 绘制成功后回调函数 36 | */ 37 | start(callback) { 38 | if (!this.prompt && this.promptStyle.show) this.prompt = new Prompt(this.viewer, this.promptStyle); 39 | this.state = "startCreate"; 40 | let that = this; 41 | if (!this.handler) this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 42 | this.handler.setInputAction(function (evt) { //单击开始绘制 43 | let cartesian = that.getCatesian3FromPX(evt.position, that.viewer); 44 | if (!cartesian) return; 45 | that.position = cartesian.clone(); 46 | that.entity = that.createBillboard(that.position); 47 | if (that.handler) { 48 | that.handler.destroy(); 49 | that.handler = null; 50 | } 51 | if (that.prompt) { 52 | that.prompt.destroy(); 53 | that.prompt = null; 54 | } 55 | that.state = "endCreate"; 56 | if (callback) callback(that.entity); 57 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 58 | this.handler.setInputAction(function (evt) { //单击开始绘制 59 | that.prompt.update(evt.endPosition, "单击新增"); 60 | that.state = "creating"; 61 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 62 | } 63 | 64 | /** 65 | * 结束绘制 66 | * @param {Function} callback 结束绘制后回调函数 67 | */ 68 | endCreate() { 69 | let that = this; 70 | if (that.handler) { 71 | that.handler.destroy(); 72 | that.handler = null; 73 | } 74 | if (that.prompt) { 75 | that.prompt.destroy(); 76 | that.prompt = null; 77 | } 78 | that.state = "endCreate"; 79 | } 80 | 81 | /** 82 | * 当前步骤结束 83 | */ 84 | done() { 85 | if (this.state == "startCreate") { 86 | this.destroy(); 87 | } else if (this.state == "creating") { 88 | this.destroy(); 89 | } else if (this.state == "startEdit" || this.state == "editing") { 90 | this.endEdit(); 91 | } else { 92 | 93 | } 94 | } 95 | 96 | /** 97 | * 通过坐标数组构建 98 | * @param {Array} lnglatArr 经纬度坐标数组 99 | * @callback {Function} callback 绘制成功后回调函数 100 | */ 101 | createByPositions(lnglatArr, callback) { 102 | if (!lnglatArr) return; 103 | this.state = "startCreate"; 104 | let position = null; 105 | if (lnglatArr instanceof Cesium.Cartesian3) { 106 | position = lnglatArr.clone(); 107 | } else { 108 | position = Cesium.Cartesian3.fromDegrees(Number(lnglatArr[0]), Number(lnglatArr[1]), Number(lnglatArr[2] || 0)); 109 | } 110 | 111 | if (!position) return; 112 | this.position = position.clone(); 113 | this.entity = this.createBillboard(this.position); 114 | if (callback) callback(this.entity); 115 | this.state = "endCreate"; 116 | } 117 | 118 | /** 119 | * 设置相关样式 120 | * @param {Object} style 样式 121 | */ 122 | setStyle(style) { 123 | if (!style) return; 124 | let billboard = this.entity.billboard; 125 | if (style.image != undefined) billboard.image = style.image; 126 | if (style.heightReference != undefined) { 127 | let heightReference = 1; 128 | if (this.style.heightReference == true) { 129 | heightReference = 1; 130 | } else { 131 | heightReference = this.style.heightReference; 132 | } 133 | billboard.heightReference = heightReference; 134 | } 135 | if (style.heightReference != undefined) 136 | billboard.heightReference = (style.heightReference == undefined ? 1 : Number(this.style.heightReference)); // 如果直接设置为true 会导致崩溃 137 | if (style.scale != undefined) billboard.scale = Number(style.scale); 138 | if (style.color) { 139 | let color = style.color instanceof Cesium.Color ? style.color : Cesium.Color.fromCssColorString(style.color); 140 | color = color.withAlpha(style.colorAlpha || 1); 141 | billboard.color = color; 142 | } 143 | this.style = Object.assign(this.style, style); 144 | } 145 | 146 | /** 147 | * 获取样式 148 | * @returns {Object} 样式 149 | */ 150 | getStyle() { 151 | let obj = {}; 152 | let billboard = this.entity.billboard; 153 | obj.image = this.style.image; 154 | if (billboard.heightReference) { 155 | let heightReference = billboard.heightReference.getValue(); 156 | obj.heightReference = Number(heightReference); 157 | } 158 | obj.scale = billboard.scale.getValue(); 159 | 160 | if (billboard.color) { 161 | let color = billboard.color.getValue(); 162 | obj.colorAlpha = color.alpha; 163 | obj.color = new Cesium.Color(color.red, color.green, color.blue, 1).toCssHexString(); 164 | } 165 | return obj; 166 | } 167 | 168 | /** 169 | * 开始编辑 170 | */ 171 | startEdit(callback) { 172 | if (this.state == "startEdit" || this.state == "editing" || !this.entity) return; 173 | this.state = "startEdit"; 174 | if (!this.modifyHandler) this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 175 | let that = this; 176 | let editBillboard; 177 | this.modifyHandler.setInputAction(function (evt) { 178 | let pick = that.viewer.scene.pick(evt.position); 179 | if (Cesium.defined(pick) && pick.id) { 180 | editBillboard = pick.id; 181 | that.forbidDrawWorld(true); 182 | } 183 | }, Cesium.ScreenSpaceEventType.LEFT_DOWN); 184 | this.modifyHandler.setInputAction(function (evt) { //移动时绘制线 185 | if (!editBillboard) return; 186 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 187 | if (!cartesian) return; 188 | editBillboard.position.setValue(cartesian.clone()); 189 | that.position = cartesian.clone(); 190 | that.state = "editing"; 191 | if(callback) callback(); 192 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 193 | 194 | this.modifyHandler.setInputAction(function (evt) { //移动时绘制线 195 | if (!editBillboard) return; 196 | that.forbidDrawWorld(false); 197 | if (that.modifyHandler) { 198 | that.modifyHandler.destroy(); 199 | that.modifyHandler = null; 200 | that.state = "editing"; 201 | } 202 | }, Cesium.ScreenSpaceEventType.LEFT_UP); 203 | } 204 | 205 | /** 206 | * 结束编辑 207 | * @param {Function} callback 回调函数 208 | */ 209 | endEdit(callback) { 210 | if (this.modifyHandler) { 211 | this.modifyHandler.destroy(); 212 | this.modifyHandler = null; 213 | if (callback) callback(this.entity); 214 | } 215 | this.state = "endEdit"; 216 | } 217 | createBillboard(cartesian) { 218 | if (!cartesian) return; 219 | let billboard = this.viewer.entities.add({ 220 | position: cartesian, 221 | billboard: { 222 | color: this.style.color ? (this.style.color instanceof Cesium.Color ? this.style.color : Cesium.Color.fromCssColorString(this.style.color).withAlpha(this.style.colorAlpha || 1)) : Cesium.Color.WHITE, 223 | image: this.style.image || "../img/mark4.png", 224 | scale: this.style.scale || 1, 225 | pixelOffset: this.style.pixelOffset, 226 | heightReference: this.style.heightReference == undefined ? 1 : Number(this.style.heightReference), 227 | verticalOrigin: Cesium.VerticalOrigin.BOTTOM 228 | } 229 | }) 230 | billboard.objId = this.objId; 231 | return billboard; 232 | } 233 | 234 | /** 235 | * 移除 236 | */ 237 | remove() { 238 | if (this.entity) { 239 | this.state = "no"; 240 | this.viewer.entities.remove(this.entity); 241 | this.entity = null; 242 | } 243 | } 244 | 245 | 246 | getPositions(isWgs84) { 247 | return isWgs84 ? util.cartesianToLnglat(this.position, this.viewer) : this.position; 248 | } 249 | getLnglats(){ 250 | return this.getPositions(true); 251 | } 252 | /** 253 | * 设置图标坐标 254 | * @param {Cesium.Cartesian3 | Array} p 坐标 255 | */ 256 | setPosition(p) { 257 | let position = null; 258 | if (p instanceof Cesium.Cartesian3) { 259 | position = p; 260 | } else { 261 | position = Cesium.Cartesian3.fromDegrees(p[0], p[1], p[2] || 0); 262 | } 263 | this.entity.position.setValue(position.clone()); 264 | this.position = position.clone(); 265 | } 266 | 267 | } 268 | export default CreateBillboard; -------------------------------------------------------------------------------- /src/js/plot/createGltfModel.js: -------------------------------------------------------------------------------- 1 | import '../prompt/prompt.css' 2 | import Prompt from '../prompt/prompt.js' 3 | import BasePlot from './basePlot'; 4 | import util from '../util'; 5 | 6 | /** 7 | * 小模型(gltf、glb)标绘类 8 | * @class 9 | * @augments BasePlot 10 | * @alias BasePlot.CreateGltfModel 11 | */ 12 | class CreateGltfModel extends BasePlot { 13 | constructor(viewer, style) { 14 | super(viewer, style); 15 | this.type = "gltfModel"; 16 | style = style || {}; 17 | this.viewer = viewer; 18 | if (!style.uri) { 19 | console.warn("请输入模型地址!"); 20 | return; 21 | } 22 | 23 | let defaultStyle = { 24 | heading: 0, 25 | pitch: 0, 26 | roll: 0, 27 | minimumPixelSize: 24, 28 | maximumScale: 120 29 | } 30 | this.style = Object.assign(defaultStyle, style || {}); 31 | /** 32 | * @property {String} modelUri 模型地址 33 | */ 34 | this.modelUri = style.uri; 35 | this.entity = null; 36 | } 37 | 38 | start(callback) { 39 | if (!this.prompt && this.promptStyle.show) this.prompt = new Prompt(this.viewer, this.promptStyle); 40 | this.state = "startCreate"; 41 | let that = this; 42 | if (!this.handler) this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 43 | this.handler.setInputAction(function (evt) { //单击开始绘制 44 | let cartesian = that.getCatesian3FromPX(evt.position, that.viewer); 45 | if (cartesian) { 46 | that.entity.position = cartesian; 47 | that.position = cartesian.clone(); 48 | } 49 | that.endCreate(); 50 | if (callback) callback(that.entity); 51 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 52 | this.handler.setInputAction(function (evt) { //单击开始绘制 53 | that.prompt.update(evt.endPosition, "单击新增"); 54 | that.state = "creating"; 55 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer, [that.entity]); 56 | if (!cartesian) return; 57 | if (!that.entity) { 58 | that.entity = that.createGltfModel(cartesian.clone()); 59 | } else { 60 | that.entity.position = cartesian; 61 | } 62 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 63 | } 64 | createByPositions(lnglatArr, callback) { 65 | if (!lnglatArr) return; 66 | this.state = "startCreate"; 67 | if (lnglatArr instanceof Cesium.Cartesian3) { 68 | this.position = lnglatArr; 69 | } else { 70 | this.position = Cesium.Cartesian3.fromDegrees(lnglatArr[0], lnglatArr[1], lnglatArr[2] || 0); 71 | } 72 | this.entity = this.createGltfModel(this.position); 73 | callback(this.entity); 74 | this.state = "endCreate"; 75 | } 76 | startEdit(callback) { 77 | if (this.state == "startEdit" || this.state == "editing") return; //表示还没绘制完成 78 | if (!this.modifyHandler) this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 79 | let that = this; 80 | let eidtModel; 81 | this.state = "startEdit"; 82 | this.modifyHandler.setInputAction(function (evt) { 83 | let pick = that.viewer.scene.pick(evt.position); 84 | if (Cesium.defined(pick) && pick.id) { 85 | eidtModel = pick.id; 86 | that.forbidDrawWorld(true); 87 | } 88 | }, Cesium.ScreenSpaceEventType.LEFT_DOWN); 89 | this.modifyHandler.setInputAction(function (evt) { 90 | if (!eidtModel) return; 91 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer, [that.entity]); 92 | if (!cartesian) return; 93 | if (that.entity) { 94 | that.entity.position.setValue(cartesian); 95 | that.position = cartesian.clone(); 96 | } 97 | that.state = "editing"; 98 | if(callback) callback(); 99 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 100 | 101 | this.modifyHandler.setInputAction(function (evt) { 102 | if (!eidtModel) return; 103 | that.forbidDrawWorld(false); 104 | if (that.modifyHandler) { 105 | that.modifyHandler.destroy(); 106 | that.modifyHandler = null; 107 | } 108 | that.state = "editing"; 109 | }, Cesium.ScreenSpaceEventType.LEFT_UP); 110 | } 111 | 112 | endCreate() { 113 | let that = this; 114 | that.state = "endCreate"; 115 | if (that.handler) { 116 | that.handler.destroy(); 117 | that.handler = null; 118 | } 119 | if (that.prompt) { 120 | that.prompt.destroy(); 121 | that.prompt = null; 122 | } 123 | } 124 | 125 | /** 126 | * 当前步骤结束 127 | */ 128 | done() { 129 | if (this.state == "startCreate") { 130 | this.destroy(); 131 | } else if (this.state == "creating") { 132 | this.destroy(); 133 | } else if (this.state == "startEdit" || this.state == "editing") { 134 | this.endEdit(); 135 | } else { 136 | 137 | } 138 | } 139 | 140 | endEdit(callback) { 141 | if (this.modifyHandler) { 142 | this.modifyHandler.destroy(); 143 | this.modifyHandler = null; 144 | if (callback) callback(this.entity); 145 | } 146 | this.forbidDrawWorld(false); 147 | this.state = "endEdit"; 148 | } 149 | createGltfModel(cartesian) { 150 | if (!cartesian) return; 151 | let heading = Cesium.Math.toRadians(this.style.heading); 152 | let pitch = Cesium.Math.toRadians(this.style.pitch); 153 | let roll = Cesium.Math.toRadians(this.style.roll); 154 | let hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll); 155 | let orientation = Cesium.Transforms.headingPitchRollQuaternion(cartesian, hpr); 156 | 157 | let entity = this.viewer.entities.add({ 158 | position: cartesian, 159 | orientation: orientation, 160 | model: { 161 | uri: this.modelUri, 162 | minimumPixelSize: this.style.minimumPixelSize, 163 | maximumScale: this.style.maximumScale, 164 | scale: this.style.scale || 1, 165 | heightReference: this.style.heightReference 166 | } 167 | }); 168 | entity.objId = this.objId; 169 | return entity; 170 | } 171 | getPositions(isWgs84) { 172 | return isWgs84 ? util.cartesianToLnglat(this.position, this.viewer) : this.position 173 | } 174 | getStyle() { 175 | let obj = {}; 176 | let model = this.entity.model; 177 | obj.minimumPixelSize = model.minimumPixelSize.getValue(); 178 | let orientation = this.entity.orientation.getValue(); 179 | let p = this.entity.position.getValue(this.viewer.clock.currentTime); 180 | let hpr = util.oreatationToHpr(p.clone(), orientation, true) || {}; 181 | obj.heading = (hpr.heading || 0) < 360 ? (hpr.heading + 360) : hpr.heading; 182 | obj.pitch = hpr.pitch || 0; 183 | obj.roll = hpr.roll || 0; 184 | obj.scale = model.scale.getValue(); 185 | obj.uri = model.uri.getValue(); 186 | 187 | let heightReference = this.entity.heightReference && this.entity.heightReference.getValue(); 188 | if(heightReference!=undefined) obj.heightReference = Number(heightReference); 189 | return obj; 190 | } 191 | setStyle(style) { 192 | if (!style) return; 193 | this.setOrientation(style.heading, style.pitch, style.roll); 194 | this.entity.model.scale.setValue(style.scale == undefined ? 1 : style.scale); 195 | if (style.uri) this.entity.model.uri.setValue(style.uri); 196 | if (style.heightReference != undefined) this.entity.model.heightReference.setValue(Number(style.heightReference)); 197 | this.style = Object.assign(this.style, style); 198 | } 199 | 200 | /** 201 | * 设置模型姿态 202 | * @param {Number} h 偏转角 203 | * @param {Number} p 仰俯角 204 | * @param {Number} r 翻滚角 205 | */ 206 | setOrientation(h, p, r) { 207 | h = h || 0; 208 | p = p || 0; 209 | r = r || 0; 210 | this.style.heading = h; 211 | this.style.pitch = p; 212 | this.style.roll = r; 213 | var heading = Cesium.Math.toRadians(h || 0); 214 | var pitch = Cesium.Math.toRadians(p || 0); 215 | var roll = Cesium.Math.toRadians(r || 0); 216 | var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll); 217 | var position = this.entity.position._value; 218 | var orientation = Cesium.Transforms.headingPitchRollQuaternion( 219 | position, 220 | hpr 221 | ); 222 | if (this.entity) this.entity.orientation = orientation; 223 | } 224 | 225 | remove() { 226 | if (this.entity) { 227 | this.state = "no"; 228 | this.viewer.entities.remove(this.entity); 229 | this.entity = null; 230 | } 231 | } 232 | 233 | destroy() { 234 | if (this.handler) { 235 | this.handler.destroy(); 236 | this.handler = null; 237 | } 238 | if (this.modifyHandler) { 239 | this.modifyHandler.destroy(); 240 | this.modifyHandler = null; 241 | } 242 | if (this.entity) { 243 | this.viewer.entities.remove(this.entity); 244 | this.entity = null; 245 | } 246 | this.style = null; 247 | if (this.prompt) { 248 | this.prompt.destroy(); 249 | this.prompt = null; 250 | } 251 | } 252 | 253 | } 254 | 255 | export default CreateGltfModel; -------------------------------------------------------------------------------- /src/js/plot/createRectangle.js: -------------------------------------------------------------------------------- 1 | //绘制矩形 2 | import '../prompt/prompt.css' 3 | import Prompt from '../prompt/prompt.js' 4 | import BasePlot from './basePlot'; 5 | 6 | /** 7 | * 矩形标绘类 8 | * @class 9 | * @augments BasePlot 10 | * @alias BasePlot.BasePlot 11 | */ 12 | class CreateRectangle extends BasePlot { 13 | constructor(viewer, style) { 14 | super(viewer, style); 15 | this.type = "rectangle"; 16 | this.viewer = viewer; 17 | this.style = style; 18 | 19 | /** 20 | * @property {Cesium.Entity} rightdownPoint 右下角实体点 21 | */ 22 | this.rightdownPoint = null; 23 | 24 | /** 25 | * @property {Cesium.Entity} leftupPoint 左上角实体点 26 | */ 27 | this.leftupPoint = null; 28 | 29 | /** 30 | * @property {Cesium.Cartesian3} leftup 左上角点坐标 31 | */ 32 | this.leftup = null; 33 | 34 | /** 35 | * @property {Cesium.Cartesian3} rightdown 右下角点坐标 36 | */ 37 | this.rightdown = null; 38 | 39 | this.modifyPoint = null; 40 | this.pointArr = []; 41 | } 42 | start(callback) { 43 | if (!this.prompt && this.promptStyle.show) this.prompt = new Prompt(this.viewer, this.promptStyle); 44 | this.state = "startCreate"; 45 | let that = this; 46 | if (!this.handler) this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 47 | this.handler.setInputAction(function (evt) { //单击开始绘制 48 | let cartesian = that.getCatesian3FromPX(evt.position, that.viewer, []); 49 | if (!cartesian) return; 50 | if (!that.leftupPoint) { 51 | that.leftup = cartesian; 52 | that.leftupPoint = that.createPoint(cartesian); 53 | that.leftupPoint.typeAttr = "leftup"; 54 | that.rightdownPoint = that.createPoint(cartesian.clone()); 55 | that.rightdown = cartesian.clone(); 56 | that.rightdownPoint.typeAttr = "rightdown"; 57 | that.entity = that.createRectangle(); 58 | } else { 59 | if (!that.entity) { 60 | return; 61 | } 62 | that.endCreate(); 63 | if (callback) callback(that.entity); 64 | } 65 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 66 | this.handler.setInputAction(function (evt) { //移动时绘制线 67 | if (!that.leftupPoint) { 68 | that.prompt.update(evt.endPosition, "单击开始绘制"); 69 | that.state = "startCreate"; 70 | return; 71 | } 72 | that.prompt.update(evt.endPosition, "单击结束"); 73 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer, []); 74 | if (!cartesian) return; 75 | if (that.rightdownPoint) { 76 | that.rightdownPoint.position.setValue(cartesian); 77 | that.rightdown = cartesian.clone(); 78 | that.state = "creating"; 79 | } 80 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 81 | } 82 | 83 | endCreate() { 84 | let that = this; 85 | if (that.handler) { 86 | that.handler.destroy(); 87 | that.handler = null; 88 | } 89 | if (that.rightdownPoint) that.rightdownPoint.show = false; 90 | if (that.leftupPoint) that.leftupPoint.show = false; 91 | if (that.prompt) { 92 | that.prompt.destroy(); 93 | that.prompt = null; 94 | } 95 | that.state = "endCreate"; 96 | } 97 | 98 | /** 99 | * 当前步骤结束 100 | */ 101 | done() { 102 | if (this.state == "startCreate") { 103 | this.destroy(); 104 | } else if (this.state == "creating") { 105 | this.destroy(); 106 | } else if (this.state == "startEdit" || this.state == "editing") { 107 | this.endEdit(); 108 | } else { 109 | 110 | } 111 | } 112 | 113 | startEdit(callback) { 114 | if (this.state == "startEdit" || this.state == "editing" || !this.entity) return; 115 | this.state = "startEdit"; 116 | if (!this.modifyHandler) this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 117 | let that = this; 118 | if (that.rightdownPoint) that.rightdownPoint.show = true; 119 | if (that.leftupPoint) that.leftupPoint.show = true; 120 | this.modifyHandler.setInputAction(function (evt) { 121 | if (!that.entity) return; 122 | let pick = that.viewer.scene.pick(evt.position); 123 | if (Cesium.defined(pick) && pick.id) { 124 | if (!pick.id.objId) 125 | that.modifyPoint = pick.id; 126 | that.forbidDrawWorld(true); 127 | } 128 | }, Cesium.ScreenSpaceEventType.LEFT_DOWN); 129 | this.modifyHandler.setInputAction(function (evt) { 130 | if (!that.modifyPoint) return; 131 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer, [that.entity, that.modifyPoint]); 132 | if (!cartesian) { 133 | return; 134 | } 135 | that.state == "editing"; 136 | if (that.modifyPoint.typeAttr == "leftup") { 137 | that.leftup = cartesian 138 | that.leftupPoint.position.setValue(that.leftup); 139 | that.entity.position.setValue(that.leftup); 140 | } else { 141 | that.rightdown = cartesian 142 | that.rightdownPoint.position.setValue(that.rightdown); 143 | } 144 | if(callback) callback(); 145 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 146 | 147 | this.modifyHandler.setInputAction(function (evt) { 148 | if (!that.modifyPoint) return; 149 | that.modifyPoint = null; 150 | that.forbidDrawWorld(false); 151 | that.state == "editing"; 152 | }, Cesium.ScreenSpaceEventType.LEFT_UP); 153 | } 154 | endEdit(callback) { 155 | if (this.rightdownPoint) this.rightdownPoint.show = false; 156 | if (this.leftupPoint) this.leftupPoint.show = false; 157 | if (this.modifyHandler) { 158 | this.modifyHandler.destroy(); 159 | this.modifyHandler = null; 160 | if (callback) callback(this.entity); 161 | } 162 | this.forbidDrawWorld(false); 163 | this.state = "endEdit"; 164 | } 165 | 166 | createRectangle() { 167 | let that = this; 168 | let rectangle = this.viewer.entities.add({ 169 | rectangle: { 170 | coordinates: new Cesium.CallbackProperty(function () { 171 | return Cesium.Rectangle.fromCartesianArray([that.leftup, that.rightdown]) 172 | }, false), 173 | heightReference: this.style.heightReference || 0, 174 | show: true, 175 | fill: this.style.fill || true, 176 | material: this.style.color instanceof Cesium.Color ? this.style.color : (this.style.color ? Cesium.Color.fromCssColorString(this.style.color).withAlpha(this.style.colorAlpha || 1) : Cesium.Color.WHITE), 177 | outlineColor: this.style.outlineColor instanceof Cesium.Color ? this.style.outlineColor : (this.style.outlineColor ? Cesium.Color.fromCssColorString(this.style.outlineColor).withAlpha(this.style.outlineColorAlpha || 1) : Cesium.Color.BLACK), 178 | outlineWidth: 1, 179 | outline: this.style.outline, 180 | } 181 | }); 182 | rectangle.objId = this.objId; 183 | return rectangle; 184 | } 185 | getPositions(isWgs84) { 186 | let positions = []; 187 | if (isWgs84) { 188 | positions = util.cartesiansToLnglats([this.leftup, this.rightdown],this.viewer); 189 | } else { 190 | positions = [this.leftup, this.rightdown]; 191 | } 192 | return positions; 193 | } 194 | getStyle() { 195 | let obj = {}; 196 | let rectangle = this.entity.rectangle; 197 | let color = rectangle.material.color.getValue(); 198 | obj.colorAlpha = color.alpha; 199 | obj.color = new Cesium.Color(color.red, color.green, color.blue, 1).toCssHexString(); 200 | if (rectangle.outline) obj.outline = rectangle.outline.getValue(); 201 | obj.outlineWidth = rectangle.outlineWidth._value; 202 | let outlineColor = rectangle.outlineColor.getValue(); 203 | obj.outlineColorAlpha = outlineColor.alpha; 204 | obj.outlineColor = new Cesium.Color(outlineColor.red, outlineColor.green, outlineColor.blue, 1).toCssHexString(); 205 | if (obj.height) obj.height = rectangle.height.getValue(); 206 | if (rectangle.fill) obj.fill = rectangle.fill.getValue(); 207 | obj.heightReference = rectangle.heightReference.getValue(); 208 | return obj; 209 | } 210 | setStyle(style) { 211 | if (!style) return; 212 | let color = style.color instanceof Cesium.Color ? style.color : Cesium.Color.fromCssColorString(style.color || "#ffff00"); 213 | if (style.colorAlpha) color = color.withAlpha(style.colorAlpha); 214 | this.entity.rectangle.material = color; 215 | this.entity.rectangle.outline = style.outline; 216 | this.entity.rectangle.outlineWidth = style.outlineWidth; 217 | 218 | let outlineColor = style.outlineColor instanceof Cesium.Color ? style.outlineColor : Cesium.Color.fromCssColorString(style.outlineColor || "#000000"); 219 | if (style.outlineColorAlpha) outlineColor = outlineColor.withAlpha(style.outlineColorAlpha) 220 | this.entity.rectangle.outlineColor = outlineColor; 221 | 222 | this.entity.rectangle.heightReference = Number(style.heightReference); 223 | if (style.heightReference == 0) { 224 | this.entity.rectangle.height = Number(style.height); 225 | this.updatePointHeight(style.height); 226 | } 227 | this.entity.rectangle.fill = Boolean(style.fill); 228 | this.style = Object.assign(this.style, style); 229 | } 230 | } 231 | 232 | export default CreateRectangle; -------------------------------------------------------------------------------- /src/js/plot/createLabel.js: -------------------------------------------------------------------------------- 1 | import '../prompt/prompt.css' 2 | import Prompt from '../prompt/prompt.js' 3 | import BasePlot from './basePlot'; 4 | import util from "../util"; 5 | /** 6 | * 文字标绘类 7 | * @class 8 | * @augments BasePlot 9 | * @alias BasePlot.CreateLabel 10 | */ 11 | class CreateLabel extends BasePlot { 12 | constructor(viewer, style) { 13 | super(viewer, style); 14 | this.type = "label"; 15 | this.viewer = viewer; 16 | this.style = style; 17 | /** 18 | * @property {Cesium.Cartesian3} 坐标 19 | */ 20 | this.position = null; 21 | } 22 | 23 | 24 | start(callback) { 25 | if (!this.prompt && this.promptStyle.show) 26 | this.prompt = new Prompt(this.viewer, this.promptStyle); 27 | let that = this; 28 | this.state = "startCreate"; 29 | if (!this.handler) this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 30 | this.handler.setInputAction(function (evt) { 31 | //单击开始绘制 32 | let cartesian = that.getCatesian3FromPX(evt.position, that.viewer); 33 | if (!cartesian) return; 34 | that.entity = that.createLabel(cartesian.clone()); 35 | that.position = cartesian.clone(); 36 | that.endCreate(); 37 | if (callback) callback(that.entity); 38 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 39 | 40 | this.handler.setInputAction(function (evt) { 41 | //单击开始绘制 42 | that.prompt.update(evt.endPosition, "单击新增"); 43 | that.state = "creating"; 44 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 45 | } 46 | 47 | endCreate() { 48 | let that = this; 49 | if (that.handler) { 50 | that.handler.destroy(); 51 | that.handler = null; 52 | } 53 | if (that.prompt) { 54 | that.prompt.destroy(); 55 | that.prompt = null; 56 | } 57 | that.state = "endCreate"; 58 | } 59 | 60 | /** 61 | * 当前步骤结束 62 | */ 63 | done() { 64 | if (this.state == "startCreate") { 65 | this.destroy(); 66 | } else if (this.state == "creating") { 67 | this.destroy(); 68 | } else if (this.state == "startEdit" || this.state == "editing") { 69 | this.endEdit(); 70 | } else { 71 | 72 | } 73 | } 74 | 75 | createByPositions(lnglatArr, callback) { 76 | if (!lnglatArr) return; 77 | this.state = "startCreate"; 78 | let position = 79 | lnglatArr instanceof Cesium.Cartesian3 80 | ? lnglatArr 81 | : Cesium.Cartesian3.fromDegrees( 82 | lnglatArr[0], 83 | lnglatArr[1], 84 | lnglatArr[2] 85 | ); 86 | this.position = position; 87 | if (!position) return; 88 | this.entity = this.createLabel(position, this.style.text); 89 | if (callback) callback(this.entity); 90 | this.state = "endCreate"; 91 | } 92 | 93 | // 设置相关样式 94 | setStyle(style) { 95 | if (!style) return; 96 | if (style.fillColor) { 97 | let fillColor = 98 | style.fillColor instanceof Cesium.Color 99 | ? style.fillColor 100 | : Cesium.Color.fromCssColorString(style.fillColor || "#ffff00"); 101 | fillColor = fillColor.withAlpha(style.fillColorAlpha || 1); 102 | this.entity.label.fillColor = fillColor; 103 | } 104 | 105 | this.entity.label.outlineWidth = style.outlineWidth; 106 | if (style.backgroundColor) { 107 | let backgroundColor = 108 | style.backgroundColor instanceof Cesium.Color 109 | ? style.backgroundColor 110 | : Cesium.Color.fromCssColorString(style.backgroundColor || "#000000"); 111 | backgroundColor = backgroundColor.withAlpha( 112 | style.backgroundColorAlpha || 1 113 | ); 114 | this.entity.label.backgroundColor = backgroundColor; 115 | } 116 | 117 | if (style.outlineColor) { 118 | let outlineColor = 119 | style.outlineColor instanceof Cesium.Color 120 | ? style.outlineColor 121 | : Cesium.Color.fromCssColorString(style.outlineColor || "#000000"); 122 | outlineColor = outlineColor.withAlpha( 123 | style.outlineColorAlpha || 1 124 | ); 125 | this.entity.label.outlineColor = outlineColor; 126 | } 127 | 128 | if (style.heightReference != undefined) 129 | this.entity.label.heightReference = Number(style.heightReference); 130 | if (style.pixelOffset) this.entity.label.pixelOffset = style.pixelOffset; 131 | 132 | if (style.text) this.entity.label.text = style.text; 133 | 134 | if (style.showBackground != undefined) 135 | this.entity.label.showBackground = Boolean(style.showBackground); 136 | 137 | if (style.scale) { 138 | this.entity.label.scale = Number(style.scale); 139 | } 140 | 141 | 142 | this.style = Object.assign(this.style, style); 143 | } 144 | // 获取相关样式 145 | getStyle() { 146 | let obj = {}; 147 | let label = this.entity.label; 148 | 149 | let fillColor = label.fillColor.getValue(); 150 | obj.fillColorAlpha = fillColor.alpha; 151 | obj.fillColor = new Cesium.Color( 152 | fillColor.red, 153 | fillColor.green, 154 | fillColor.blue, 155 | 1 156 | ).toCssHexString(); 157 | 158 | if (label.outlineWidth != undefined) obj.outlineWidth = label.outlineWidth._value; 159 | if (label.showBackground != undefined) obj.showBackground = Boolean(label.showBackground.getValue()); 160 | if (label.backgroundColor) { 161 | let bkColor = label.backgroundColor.getValue(); 162 | obj.backgroundColorAlpha = bkColor.alpha; 163 | obj.backgroundColor = new Cesium.Color(bkColor.red, bkColor.green, bkColor.blue, 1).toCssHexString(); 164 | } 165 | 166 | 167 | if (label.outlineColor) { 168 | let outlineColor = label.outlineColor.getValue(); 169 | obj.outlineColorAlpha = outlineColor.alpha; 170 | obj.outlineColor = new Cesium.Color(outlineColor.red, outlineColor.green, outlineColor.blue, 1).toCssHexString(); 171 | } 172 | 173 | if (label.heightReference != undefined) { 174 | obj.heightReference = label.heightReference.getValue(); 175 | } 176 | 177 | if (label.pixelOffset) obj.pixelOffset = label.pixelOffset.getValue(); 178 | 179 | if (label.scale) obj.scale = label.scale.getValue(); 180 | 181 | obj.text = label.text.getValue(); 182 | 183 | 184 | return obj; 185 | } 186 | getPositions(isWgs84) { 187 | return isWgs84 ? util.cartesianToLnglat(this.position) : this.position; 188 | } 189 | 190 | startEdit(callback) { 191 | if (this.state == "startEdit" || this.state == "editing" || !this.entity) 192 | return; 193 | this.state = "startEdit"; 194 | if (!this.modifyHandler) 195 | this.modifyHandler = new Cesium.ScreenSpaceEventHandler( 196 | this.viewer.scene.canvas 197 | ); 198 | let that = this; 199 | let editLabel; 200 | this.modifyHandler.setInputAction(function (evt) { 201 | let pick = that.viewer.scene.pick(evt.position); 202 | if (Cesium.defined(pick) && pick.id) { 203 | editLabel = pick.id; 204 | that.forbidDrawWorld(true); 205 | } 206 | }, Cesium.ScreenSpaceEventType.LEFT_DOWN); 207 | this.modifyHandler.setInputAction(function (evt) { 208 | if (!editLabel) return; 209 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 210 | if (!cartesian) return; 211 | if (that.entity) { 212 | that.entity.position.setValue(cartesian); 213 | that.position = cartesian; 214 | that.state = "editing"; 215 | } 216 | if (callback) callback(); 217 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 218 | 219 | this.modifyHandler.setInputAction(function (evt) { 220 | if (!editLabel) return; 221 | that.forbidDrawWorld(false); 222 | if (that.modifyHandler) { 223 | that.modifyHandler.destroy(); 224 | that.modifyHandler = null; 225 | that.state = "editing"; 226 | } 227 | }, Cesium.ScreenSpaceEventType.LEFT_UP); 228 | } 229 | endEdit(callback) { 230 | if (this.modifyHandler) { 231 | this.modifyHandler.destroy(); 232 | this.modifyHandler = null; 233 | if (callback) callback(this.entity); 234 | } 235 | this.forbidDrawWorld(false); 236 | this.state = "endEdit"; 237 | } 238 | createLabel(cartesian) { 239 | if (!cartesian) return; 240 | let label = this.viewer.entities.add({ 241 | position: cartesian, 242 | label: { 243 | text: this.style.text || "--", 244 | fillColor: this.style.fillColor 245 | ? Cesium.Color.fromCssColorString(this.style.fillColor).withAlpha( 246 | this.style.fillColorAlpha || 1 247 | ) 248 | : Cesium.Color.WHITE, 249 | backgroundColor: this.style.backgroundColor 250 | ? Cesium.Color.fromCssColorString( 251 | this.style.backgroundColor 252 | ).withAlpha(this.style.backgroundColorAlpha || 1) 253 | : Cesium.Color.WHITE, 254 | style: Cesium.LabelStyle.FILL, 255 | outlineWidth: this.style.outlineWidth || 4, 256 | scale: this.style.scale || 1, 257 | pixelOffset: this.style.pixelOffset || Cesium.Cartesian2.ZERO, 258 | showBackground: this.style.showBackground, 259 | heightReference: this.style.heightReference || 0, 260 | disableDepthTestDistance: Number.MAX_VALUE 261 | }, 262 | }); 263 | label.objId = this.objId; 264 | return label; 265 | } 266 | 267 | }; 268 | 269 | export default CreateLabel; 270 | -------------------------------------------------------------------------------- /src/js/plot/createPolyline.js: -------------------------------------------------------------------------------- 1 | // 绘制线 2 | import BasePlot from "./basePlot"; 3 | import '../prompt/prompt.css' 4 | import Prompt from '../prompt/prompt.js' 5 | /* import animate from "../material/animate" */ // 动态材质 6 | // 注册自定义材质 7 | /** 8 | * 线标绘类 9 | * @class 10 | * @augments BasePlot 11 | * @alias BasePlot.CreatePolyline 12 | */ 13 | class CreatePolyline extends BasePlot { 14 | constructor(viewer, style) { 15 | super(viewer, style); 16 | style = style || {}; 17 | this.movePush = false; 18 | this.type = "polyline"; 19 | /** 20 | * @property {Number} [maxPointNum=Number.MAX_VALUE] 线的最大点位数量 21 | */ 22 | this.maxPointNum = style.maxPointNum || Number.MAX_VALUE; // 最多点数 23 | } 24 | 25 | /** 26 | * 开始绘制 27 | * @param {Function} callback 绘制完成之后的回调函数 28 | */ 29 | start(callback) { 30 | if (!this.prompt && this.promptStyle.show) this.prompt = new Prompt(this.viewer, this.promptStyle); 31 | this.state = "startCreate"; 32 | let that = this; 33 | if (!this.handler) this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 34 | this.handler.setInputAction(function (evt) { //单击开始绘制 35 | let cartesian = that.getCatesian3FromPX(evt.position, that.viewer, [that.entity]); 36 | if (!cartesian) return; 37 | if (that.movePush) { 38 | that.positions.pop(); 39 | that.movePush = false; 40 | } 41 | that.positions.push(cartesian); 42 | let point = that.createPoint(cartesian); 43 | point.wz = that.positions.length - 1; 44 | that.controlPoints.push(point); 45 | 46 | // 达到最大数量 结束绘制 47 | if (that.positions.length == that.maxPointNum) { 48 | that.endCreate(); 49 | if (callback) callback(that.entity); 50 | } 51 | 52 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 53 | 54 | this.handler.setInputAction(function (evt) { //移动时绘制线 55 | that.state = "creating"; 56 | if (that.positions.length < 1) { 57 | that.prompt.update(evt.endPosition, "单击开始绘制"); 58 | that.state = "startCreate"; 59 | return; 60 | } 61 | that.prompt.update(evt.endPosition, "右键取消上一步,双击结束"); 62 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer, [that.entity]); 63 | if (!cartesian) return; 64 | 65 | if (!that.movePush) { 66 | that.positions.push(cartesian); 67 | that.movePush = true; 68 | } else { 69 | that.positions[that.positions.length - 1] = cartesian; 70 | } 71 | 72 | if (that.positions.length == 2) { 73 | if (!Cesium.defined(that.entity)) { 74 | that.entity = that.createPolyline(); 75 | } 76 | } 77 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 78 | 79 | this.handler.setInputAction(function (evt) { //右键取消上一步 80 | if (!that.entity) { 81 | return; 82 | } 83 | that.positions.splice(that.positions.length - 2, 1); 84 | that.viewer.entities.remove(that.controlPoints.pop()) 85 | if (that.positions.length == 1) { 86 | if (that.entity) { 87 | that.viewer.entities.remove(that.entity); 88 | that.entity = null; 89 | } 90 | that.prompt.update(evt.endPosition, "单击开始绘制"); 91 | that.movePush = false; 92 | that.positions = []; 93 | } 94 | }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); 95 | 96 | this.handler.setInputAction(function (evt) { //双击结束绘制 97 | if (!that.entity) { 98 | return; 99 | } 100 | that.endCreate(); 101 | if (callback) callback(that.entity); 102 | }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); 103 | } 104 | 105 | endCreate() { 106 | let that = this; 107 | that.state = "endCreate"; 108 | if (that.handler) { 109 | that.handler.destroy(); 110 | that.handler = null; 111 | } 112 | that.positions.pop(); 113 | that.viewer.entities.remove(that.controlPoints.pop()) 114 | if (that.prompt) { 115 | that.prompt.destroy(); 116 | that.prompt = null; 117 | } 118 | that.viewer.trackedEntity = undefined; 119 | that.viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); 120 | } 121 | 122 | /** 123 | * 当前步骤结束 124 | */ 125 | done() { 126 | if (this.state == "startCreate") { 127 | this.destroy(); 128 | } else if (this.state == "creating") { 129 | if (this.positions.length <= 2 && this.movePush == true) { 130 | this.destroy(); 131 | } else { 132 | this.endCreate(); 133 | } 134 | } else if (this.state == "startEdit" || this.state == "editing") { 135 | this.endEdit(); 136 | } else { 137 | 138 | } 139 | } 140 | 141 | createByPositions(lnglatArr, callback) { //通过传入坐标数组创建面 142 | if (!lnglatArr || lnglatArr.length < 1) return; 143 | this.state = "startCreate"; 144 | let positions = (lnglatArr[0] instanceof Cesium.Cartesian3) ? lnglatArr : util.lnglatsToCartesians(lnglatArr); 145 | if (!positions) return; 146 | this.entity = this.createPolyline(this.style); 147 | this.positions = positions; 148 | if (callback) callback(this.entity); 149 | for (let i = 0; i < positions.length; i++) { 150 | let newP = positions[i]; 151 | 152 | let point = this.createPoint(newP); 153 | if (this.style.clampToGround) { 154 | point.point.heightReference = 1; 155 | } 156 | point.wz = this.controlPoints.length; 157 | this.controlPoints.push(point); 158 | } 159 | this.state = "endCreate"; 160 | } 161 | 162 | setStyle(style) { 163 | if (!style) return; 164 | 165 | let material = this.getMaterial(style.material, style); 166 | this.entity.polyline.material = material; 167 | this.entity.polyline.clampToGround = Boolean(style.clampToGround); 168 | if (style.width) this.entity.polyline.width = style.width || 3; 169 | this.style = Object.assign(this.style, style); 170 | } 171 | // 获取相关样式 172 | getStyle() { 173 | if (!this.entity) return; 174 | let obj = {}; 175 | let polyline = this.entity.polyline; 176 | if (this.style.animateType != undefined) { 177 | obj.animateType = this.style.animateType; 178 | obj.image = this.style.image; 179 | obj.duration = this.style.duration; 180 | } 181 | if (polyline.material instanceof Cesium.ColorMaterialProperty) { 182 | obj.material = "common"; 183 | } else { 184 | obj.material = "flowline"; 185 | if (polyline.material instanceof animate.FlowLineMaterial) { 186 | } 187 | obj.duration = polyline.material._duration; 188 | obj.image = polyline.material.url; 189 | } 190 | 191 | let color = polyline.material.color.getValue(); 192 | obj.colorAlpha = color.alpha; 193 | obj.color = new Cesium.Color(color.red, color.green, color.blue, 1).toCssHexString(); 194 | obj.width = polyline.width._value; 195 | let clampToGround = polyline.clampToGround ? polyline.clampToGround.getValue() : false; 196 | obj.clampToGround = Boolean(clampToGround); 197 | return obj; 198 | } 199 | 200 | createPolyline() { 201 | let that = this; 202 | 203 | let polyline = this.viewer.entities.add({ 204 | polyline: { 205 | positions: new Cesium.CallbackProperty(function () { 206 | return that.positions 207 | }, false), 208 | show: true, 209 | material: this.getMaterial(this.style.animateType, this.style), 210 | width: this.style.width || 3, 211 | clampToGround: this.style.clampToGround 212 | } 213 | }); 214 | polyline.objId = this.objId; // 此处进行和entityObj进行关联 215 | return polyline; 216 | } 217 | 218 | getMaterial(animateType, style) { 219 | // 构建多种材质的线 220 | style = style || {}; 221 | let material = null; 222 | let color = style.color || Cesium.Color.WHITE; 223 | color = color instanceof Cesium.Color ? color : Cesium.Color.fromCssColorString(style.color); 224 | color = color.withAlpha(style.colorAlpha || 1); 225 | if (animateType == "flowline") { 226 | /* if (!style.image) { 227 | console.log("动态材质,缺少纹理图片"); 228 | return color; 229 | } 230 | material = new animate.FlowLine({ 231 | color: color, // 默认颜色 232 | image: style.image, 233 | duration: style.duration || 5000 234 | }) */ 235 | } else if (animateType == "flyline") { 236 | /* if (!style.image) { 237 | console.log("动态材质,缺少纹理图片"); 238 | return color; 239 | } 240 | material = new animate.FlyLine({ //动画线材质 241 | color: color, 242 | duration: style.duration || 3000, 243 | image: style.image, 244 | repeat: new Cesium.Cartesian2(1, 1) //平铺 245 | }) */ 246 | } else { 247 | material = color; 248 | } 249 | return material; 250 | } 251 | 252 | } 253 | export default CreatePolyline; 254 | -------------------------------------------------------------------------------- /src/js/plot/createPolygon.js: -------------------------------------------------------------------------------- 1 | import '../prompt/prompt.css' 2 | import Prompt from '../prompt/prompt.js' 3 | import BasePlot from './basePlot' 4 | import util from '../util'; 5 | 6 | /** 7 | * 面标绘类 8 | * @class 9 | * @augments BasePlot 10 | * @alias BasePlot.CreatePolygon 11 | */ 12 | class CreatePolygon extends BasePlot { 13 | constructor(viewer, style) { 14 | super(viewer, style); 15 | this.type = "polygon"; 16 | this.viewer = viewer; 17 | this.entity = null; 18 | this.polyline = null; 19 | let defaultStyle = { 20 | outlineColor: "#000000", 21 | outlineWidth: 2 22 | } 23 | this.style = Object.assign(defaultStyle, style || {}); 24 | this.outline = null; 25 | } 26 | 27 | start(callback) { 28 | if (!this.prompt && this.promptStyle.show) this.prompt = new Prompt(this.viewer, this.promptStyle); 29 | this.state = "startCreate"; 30 | let that = this; 31 | if (!this.handler) this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 32 | this.handler.setInputAction(function (evt) { //单击开始绘制 33 | let cartesian = that.getCatesian3FromPX(evt.position, that.viewer, []); 34 | if (!cartesian) return; 35 | 36 | if (that.movePush) { 37 | that.positions.pop(); 38 | that.movePush = false; 39 | } 40 | that.positions.push(cartesian); 41 | let point = that.createPoint(cartesian); 42 | point.wz = that.positions.length - 1; 43 | that.controlPoints.push(point); 44 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 45 | this.handler.setInputAction(function (evt) { //移动时绘制面 46 | if (that.positions.length < 1) { 47 | that.prompt.update(evt.endPosition, "单击开始绘制"); 48 | that.state = "startCreate"; 49 | return; 50 | } 51 | if (that.prompt) that.prompt.update(evt.endPosition, "双击结束,右键取消上一步"); 52 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer, []); 53 | if (that.positions.length >= 1) { 54 | that.state = "creating"; 55 | if (!that.movePush) { 56 | that.positions.push(cartesian); 57 | that.movePush = true; 58 | } else { 59 | that.positions[that.positions.length - 1] = cartesian; 60 | } 61 | if (that.positions.length == 2) { 62 | if (!Cesium.defined(that.polyline)) { 63 | that.polyline = that.createPolyline(); 64 | } 65 | } 66 | if (that.positions.length == 3) { 67 | if (!Cesium.defined(that.entity)) { 68 | that.entity = that.createPolygon(that.style); 69 | if (!that.style.outline && that.polyline) { // 不需要创建轮廓 则后续删除 70 | that.polyline.show = false; 71 | } 72 | that.entity.objId = that.objId; 73 | } 74 | } 75 | } 76 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 77 | 78 | this.handler.setInputAction(function (evt) { 79 | if (!that.entity) return; 80 | that.positions.splice(that.positions.length - 2, 1); 81 | that.viewer.entities.remove(that.controlPoints.pop()); 82 | if (that.positions.length == 2) { 83 | if (that.entity) { 84 | that.viewer.entities.remove(that.entity); 85 | that.entity = null; 86 | if (that.polyline) that.polyline.show = true; 87 | } 88 | } 89 | if (that.positions.length == 1) { 90 | if (that.polyline) { 91 | that.viewer.entities.remove(that.polyline); 92 | that.polyline = null; 93 | } 94 | if (that.prompt) that.prompt.update(evt.endPosition, "单击开始绘制"); 95 | that.positions = []; 96 | that.movePush = false; 97 | } 98 | 99 | }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); 100 | 101 | this.handler.setInputAction(function (evt) { //双击结束绘制 102 | if (!that.entity) return; 103 | that.endCreate(); 104 | if (callback) callback(that.entity); 105 | }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); 106 | } 107 | 108 | endCreate() { 109 | let that = this; 110 | that.state = "endCreate"; 111 | that.positions.pop(); 112 | that.viewer.entities.remove(that.controlPoints.pop()); 113 | if (that.handler) { 114 | that.handler.destroy(); 115 | that.handler = null; 116 | } 117 | that.movePush = false; 118 | if (that.prompt) { 119 | that.prompt.destroy(); 120 | that.prompt = null; 121 | } 122 | 123 | that.viewer.trackedEntity = undefined; 124 | that.viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); 125 | 126 | } 127 | 128 | /** 129 | * 当前步骤结束 130 | */ 131 | done() { 132 | if (this.state == "startCreate") { 133 | this.destroy(); 134 | } else if (this.state == "creating") { 135 | if (this.positions.length <= 2 && this.movePush == true) { 136 | this.destroy(); 137 | } else { 138 | this.endCreate(); 139 | } 140 | } else if (this.state == "startEdit" || this.state == "editing") { 141 | this.endEdit(); 142 | } else { 143 | 144 | } 145 | } 146 | 147 | createByPositions(lnglatArr, callback) { //通过传入坐标数组创建面 148 | if (!lnglatArr) return; 149 | this.state = "startCreate"; 150 | let positions = (lnglatArr[0] instanceof Cesium.Cartesian3) ? lnglatArr : util.lnglatsToCartesians(lnglatArr); 151 | if (!positions) return; 152 | this.entity = this.createPolygon(); 153 | this.polyline = this.createPolyline(); 154 | this.polyline.show = this.style.outline; 155 | 156 | this.positions = positions; 157 | for (let i = 0; i < positions.length; i++) { 158 | let newP = positions[i]; 159 | let ctgc = Cesium.Cartographic.fromCartesian(positions[i]); 160 | let point = this.createPoint(newP); 161 | point.point.heightReference = this.style.heightReference; 162 | point.ctgc = ctgc; 163 | point.wz = this.controlPoints.length; 164 | this.controlPoints.push(point); 165 | } 166 | this.state = "endCreate"; 167 | this.entity.objId = this.objId; 168 | 169 | if (callback) callback(this.entity); 170 | } 171 | getStyle() { 172 | if (!this.entity) return; 173 | let obj = {}; 174 | let polygon = this.entity.polygon; 175 | 176 | if (polygon.material instanceof Cesium.ColorMaterialProperty) { 177 | obj.material = "common"; 178 | let color = polygon.material.color.getValue(); 179 | obj.colorAlpha = color.alpha; 180 | obj.color = new Cesium.Color(color.red, color.green, color.blue, 1).toCssHexString(); 181 | } else { 182 | 183 | } 184 | 185 | obj.fill = polygon.fill ? polygon.fill.getValue() : false; 186 | if (polygon.heightReference) { 187 | let heightReference = polygon.heightReference.getValue(); 188 | obj.heightReference = Number(heightReference); 189 | } 190 | 191 | /* obj.heightReference = isNaN(polygon.heightReference.getValue()) ? false : polygon.heightReference.getValue(); */ 192 | let outline = this.polyline.polyline; 193 | if (outline && this.polyline.show) { 194 | obj.outlineWidth = outline.width.getValue(); 195 | /* obj.outline = "show"; */ 196 | obj.outline = true; 197 | let oColor = outline.material.color.getValue(); 198 | obj.outlineColorAlpha = oColor.alpha; 199 | obj.outlineColor = new Cesium.Color(oColor.red, oColor.green, oColor.blue, 1).toCssHexString(); 200 | } else { 201 | /* obj.outline = "hide"; */ 202 | obj.outline = false; 203 | } 204 | return obj; 205 | 206 | } 207 | // 设置相关样式 208 | setStyle(style) { 209 | if (!style) return; 210 | // 由于官方api中的outline限制太多 此处outline为重新构建的polyline 211 | /* this.polyline.show = style.outline.show == "show" ? true : false; */ 212 | this.polyline.show = style.outline; 213 | let outline = this.polyline.polyline; 214 | outline.width = style.outlineWidth; 215 | this.polyline.clampToGround = Boolean(style.heightReference); 216 | let outlineColor = (style.outlineColor instanceof Cesium.Color) ? style.outlineColor : Cesium.Color.fromCssColorString(style.outlineColor); 217 | let outlineMaterial = outlineColor.withAlpha(style.outlineColorAlpha || 1); 218 | outline.material = outlineMaterial; 219 | if (style.heightReference != undefined) this.entity.polygon.heightReference = Number(style.heightReference); 220 | let color = style.color instanceof Cesium.Color ? style.color : Cesium.Color.fromCssColorString(style.color); 221 | let material = color.withAlpha(style.colorAlpha || 1); 222 | this.entity.polygon.material = material; 223 | if (style.fill != undefined) this.entity.polygon.fill = style.fill; 224 | this.style = Object.assign(this.style, style); 225 | } 226 | 227 | createPolygon() { 228 | let that = this; 229 | this.style.color = this.style.color || Cesium.Color.WHITE; 230 | this.style.outlineColor = this.style.outlineColor || Cesium.Color.BLACK; 231 | let polygonObj = { 232 | polygon: { 233 | hierarchy: new Cesium.CallbackProperty(function () { 234 | return new Cesium.PolygonHierarchy(that.positions) 235 | }, false), 236 | heightReference: Number(this.style.heightReference), 237 | show: true, 238 | fill: this.style.fill == undefined ? true : this.style.fill, 239 | material: this.style.color instanceof Cesium.Color ? this.style.color : Cesium.Color.fromCssColorString(this.style.color).withAlpha(this.style.colorAlpha || 1) 240 | } 241 | } 242 | 243 | if (!this.style.heightReference) { 244 | polygonObj.polygon.height = 0; // 不贴地 必设 245 | polygonObj.polygon.perPositionHeight = true; // 启用点的真实高度 246 | } 247 | return this.viewer.entities.add(polygonObj); 248 | } 249 | createPolyline() { 250 | let that = this; 251 | return this.viewer.entities.add({ 252 | polyline: { 253 | positions: new Cesium.CallbackProperty(function () { 254 | let newPositions = that.positions.concat(that.positions[0]); 255 | return newPositions 256 | }, false), 257 | clampToGround: Boolean(this.style.heightReference), 258 | material: this.style.outlineColor instanceof Cesium.Color ? this.style.outlineColor : Cesium.Color.fromCssColorString(this.style.outlineColor).withAlpha(this.style.outlineColorAlpha || 1), 259 | width: this.style.outlineWidth || 1 260 | } 261 | }); 262 | } 263 | 264 | destroy() { 265 | if (this.handler) { 266 | this.handler.destroy(); 267 | this.handler = null; 268 | } 269 | if (this.modifyHandler) { 270 | this.modifyHandler.destroy(); 271 | this.modifyHandler = null; 272 | } 273 | if (this.entity) { 274 | this.viewer.entities.remove(this.entity); 275 | this.entity = null; 276 | } 277 | if (this.polyline) { 278 | this.viewer.entities.remove(this.polyline); 279 | this.polyline = null; 280 | } 281 | this.positions = []; 282 | this.style = null; 283 | if (this.modifyPoint) { 284 | this.viewer.entities.remove(this.modifyPoint); 285 | this.modifyPoint = null; 286 | } 287 | for (let i = 0; i < this.controlPoints.length; i++) { 288 | let point = this.controlPoints[i]; 289 | this.viewer.entities.remove(point); 290 | } 291 | this.controlPoints = []; 292 | this.state = "no"; 293 | if (this.prompt) this.prompt.destroy(); 294 | if (this.polyline) { 295 | this.polyline = null; 296 | this.viewer.entities.remove(this.polyline); 297 | } 298 | this.forbidDrawWorld(false); 299 | } 300 | 301 | } 302 | 303 | export default CreatePolygon; -------------------------------------------------------------------------------- /src/js/plot/createRectgon.js: -------------------------------------------------------------------------------- 1 | import '../prompt/prompt.css' 2 | import Prompt from '../prompt/prompt.js' 3 | import BasePlot from './basePlot' 4 | import util from '../util'; 5 | class CreateRectgon extends BasePlot { 6 | constructor(viewer, style) { 7 | super(viewer, style); 8 | this.type = "polygon"; 9 | this.viewer = viewer; 10 | this.entity = null; 11 | this.polyline = null; 12 | let defaultStyle = { 13 | outlineColor: "#000000", 14 | outlineWidth: 2 15 | } 16 | this.style = Object.assign(defaultStyle, style || {}); 17 | this.outline = null; 18 | } 19 | 20 | start(callBack) { 21 | if (!this.prompt && this.promptStyle.show) this.prompt = new Prompt(this.viewer, this.promptStyle); 22 | 23 | this.state = "startCreate"; 24 | let that = this; 25 | this.handler.setInputAction(function (evt) { //单击开始绘制 26 | let cartesian = that.getCatesian3FromPX(evt.position, that.viewer, []); 27 | if (!cartesian) return; 28 | 29 | if (that.movePush) { 30 | that.positions.pop(); 31 | that.movePush = false; 32 | } 33 | that.positions.push(cartesian); 34 | let point = that.createPoint(cartesian); 35 | point.wz = that.positions.length - 1; 36 | that.controlPoints.push(point); 37 | 38 | if (that.positions.length == 3) { // 绘制第三个点 结束 39 | that.state = "endCreate"; 40 | if (that.handler) { 41 | that.handler.destroy(); 42 | that.handler = null; 43 | } 44 | that.movePush = false; 45 | if (that.prompt) { 46 | that.prompt.destroy(); 47 | that.prompt = null; 48 | } 49 | that.viewer.trackedEntity = undefined; 50 | that.viewer.scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); 51 | if (callBack) callBack(that.entity); 52 | } 53 | 54 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 55 | this.handler.setInputAction(function (evt) { //移动时绘制面 56 | if (that.positions.length < 1) { 57 | that.prompt.update(evt.endPosition, "单击开始绘制"); 58 | that.state = "startCreate"; 59 | return; 60 | } 61 | if (that.prompt) that.prompt.update(evt.endPosition, "双击结束,右键取消上一步"); 62 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer, []); 63 | if (that.positions.length >= 1) { 64 | that.state = "creating"; 65 | if (!that.movePush) { 66 | that.positions.push(cartesian); 67 | that.movePush = true; 68 | } else { 69 | that.positions[that.positions.length - 1] = cartesian; 70 | } 71 | if (that.positions.length == 2) { 72 | if (!Cesium.defined(that.polyline)) { 73 | that.polyline = that.createPolyline(); 74 | } 75 | } 76 | if (that.positions.length == 3) { 77 | if (!Cesium.defined(that.entity)) { 78 | that.entity = that.createPolygon(that.style); 79 | if (!that.style.outline && that.polyline) { // 不需要创建轮廓 则后续删除 80 | that.polyline.show = false; 81 | } 82 | that.entity.objId = that.objId; 83 | } 84 | } 85 | } 86 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 87 | 88 | this.handler.setInputAction(function (evt) { 89 | if (!that.entity) return; 90 | that.positions.splice(that.positions.length - 2, 1); 91 | that.viewer.entities.remove(that.controlPoints.pop()); 92 | if (that.positions.length == 2) { 93 | if (that.entity) { 94 | that.viewer.entities.remove(that.entity); 95 | that.entity = null; 96 | if (that.polyline) that.polyline.show = true; 97 | } 98 | } 99 | if (that.positions.length == 1) { 100 | if (that.polyline) { 101 | that.viewer.entities.remove(that.polyline); 102 | that.polyline = null; 103 | } 104 | if (that.prompt) that.prompt.update(evt.endPosition, "单击开始绘制"); 105 | that.positions = []; 106 | that.movePush = false; 107 | } 108 | 109 | }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); 110 | 111 | } 112 | createByPositions(lnglatArr, callBack) { //通过传入坐标数组创建面 113 | if (!lnglatArr) return; 114 | this.state = "startCreate"; 115 | let positions = (lnglatArr[0] instanceof Cesium.Cartesian3) ? lnglatArr : util.lnglatsToCartesians(lnglatArr); 116 | if (!positions) return; 117 | this.entity = this.createPolygon(); 118 | this.polyline = this.createPolyline(); 119 | this.polyline.show = this.style.outline; 120 | 121 | this.positions = positions; 122 | for (let i = 0; i < positions.length; i++) { 123 | let newP = positions[i]; 124 | let ctgc = Cesium.Cartographic.fromCartesian(positions[i]); 125 | let point = this.createPoint(newP); 126 | point.point.heightReference = this.style.heightReference; 127 | point.ctgc = ctgc; 128 | point.wz = this.controlPoints.length; 129 | this.controlPoints.push(point); 130 | } 131 | this.state = "endCreate"; 132 | this.entity.objId = this.objId; 133 | 134 | if (callBack) callBack(this.entity); 135 | } 136 | getStyle() { 137 | if (!this.entity) return; 138 | let obj = {}; 139 | let polygon = this.entity.polygon; 140 | 141 | if (polygon.material instanceof Cesium.ColorMaterialProperty) { 142 | obj.material = "common"; 143 | let color = polygon.material.color.getValue(); 144 | obj.colorAlpha = color.alpha; 145 | obj.color = new Cesium.Color(color.red, color.green, color.blue, 1).toCssHexString(); 146 | } else { 147 | 148 | } 149 | 150 | obj.fill = polygon.fill ? polygon.fill.getValue() : false; 151 | if (polygon.heightReference) { 152 | let heightReference = polygon.heightReference.getValue(); 153 | obj.heightReference = Number(heightReference); 154 | } 155 | 156 | /* obj.heightReference = isNaN(polygon.heightReference.getValue()) ? false : polygon.heightReference.getValue(); */ 157 | let outline = this.polyline.polyline; 158 | if (outline && this.polyline.show) { 159 | obj.outlineWidth = outline.width.getValue(); 160 | /* obj.outline = "show"; */ 161 | obj.outline = true; 162 | let oColor = outline.material.color.getValue(); 163 | obj.outlineColorAlpha = oColor.alpha; 164 | obj.outlineColor = new Cesium.Color(oColor.red, oColor.green, oColor.blue, 1).toCssHexString(); 165 | } else { 166 | /* obj.outline = "hide"; */ 167 | obj.outline = false; 168 | } 169 | return obj; 170 | 171 | } 172 | // 设置相关样式 173 | setStyle(style) { 174 | if (!style) return; 175 | // 由于官方api中的outline限制太多 此处outline为重新构建的polyline 176 | /* this.polyline.show = style.outline.show == "show" ? true : false; */ 177 | this.polyline.show = style.outline; 178 | let outline = this.polyline.polyline; 179 | outline.width = style.outlineWidth; 180 | this.polyline.clampToGround = Boolean(style.heightReference); 181 | let outlineColor = (style.outlineColor instanceof Cesium.Color) ? style.outlineColor : Cesium.Color.fromCssColorString(style.outlineColor); 182 | let outlineMaterial = outlineColor.withAlpha(style.outlineColorAlpha || 1); 183 | outline.material = outlineMaterial; 184 | if (style.heightReference != undefined) this.entity.polygon.heightReference = Number(style.heightReference); 185 | let color = style.color instanceof Cesium.Color ? style.color : Cesium.Color.fromCssColorString(style.color); 186 | let material = color.withAlpha(style.colorAlpha || 1); 187 | this.entity.polygon.material = material; 188 | if (style.fill != undefined) this.entity.polygon.fill = style.fill; 189 | this.style = Object.assign(this.style, style); 190 | } 191 | 192 | createPolygon() { 193 | let that = this; 194 | this.style.color = this.style.color || Cesium.Color.WHITE; 195 | this.style.outlineColor = this.style.outlineColor || Cesium.Color.BLACK; 196 | let polygonObj = { 197 | polygon: { 198 | hierarchy: new Cesium.CallbackProperty(function () { 199 | let rps = that.computePositions(that.positions); 200 | return new Cesium.PolygonHierarchy(rps) 201 | }, false), 202 | heightReference: Number(this.style.heightReference), 203 | show: true, 204 | fill: this.style.fill == undefined ? true : this.style.fill, 205 | material: this.style.color instanceof Cesium.Color ? this.style.color : Cesium.Color.fromCssColorString(this.style.color).withAlpha(this.style.colorAlpha || 1) 206 | } 207 | } 208 | 209 | if (!this.style.heightReference) { 210 | polygonObj.polygon.height = 0; // 不贴地 必设 211 | polygonObj.polygon.perPositionHeight = true; // 启用点的真实高度 212 | } 213 | return this.viewer.entities.add(polygonObj); 214 | } 215 | 216 | computePositions() { 217 | let p1 = this.positions[0]; 218 | let p2 = this.positions[1]; 219 | let p3 = this.positions[2]; 220 | 221 | 222 | 223 | let mid = Cesium.Cartesian3.midpoint(p1.clone(), p2.clone(), new Cesium.Cartesian3()); 224 | const radius = Cesium.Cartesian3.distance(p1.clone(), p2.clone()) / 2; 225 | let dir = Cesium.Cartesian3.subtract(p3.clone(), mid.clone(), new Cesium.Cartesian3()); 226 | dir = Cesium.Cartesian3.normalize(dir, new Cesium.Cartesian3()); 227 | 228 | let newp3 = Cesium.Cartesian3.multiplyByScalar(dir.clone(), radius, new Cesium.Cartesian3()); 229 | newp3 = Cesium.Cartesian3.add(newp3.clone(), mid.clone()); 230 | 231 | let negate = Cesium.Cartesian3.negate(dir.clone(), new Cesium.Cartesian3()); 232 | negate = Cesium.Cartesian3.multiplyByScalar(negate.clone(), radius, new Cesium.Cartesian3()); 233 | p4 = Cesium.Cartesian3.add(negate.clone(), mid.clone()); 234 | return [p1.clone(), newp3.clone(), p2.clone(), p4.clone()]; 235 | } 236 | 237 | createPolyline() { 238 | let that = this; 239 | return this.viewer.entities.add({ 240 | polyline: { 241 | positions: new Cesium.CallbackProperty(function () { 242 | let newPositions = that.positions.concat(that.positions[0]); 243 | return newPositions 244 | }, false), 245 | clampToGround: Boolean(this.style.heightReference), 246 | material: this.style.outlineColor instanceof Cesium.Color ? this.style.outlineColor : Cesium.Color.fromCssColorString(this.style.outlineColor).withAlpha(this.style.outlineColorAlpha || 1), 247 | width: this.style.outlineWidth || 1 248 | } 249 | }); 250 | } 251 | 252 | destroy() { 253 | if (this.handler) { 254 | this.handler.destroy(); 255 | this.handler = null; 256 | } 257 | if (this.modifyHandler) { 258 | this.modifyHandler.destroy(); 259 | this.modifyHandler = null; 260 | } 261 | if (this.entity) { 262 | this.viewer.entities.remove(this.entity); 263 | this.entity = null; 264 | } 265 | if (this.polyline) { 266 | this.viewer.entities.remove(this.polyline); 267 | this.polyline = null; 268 | } 269 | this.positions = []; 270 | this.style = null; 271 | if (this.modifyPoint) { 272 | this.viewer.entities.remove(this.modifyPoint); 273 | this.modifyPoint = null; 274 | } 275 | for (let i = 0; i < this.controlPoints.length; i++) { 276 | let point = this.controlPoints[i]; 277 | this.viewer.entities.remove(point); 278 | } 279 | this.controlPoints = []; 280 | this.state = "no"; 281 | if (this.prompt) this.prompt.destroy(); 282 | if (this.polyline) { 283 | this.polyline = null; 284 | this.viewer.entities.remove(this.polyline); 285 | } 286 | this.forbidDrawWorld(false); 287 | } 288 | 289 | } 290 | 291 | export default CreateRectgon; 292 | -------------------------------------------------------------------------------- /src/js/prompt/prompt.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * 气泡窗类 4 | * @class 5 | * 6 | */ 7 | import "./prompt.css" 8 | class Prompt { 9 | /** 10 | * @param {Cesium.Viewer} viewer 地图viewer对象 11 | * @param {Object} opt 12 | * @param {Cesium.Cartesian3 | Array} [opt.position] 弹窗坐标 (type=2时生效) 13 | * @param {Boolean} opt.show 是否显示 14 | * @param {Function} [opt.success] 创建成功的回调函数 15 | * @param {Number} [opt.type=1] 1~位置变化提示框 / 2~固定坐标提示框 16 | * @param {Cesium.Cartesian3 | Array} opt.position 固定坐标提示框的坐标( cartesian3 / [101,30] ),type为1时,可不设置此参数 17 | * @param {Boolean} [opt.anchor=true] 是否显示锚点 18 | * @param {Boolean} [opt.closeBtn=true] 是否显示关闭按钮 19 | * @param {String} opt.className 自定义class 20 | * @param {String} opt.content 弹窗内容 21 | * @param {Function} [opt.close] 关闭弹窗时的回调函数 22 | * @param {Object} [opt.offset] 偏移参数 23 | * @param {Number} [opt.offset.x] 横坐标偏移像素单位 24 | * @param {Number} [opt.offset.y] 纵坐标偏移像素单位 25 | * @param {Object} [opt.style] 弹窗面板样式 26 | * @param {String} [opt.style.background='white'] 背景色 27 | * @param {String} [opt.style.boxShadow] 弹窗阴影(css属性) 28 | * @param {String} [opt.style.color] 弹窗颜色 29 | * 30 | */ 31 | constructor(viewer, opt) { 32 | this.viewer = viewer; 33 | if (!this.viewer) return; 34 | this.type = "prompt"; 35 | // 默认值 36 | opt = opt || {}; 37 | const promptType = opt.type == undefined ? 1 : opt.type; 38 | let defaultOpt = { 39 | id: (new Date().getTime() + "" + Math.floor(Math.random() * 10000)), 40 | type: promptType, 41 | anchor: promptType == 2 ? true : false, 42 | closeBtn: promptType == 2 ? true : false, 43 | offset: promptType == 2 ? { x: 0, y: -20 } : { x: 10, y: 10 }, 44 | content: "", 45 | show: true, 46 | style: { 47 | background: "rgba(0,0,0,0.5)", 48 | color: "white" 49 | } 50 | } 51 | 52 | this.opt = Object.assign(defaultOpt, opt); 53 | 54 | /** 55 | * @property {Object} attr 相关属性 56 | */ 57 | this.attr = this.opt; 58 | // ====================== 创建弹窗内容 start ====================== 59 | const mapid = this.viewer.container.id; 60 | 61 | /** 62 | * @property {Boolearn} isShow 当前显示状态 63 | */ 64 | this.isShow = this.opt.show == undefined ? true : this.opt.show; // 是否显示 65 | let anchorHtml = ``; 66 | let closeHtml = ``; 67 | const background = this.opt.style.background; 68 | const color = this.opt.style.color; 69 | if (this.opt.anchor) { 70 | anchorHtml += ` 71 |
72 |
73 |
74 |
75 | `; 76 | } 77 | if (this.opt.closeBtn) { // 移动提示框 不显示关闭按钮 78 | closeHtml = `x`; 79 | } 80 | let boxShadow = this.opt.style.boxShadow; 81 | const promptId = "prompt-" + this.opt.id; 82 | const promptConenet = ` 83 | 84 |
85 |
86 | ${this.opt.content} 87 |
88 |
89 | 90 | ${anchorHtml} 91 | 92 | ${closeHtml} 93 | `; 94 | // 构建弹窗元素 95 | this.promptDiv = window.document.createElement("div"); 96 | this.promptDiv.className = `easy3d-prompt ${this.opt.className}`; 97 | this.promptDiv.id = promptId; 98 | this.promptDiv.innerHTML = promptConenet; 99 | let mapDom = window.document.getElementById(mapid); 100 | mapDom.appendChild(this.promptDiv); 101 | const clsBtn = window.document.getElementById(`prompt-close-${this.opt.id}`); 102 | let that = this; 103 | if (clsBtn) { 104 | clsBtn.addEventListener("click", (e) => { 105 | that.hide(); 106 | if (that.opt.close) that.opt.close(); 107 | }) 108 | } 109 | 110 | /** 111 | * @property {Object} promptDom 弹窗div 112 | */ 113 | this.promptDom = window.document.getElementById(promptId); 114 | 115 | this.position = this.transPosition(this.opt.position); 116 | // ====================== 创建弹窗内容 end ====================== 117 | 118 | if (promptType == 2) this.bindRender(); // 固定位置弹窗 绑定实时渲染 当到地球背面时 隐藏 119 | if (this.opt.show == false) this.hide(); 120 | this.containerW = this.viewer.container.offsetWidth; 121 | this.containerH = this.viewer.container.offsetHeight; 122 | this.containerLeft = this.viewer.container.offsetLeft; 123 | this.containerTop = this.viewer.container.offsetTop; 124 | 125 | /** 126 | * @property {Number} contentW 弹窗宽度 127 | */ 128 | this.contentW = Math.ceil(Number(this.promptDom.offsetWidth)); // 宽度 129 | 130 | /** 131 | * @property {Number} contentH 弹窗高度 132 | */ 133 | this.contentH = this.promptDom.offsetHeight; // 高度 134 | 135 | if (this.opt.success) this.opt.success(); 136 | } 137 | 138 | /** 139 | * 销毁 140 | */ 141 | destroy() { 142 | if (this.promptDiv) { 143 | window.document.getElementById(this.viewer.container.id).removeChild(this.promptDiv); 144 | this.promptDiv = null; 145 | } 146 | if (this.rendHandler) { 147 | this.rendHandler(); 148 | this.rendHandler = null; 149 | } 150 | } 151 | // 实时监听 152 | bindRender() { 153 | let that = this; 154 | this.rendHandler = this.viewer.scene.postRender.addEventListener(function () { 155 | if (!that.isShow && that.promptDom) { 156 | that.promptDom.style.display = "none"; 157 | return; 158 | } 159 | if (!that.position) return; 160 | if (that.position instanceof Cesium.Cartesian3) { 161 | let px = Cesium.SceneTransforms.wgs84ToWindowCoordinates(that.viewer.scene, that.position); 162 | if (!px) return; 163 | const occluder = new Cesium.EllipsoidalOccluder(that.viewer.scene.globe.ellipsoid, that.viewer.scene.camera.position); 164 | // 当前点位是否可见 是否在地球背面 165 | const res = occluder.isPointVisible(that.position); 166 | if (res) { 167 | if (that.promptDom) that.promptDom.style.display = "block"; 168 | } else { 169 | if (that.promptDom) that.promptDom.style.display = "none"; 170 | } 171 | that.setByPX({ 172 | x: px.x, 173 | y: px.y 174 | }); 175 | } else { 176 | that.setByPX({ 177 | x: that.position.x, 178 | y: that.position.y 179 | }); 180 | } 181 | 182 | }, this); 183 | } 184 | 185 | /** 186 | * 187 | * @param {Cesium.Cartesian3 | Object} px 弹窗坐标 188 | * @param {String} html 弹窗内容 189 | */ 190 | update(px, html) { 191 | if (px instanceof Cesium.Cartesian3) { 192 | this.position = px.clone(); 193 | px = Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.viewer.scene, px); 194 | } 195 | this.contentW = Math.ceil(Number(this.promptDom.offsetWidth)); // 宽度 196 | this.contentH = this.promptDom.offsetHeight; // 高度 197 | if (px) this.setByPX(px); 198 | if (html) this.setContent(html); 199 | } 200 | 201 | // 判断是否在当前视野内 202 | isInView() { 203 | if (!this.position) return false; 204 | let px = null; 205 | if (this.position instanceof Cesium.Cartesian2) { 206 | px = this.position; 207 | } else { 208 | px = Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.viewer.scene, this.position); 209 | } 210 | const occluder = new Cesium.EllipsoidalOccluder(this.viewer.scene.globe.ellipsoid, this.viewer.scene.camera.position); 211 | // 是否在地球背面 212 | const res = occluder.isPointVisible(this.position); 213 | let isin = false; 214 | if (!px) return isin; 215 | if ( 216 | px.x > this.containerLeft && 217 | px.x < (this.containerLeft + this.containerW) && 218 | px.y > this.containerTop && 219 | px.y < (this.containerTop + this.containerH) 220 | ) { 221 | isin = true; 222 | } 223 | return res && isin; 224 | } 225 | 226 | /** 227 | * 是否可见 228 | * @param {Boolean} isShow true可见,false不可见 229 | */ 230 | setVisible(isShow) { 231 | let isin = this.isInView(this.position); 232 | if (isin && isShow) { 233 | this.isShow = true; 234 | if (this.promptDom) this.promptDom.style.display = "block"; 235 | } else { 236 | this.isShow = false; 237 | if (this.promptDom) this.promptDom.style.display = "none"; 238 | } 239 | } 240 | 241 | /** 242 | * 显示 243 | */ 244 | show() { 245 | this.setVisible(true); 246 | } 247 | 248 | /** 249 | * 隐藏 250 | */ 251 | hide() { 252 | this.setVisible(false); 253 | } 254 | 255 | /** 256 | * 设置弹窗内容 257 | * @param {String} content 内容 258 | */ 259 | setContent(content) { 260 | let pc = window.document.getElementById(`prompt-content-${this.opt.id}`); 261 | pc.innerHTML = content; 262 | } 263 | 264 | /** 265 | * 设置弹窗坐标 266 | * @param {Object} opt 屏幕坐标 267 | */ 268 | setByPX(opt) { 269 | if (!opt) return; 270 | if (this.promptDom) { 271 | const contentW = this.promptDom.offsetWidth; // 宽度 272 | const contentH = this.promptDom.offsetHeight; // 高度 273 | if (this.opt.type == 1) { 274 | this.promptDom.style.left = ((Number(opt.x) + Number(this.opt.offset.x || 0))) + "px"; 275 | this.promptDom.style.top = ((Number(opt.y) + Number(this.opt.offset.y || 0))) + "px"; 276 | } else { 277 | this.promptDom.style.left = ((Number(opt.x) + Number(this.opt.offset.x || 0)) - Number(this.contentW) / 2) + "px"; 278 | this.promptDom.style.top = ((Number(opt.y) + Number(this.opt.offset.y || 0)) - Number(this.contentH)) + "px"; 279 | } 280 | } 281 | } 282 | 283 | // 坐标转换 284 | transPosition(p) { 285 | let position; 286 | if (Array.isArray(p)) { 287 | const posi = Cesium.Cartesian3.fromDegrees(p[0], p[1], p[2] || 0); 288 | position = posi.clone(); 289 | } else if (p instanceof Cesium.Cartesian3) { 290 | position = p.clone(); 291 | } else { // 像素类型 292 | position = p; 293 | } 294 | return position; 295 | } 296 | } 297 | 298 | export default Prompt; -------------------------------------------------------------------------------- /src/js/plot/basePlot.js: -------------------------------------------------------------------------------- 1 | // 所有标绘类的父类 2 | import util from "../util"; 3 | /** 4 | * 标绘基类 5 | * @description 标绘基类,一般不直接实例化,而实例化其子类(见下方Classes) 6 | * @class 7 | * @alias BasePlot 8 | */ 9 | class BasePlot { 10 | /** 11 | * @param {Cesium.Viewer} viewer 地图viewer对象 12 | * @param {Object} style 样式属性 13 | */ 14 | constructor(viewer, style) { 15 | this.viewer = viewer; 16 | 17 | /** 18 | * @property {Object} style 样式 19 | */ 20 | this.style = style || {}; 21 | 22 | /** 23 | * @property {String | Number} objId 唯一id 24 | */ 25 | this.objId = Number((new Date()).getTime() + "" + Number(Math.random() * 1000).toFixed(0)); 26 | this.handler = undefined; 27 | this.modifyHandler = undefined; 28 | 29 | /** 30 | * @property {String} type 类型 31 | */ 32 | this.type = ''; 33 | /** 34 | *@property {Cesium.Cartesian3[]} positions 坐标数组 35 | */ 36 | this.positions = []; 37 | 38 | /** 39 | *@property {String} state 标识当前状态 no startCreate creating endCreate startEdit endEdit editing 40 | */ 41 | this.state = null; // 42 | 43 | /** 44 | * @property {Object} prompt 鼠标提示框 45 | */ 46 | this.prompt = null; // 初始化鼠标提示框 47 | this.controlPoints = []; // 控制点 48 | this.modifyPoint = null; 49 | 50 | /** 51 | * 图标entity对象 52 | * @property {Cesium.Entity} entity entity对象 53 | */ 54 | 55 | this.entity = null; 56 | this.pointStyle = {}; 57 | 58 | /** 59 | * @property {Object} promptStyle 鼠标提示框样式 60 | */ 61 | this.promptStyle = this.style.prompt || { 62 | show: true 63 | } 64 | this.properties = {}; 65 | 66 | // 缩放分辨率比例 67 | this.clientScale = 1; 68 | } 69 | 70 | /** 71 | * 72 | * @param {Object} px 像素坐标 73 | * @returns {Cesium.Cartesian3} 世界坐标 74 | */ 75 | getCatesian3FromPX(px) { 76 | px = this.transpx(px); // 此处单独解决了地图采点的偏移 prompt的偏移暂未处理 77 | let picks = this.viewer.scene.drillPick(px); 78 | this.viewer.scene.render(); 79 | let cartesian; 80 | let isOn3dtiles = false; 81 | for (let i = 0; i < picks.length; i++) { 82 | if ((picks[i] && picks[i].primitive) && picks[i].primitive instanceof Cesium.Cesium3DTileset) { //模型上拾取 83 | isOn3dtiles = true; 84 | break; 85 | } 86 | } 87 | if (isOn3dtiles) { 88 | cartesian = this.viewer.scene.pickPosition(px); 89 | } else { 90 | let ray = this.viewer.camera.getPickRay(px); 91 | if (!ray) return null; 92 | cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene); 93 | } 94 | return cartesian; 95 | } 96 | 97 | /** 98 | * 此方法用于 地图界面缩放问题(transform:translate(2)) 99 | * @param {Number} scale 缩放比例 100 | */ 101 | setClientScale(scale) { 102 | scale = scale || 1; 103 | this.clientScale = scale; 104 | } 105 | 106 | transpx(px) { 107 | return { 108 | x: px.x / (this.clientScale || 1), 109 | y: px.y / (this.clientScale || 1) 110 | } 111 | } 112 | 113 | /** 114 | * 115 | * @returns {Cesium.Entity} 实体对象 116 | */ 117 | getEntity() { 118 | return this.entity; 119 | } 120 | 121 | /** 122 | * 123 | * @param {Boolean} isWgs84 是否转化为经纬度 124 | * @returns {Array} 坐标数组 125 | */ 126 | getPositions(isWgs84) { 127 | return isWgs84 ? util.cartesiansToLnglats(this.positions, this.viewer) : this.positions; 128 | } 129 | 130 | /** 131 | * 获取经纬度坐标 132 | * @returns {Array} 经纬度坐标数组 133 | */ 134 | getLnglats() { 135 | return util.cartesiansToLnglats(this.positions, this.viewer); 136 | } 137 | 138 | /** 139 | * 设置自定义属性 140 | * @param {Object} prop 属性 141 | */ 142 | setOwnProp(prop) { 143 | if (this.entity) this.entity.ownProp = prop; 144 | } 145 | 146 | /** 147 | * 移除当前entity对象 148 | */ 149 | remove() { 150 | if (this.entity) { 151 | this.state = "no"; 152 | this.viewer.entities.remove(this.entity); 153 | this.entity = null; 154 | } 155 | } 156 | 157 | /** 158 | * 设置entity对象的显示隐藏 159 | * @param {Boolean} visible 160 | */ 161 | setVisible(visible) { 162 | if (this.entity) this.entity.show = visible; 163 | } 164 | 165 | // 操作控制 166 | forbidDrawWorld(isForbid) { 167 | this.viewer.scene.screenSpaceCameraController.enableRotate = !isForbid; 168 | this.viewer.scene.screenSpaceCameraController.enableTilt = !isForbid; 169 | this.viewer.scene.screenSpaceCameraController.enableTranslate = !isForbid; 170 | this.viewer.scene.screenSpaceCameraController.enableInputs = !isForbid; 171 | } 172 | 173 | /** 174 | * 销毁 175 | */ 176 | destroy() { 177 | if (this.handler) { 178 | this.handler.destroy(); 179 | this.handler = null; 180 | } 181 | if (this.modifyHandler) { 182 | this.modifyHandler.destroy(); 183 | this.modifyHandler = null; 184 | } 185 | if (this.entity) { 186 | this.viewer.entities.remove(this.entity); 187 | this.entity = null; 188 | } 189 | 190 | this.positions = []; 191 | this.style = null; 192 | for (var i = 0; i < this.controlPoints.length; i++) { 193 | var point = this.controlPoints[i]; 194 | this.viewer.entities.remove(point); 195 | } 196 | this.controlPoints = []; 197 | this.modifyPoint = null; 198 | if (this.prompt) { 199 | this.prompt.destroy(); 200 | this.prompt = null; 201 | } 202 | this.state = "no"; 203 | this.forbidDrawWorld(false); 204 | } 205 | 206 | /** 207 | * 208 | * 开始编辑 209 | */ 210 | startEdit(callback) { 211 | if (this.state == "startEdit" || this.state == "editing" || !this.entity) return; 212 | this.state = "startEdit";; 213 | if (!this.modifyHandler) this.modifyHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 214 | let that = this; 215 | for (let i = 0; i < that.controlPoints.length; i++) { 216 | let point = that.controlPoints[i]; 217 | if (point) point.show = true; 218 | } 219 | this.entity.show = true; 220 | 221 | this.modifyHandler.setInputAction(function (evt) { 222 | if (!that.entity) return; 223 | let pick = that.viewer.scene.pick(evt.position); 224 | if (Cesium.defined(pick) && pick.id) { 225 | if (!pick.id.objId) 226 | that.modifyPoint = pick.id; 227 | that.forbidDrawWorld(true); 228 | } 229 | }, Cesium.ScreenSpaceEventType.LEFT_DOWN); 230 | this.modifyHandler.setInputAction(function (evt) { 231 | if (that.positions.length < 1 || !that.modifyPoint) return; 232 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer, [that.entity, that.modifyPoint]); 233 | if (cartesian) { 234 | that.modifyPoint.position.setValue(cartesian); 235 | that.positions[that.modifyPoint.wz] = cartesian; 236 | that.state = "editing"; 237 | if (callback) callback(); 238 | } 239 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 240 | 241 | this.modifyHandler.setInputAction(function (evt) { 242 | if (!that.modifyPoint) return; 243 | that.modifyPoint = null; 244 | that.forbidDrawWorld(false); 245 | that.state = "editing"; 246 | }, Cesium.ScreenSpaceEventType.LEFT_UP); 247 | } 248 | 249 | /** 250 | * 结束编辑 251 | * @param {Function} callback 回调函数 252 | * @example 253 | * plotObj.endEdit(function(entity){}) 254 | */ 255 | endEdit(callback) { 256 | for (let i = 0; i < this.controlPoints.length; i++) { 257 | let point = this.controlPoints[i]; 258 | if (point) point.show = false; 259 | } 260 | if (this.modifyHandler) { 261 | this.modifyHandler.destroy(); 262 | this.modifyHandler = null; 263 | if (callback) callback(this.entity); 264 | } 265 | this.forbidDrawWorld(false); 266 | this.state = "endEdit"; 267 | } 268 | 269 | /** 270 | * 结束创建 271 | */ 272 | endCreate() { 273 | 274 | } 275 | 276 | /** 277 | * 在当前步骤结束 278 | */ 279 | done() { 280 | 281 | } 282 | 283 | 284 | // 构建控制点 285 | createPoint(position) { 286 | if (!position) return; 287 | this.pointStyle.color = this.pointStyle.color || Cesium.Color.CORNFLOWERBLUE; 288 | this.pointStyle.outlineColor = this.pointStyle.color || Cesium.Color.CORNFLOWERBLUE; 289 | 290 | let color = this.pointStyle.color instanceof Cesium.Color ? this.pointStyle.color : Cesium.Color.fromCssColorString(this.pointStyle.color); 291 | color = color.withAlpha(this.pointStyle.colorAlpha || 1); 292 | 293 | let outlineColor = this.pointStyle.outlineColor instanceof Cesium.Color ? this.pointStyle.outlineColor : Cesium.Color.fromCssColorString(this.pointStyle.outlineColor); 294 | outlineColor = outlineColor.withAlpha(this.pointStyle.outlineColorAlpha || 1); 295 | 296 | return this.viewer.entities.add({ 297 | position: position, 298 | point: { 299 | pixelSize: this.pointStyle.property || 10, 300 | color: color, 301 | outlineWidth: this.pointStyle.outlineWidth || 0, 302 | outlineColor: outlineColor, 303 | disableDepthTestDistance: Number.POSITIVE_INFINITY 304 | }, 305 | show: false 306 | }); 307 | } 308 | 309 | // 获取当前标绘的样式 310 | /* getStyle() { 311 | if (!this.entity) return; 312 | let graphic = this.entity[this.plotType]; 313 | if (!graphic) return; 314 | let style = {}; 315 | switch (this.plotType) { 316 | case 'polyline': 317 | style.clampToGround = graphic.clampToGround._value; // 是否贴地 318 | style.distanceDisplayCondition = graphic.distanceDisplayCondition._value; // 显示控制 319 | style.width = graphic.width._value; // 线宽 320 | let colorObj = this.transfromLineMaterial(graphic.material); 321 | style = Object.assign(style, colorObj); 322 | break; 323 | case "polygon": 324 | style.heightReference = graphic.heightReference.getValue(); 325 | style.fill = graphic.fill._value; 326 | style.extrudedHeight = graphic.extrudedHeight._value; 327 | let gonColorObj = this.transfromGonMaterial(graphic.material); 328 | style = Object.assign(style, gonColorObj); 329 | 330 | style.outline = graphic.outline._value; 331 | let ocv = graphic.outlineColor.getValue(); 332 | style.outlineColorAlpha = ocv.alpha; 333 | style.outlineColor = new Cesium.Color(ocv.red, ocv.green, ocv.blue, 1).toCssHexString(); 334 | 335 | break; 336 | default: 337 | break; 338 | } 339 | return style; 340 | } */ 341 | 342 | // 获取线的材质 343 | transfromLineMaterial(material) { 344 | if (!material) return; 345 | let colorObj = {}; 346 | if (material instanceof Cesium.Color) { 347 | let colorVal = material.color.getValue(); 348 | colorObj.colorAlpha = colorVal.alpha; 349 | // 转为hex 350 | colorObj.colorHex = new Cesium.Color(colorVal.red, colorVal.green, colorVal.blue, 1).toCssHexString(); 351 | } 352 | return colorObj; 353 | } 354 | 355 | // 获取面材质 356 | transfromGonMaterial(material) { 357 | if (!material) return; 358 | let colorObj = {}; 359 | if (material instanceof Cesium.Color) { 360 | let colorVal = material.color.getValue(); 361 | colorObj.colorAlpha = colorVal.alpha; 362 | // 转为hex 363 | colorObj.colorHex = new Cesium.Color(colorVal.red, colorVal.green, colorVal.blue, 1).toCssHexString(); 364 | } 365 | return colorObj; 366 | } 367 | 368 | // 设置实体的属性 369 | setAttr(attr) { 370 | this.properties.attr = attr || {}; 371 | } 372 | 373 | getAttr(){ 374 | return this.properties.attr; 375 | } 376 | 377 | /** 378 | * 缩放至当前绘制的对象 379 | */ 380 | zoomTo() { 381 | if (this.entity) { 382 | this.viewer.zoomTo(this.entity); 383 | } 384 | } 385 | 386 | 387 | } 388 | 389 | export default BasePlot; -------------------------------------------------------------------------------- /src/js/plot/createCircle.js: -------------------------------------------------------------------------------- 1 | import '../prompt/prompt.css' 2 | import Prompt from '../prompt/prompt.js' 3 | import util from '../util.js' 4 | import BasePlot from './basePlot'; 5 | /** 6 | * 圆标绘类 7 | * @class 8 | * @augments BasePlot 9 | * @alias BasePlot.CreateCircle 10 | */ 11 | class CreateCircle extends BasePlot { 12 | constructor(viewer, style) { 13 | super(viewer, style); 14 | this.type = "circle"; 15 | this.objId = Number( 16 | new Date().getTime() + "" + Number(Math.random() * 1000).toFixed(0) 17 | ); 18 | this.viewer = viewer; 19 | this.style = style; 20 | this.floatPoint = null; 21 | 22 | /** 23 | * @property {Cesium.Entity} centerPoint 圆中心点 24 | */ 25 | this.centerPoint = null; 26 | 27 | /** 28 | * @property {Cesium.Cartesian3} position 圆中心点坐标 29 | */ 30 | this.position = null; 31 | this.floatPosition = null; 32 | 33 | /** 34 | * @property {Number} 圆半径 35 | */ 36 | this.radius = 0.001; 37 | this.modifyPoint = null; 38 | this.pointArr = []; 39 | } 40 | 41 | /** 42 | * 开始绘制 43 | * @param {Function} callback 绘制成功后回调函数 44 | */ 45 | start(callback) { 46 | if (!this.prompt && this.promptStyle.show) 47 | this.prompt = new Prompt(this.viewer, this.promptStyle); 48 | this.state = "startCreate"; 49 | let that = this; 50 | if (!this.handler) this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 51 | this.handler.setInputAction(function (evt) { 52 | //单击开始绘制 53 | let cartesian = that.getCatesian3FromPX(evt.position, that.viewer); 54 | if (!cartesian) return; 55 | if (!that.centerPoint) { 56 | that.position = cartesian; 57 | that.centerPoint = that.createPoint(cartesian); 58 | that.centerPoint.typeAttr = "center"; 59 | 60 | that.floatPoint = that.createPoint(cartesian.clone()); 61 | that.floatPosition = cartesian.clone(); 62 | that.floatPoint.typeAttr = "float"; 63 | that.entity = that.createCircle(that.position, that.radius); 64 | } else { 65 | if (that.entity) { 66 | that.endCreate(); 67 | if (callback) callback(that.entity); 68 | } 69 | } 70 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 71 | this.handler.setInputAction(function (evt) { 72 | // 移动时绘制线 73 | if (!that.centerPoint) { 74 | that.prompt.update(evt.endPosition, "单击开始绘制"); 75 | 76 | return; 77 | } 78 | that.state = "creating"; 79 | that.prompt.update(evt.endPosition, "再次单击结束"); 80 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 81 | if (!cartesian) return; 82 | if (that.floatPoint) { 83 | that.floatPoint.position.setValue(cartesian); 84 | that.floatPosition = cartesian.clone(); 85 | } 86 | that.radius = Cesium.Cartesian3.distance(cartesian, that.position); 87 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 88 | } 89 | 90 | /** 91 | * 通过坐标数组构建 92 | * @param {Array} lnglatArr 经纬度坐标数组 93 | * @callback {Function} callback 绘制成功后回调函数 94 | */ 95 | createByPositions(lnglatArr, callback) { 96 | if (!lnglatArr || lnglatArr.length < 1) return; 97 | this.state = "startCreate"; 98 | if (Array.isArray(lnglatArr)) { 99 | // 第一种 传入中间点坐标和边界上某点坐标 100 | let isCartesian3 = lnglatArr[0] instanceof Cesium.Cartesian3; 101 | let positions = []; 102 | if (isCartesian3) { 103 | positions = lnglatArr; 104 | } else { 105 | positions = util.lnglatsToCartesians(lnglatArr); 106 | } 107 | if (!positions || positions.length < 1) return; 108 | this.position = positions[0].clone(); 109 | this.radius = Cesium.Cartesian3.distance(this.position, positions[1]); 110 | this.floatPosition = positions[1].clone(); 111 | } else { 112 | // 第二种 传入中间点坐标和半径 113 | this.position = lnglatArr.position; 114 | this.radius = lnglatArr.radius; 115 | this.floatPosition = util.getPositionByLength(); 116 | } 117 | this.centerPoint = this.createPoint(this.position); 118 | this.centerPoint.typeAttr = "center"; 119 | this.floatPoint = this.createPoint(this.float); 120 | this.floatPoint.typeAttr = "float"; 121 | this.entity = this.createCircle(this.position, this.radius); 122 | this.state = "endCreate"; 123 | if (callback) callback(this.entity); 124 | } 125 | 126 | /** 127 | * 开始编辑 128 | * @param {Function} callback 回调函数 129 | */ 130 | startEdit(callback) { 131 | if (this.state == "startEdit" || this.state == "editing" || !this.entity) 132 | return; 133 | this.state = "startEdit"; 134 | if (!this.modifyHandler) 135 | this.modifyHandler = new Cesium.ScreenSpaceEventHandler( 136 | this.viewer.scene.canvas 137 | ); 138 | let that = this; 139 | if (that.floatPoint) that.floatPoint.show = true; 140 | if (that.centerPoint) that.centerPoint.show = true; 141 | this.modifyHandler.setInputAction(function (evt) { 142 | if (!that.entity) return; 143 | that.state = "editing"; 144 | let pick = that.viewer.scene.pick(evt.position); 145 | if (Cesium.defined(pick) && pick.id) { 146 | if (!pick.id.objId) that.modifyPoint = pick.id; 147 | that.forbidDrawWorld(true); 148 | } else { 149 | if (that.floatPoint) that.floatPoint.show = false; 150 | if (that.centerPoint) that.centerPoint.show = false; 151 | if (that.modifyHandler) { 152 | that.modifyHandler.destroy(); 153 | that.modifyHandler = null; 154 | 155 | } 156 | } 157 | }, Cesium.ScreenSpaceEventType.LEFT_DOWN); 158 | this.modifyHandler.setInputAction(function (evt) { 159 | if (!that.modifyPoint) return; 160 | let cartesian = that.getCatesian3FromPX(evt.endPosition, that.viewer); 161 | if (!cartesian) return; 162 | that.state = "editing"; 163 | if (that.modifyPoint.typeAttr == "center") { 164 | // 计算当前偏移量 165 | let subtract = Cesium.Cartesian3.subtract( 166 | cartesian, 167 | that.position, 168 | new Cesium.Cartesian3() 169 | ); 170 | that.position = cartesian; 171 | that.centerPoint.position.setValue(that.position); 172 | that.entity.position.setValue(that.position); 173 | 174 | that.floatPosition = Cesium.Cartesian3.add( 175 | that.floatPosition, 176 | subtract, 177 | new Cesium.Cartesian3() 178 | ); 179 | that.floatPoint.position.setValue(that.floatPosition); 180 | } else { 181 | that.floatPosition = cartesian; 182 | that.floatPoint.position.setValue(that.floatPosition); 183 | that.radius = Cesium.Cartesian3.distance(that.floatPosition, that.position); 184 | } 185 | if (callback) callback(); 186 | }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); 187 | 188 | this.modifyHandler.setInputAction(function (evt) { 189 | if (!that.modifyPoint) return; 190 | that.modifyPoint = null; 191 | that.forbidDrawWorld(false); 192 | that.state = "editing"; 193 | }, Cesium.ScreenSpaceEventType.LEFT_UP); 194 | } 195 | 196 | /** 197 | * 结束绘制cartesiansToLnglats 198 | * @param {Function} callback 结束绘制后回调函数 199 | */ 200 | endCreate() { 201 | let that = this; 202 | that.state = "endCreate"; 203 | if (that.handler) { 204 | that.handler.destroy(); 205 | that.handler = null; 206 | } 207 | if (that.floatPoint) that.floatPoint.show = false; 208 | if (that.centerPoint) that.centerPoint.show = false; 209 | if (that.prompt) { 210 | that.prompt.destroy(); 211 | that.prompt = null; 212 | } 213 | } 214 | 215 | /** 216 | * 当前步骤结束 217 | */ 218 | done() { 219 | if (this.state == "startCreate") { 220 | this.destroy(); 221 | } else if (this.state == "creating") { 222 | this.destroy(); 223 | } else if (this.state == "startEdit" || this.state == "editing") { 224 | this.endEdit(); 225 | } else { 226 | 227 | } 228 | } 229 | 230 | /** 231 | * 结束编辑 232 | * @param {Function} callback 回调函数 233 | */ 234 | endEdit(callback) { 235 | if (this.floatPoint) this.floatPoint.show = false; 236 | if (this.centerPoint) this.centerPoint.show = false; 237 | if (this.modifyHandler) { 238 | this.modifyHandler.destroy(); 239 | this.modifyHandler = null; 240 | if (callback) callback(this.entity); 241 | } 242 | this.forbidDrawWorld(false); 243 | this.state = "endEdit"; 244 | } 245 | 246 | createCircle() { 247 | let that = this; 248 | let defauteObj = { 249 | semiMajorAxis: new Cesium.CallbackProperty(function () { 250 | return that.radius; 251 | }, false), 252 | semiMinorAxis: new Cesium.CallbackProperty(function () { 253 | return that.radius; 254 | }, false), 255 | material: 256 | this.style.color instanceof Cesium.Color 257 | ? this.style.color 258 | : this.style.color 259 | ? Cesium.Color.fromCssColorString(this.style.color).withAlpha( 260 | this.style.colorAlpha || 1 261 | ) 262 | : Cesium.Color.WHITE, 263 | outlineColor: 264 | this.style.outlineColor instanceof Cesium.Color 265 | ? this.style.outlineColor 266 | : this.style.outlineColor 267 | ? Cesium.Color.fromCssColorString(this.style.outlineColor).withAlpha( 268 | this.style.outlineColorAlpha || 1 269 | ) 270 | : Cesium.Color.BLACK, 271 | outline: this.style.outline, 272 | heightReference : this.style.heightReference, 273 | outlineWidth: this.style.outlineWidth, 274 | fill: this.style.fill, 275 | }; 276 | /* if ( 277 | !this.style.heightReference || 278 | Number(this.style.heightReference) == 0 279 | ) { 280 | defauteObj.height = 100 || this.style.height; 281 | defauteObj.heightReference = 0; 282 | } else { 283 | defauteObj.heightReference = 1; 284 | } */ 285 | let ellipse = this.viewer.entities.add({ 286 | position: this.position, 287 | ellipse: defauteObj, 288 | }); 289 | ellipse.objId = this.objId; 290 | return ellipse; 291 | } 292 | setStyle(style) { 293 | if (!style) return; 294 | let color = Cesium.Color.fromCssColorString(style.color || "#ffff00"); 295 | color = color.withAlpha(style.colorAlpha); 296 | this.entity.ellipse.material = color; 297 | this.entity.ellipse.outline = style.outline; 298 | this.entity.ellipse.outlineWidth = style.outlineWidth; 299 | 300 | let outlineColor = Cesium.Color.fromCssColorString( 301 | style.outlineColor || "#000000" 302 | ); 303 | outlineColor = outlineColor.withAlpha(style.outlineColorAlpha); 304 | this.entity.ellipse.outlineColor = outlineColor; 305 | 306 | this.entity.ellipse.heightReference = Number(style.heightReference); 307 | if (style.heightReference == 0) { 308 | this.entity.ellipse.height = Number(style.height); 309 | this.updatePointHeight(style.height); 310 | } 311 | this.entity.ellipse.fill = Boolean(style.fill); 312 | this.style = Object.assign(this.style, style); 313 | } 314 | getStyle() { 315 | let obj = {}; 316 | let ellipse = this.entity.ellipse; 317 | let color = ellipse.material.color.getValue(); 318 | obj.colorAlpha = color.alpha; 319 | obj.color = new Cesium.Color( 320 | color.red, 321 | color.green, 322 | color.blue, 323 | 1 324 | ).toCssHexString(); 325 | if (ellipse.outline) obj.outline = ellipse.outline.getValue(); 326 | obj.outlineWidth = ellipse.outlineWidth._value; 327 | let outlineColor = ellipse.outlineColor.getValue(); 328 | obj.outlineColorAlpha = outlineColor.alpha; 329 | obj.outlineColor = new Cesium.Color( 330 | outlineColor.red, 331 | outlineColor.green, 332 | outlineColor.blue, 333 | 1 334 | ).toCssHexString(); 335 | if (ellipse.height) obj.height = ellipse.height.getValue(); 336 | if (ellipse.fill) obj.fill = ellipse.fill.getValue(); 337 | obj.heightReference = ellipse.heightReference.getValue(); 338 | return obj; 339 | } 340 | 341 | destroy() { 342 | if (this.handler) { 343 | this.handler.destroy(); 344 | this.handler = null; 345 | } 346 | if (this.modifyHandler) { 347 | this.modifyHandler.destroy(); 348 | this.modifyHandler = null; 349 | } 350 | if (this.entity) { 351 | this.viewer.entities.remove(this.entity); 352 | this.entity = null; 353 | } 354 | if (this.floatPoint) { 355 | this.viewer.entities.remove(this.floatPoint); 356 | this.floatPoint = null; 357 | } 358 | if (this.centerPoint) { 359 | this.viewer.entities.remove(this.centerPoint); 360 | this.centerPoint = null; 361 | } 362 | 363 | this.style = null; 364 | this.modifyPoint = null; 365 | if (this.prompt) this.prompt.destroy(); 366 | this.forbidDrawWorld(false); 367 | this.state = "no"; 368 | } 369 | // 修改点的高度 370 | updatePointHeight(h) { 371 | let centerP = this.centerPoint.position.getValue(); 372 | let floatP = this.floatPoint.position.getValue(); 373 | centerP = util.updatePositionsHeight( 374 | [centerP], 375 | Number(this.style.height) 376 | )[0]; 377 | floatP = util.updatePositionsHeight( 378 | [floatP], 379 | Number(this.style.height) 380 | )[0]; 381 | 382 | this.centerPoint.position.setValue(centerP); 383 | this.floatPoint.position.setValue(floatP); 384 | } 385 | getPositions(isWgs84) { 386 | let positions = []; 387 | if (isWgs84) { 388 | positions = util.cartesiansToLnglats([this.position, this.floatPosition],this.viewer); 389 | } else { 390 | positions = [this.position, this.floatPosition]; 391 | } 392 | return positions; 393 | } 394 | 395 | } 396 | 397 | export default CreateCircle; -------------------------------------------------------------------------------- /src/js/plot/drawTool.js: -------------------------------------------------------------------------------- 1 | 2 | import CreateBillboard from './createBillboard.js' 3 | import CreateCircle from './createCircle.js' 4 | import CreateGltfModel from './createGltfModel.js' 5 | import CreateLabel from './createLabel.js' 6 | import CreatePoint from './createPoint.js' 7 | import CreatePolygon from './createPolygon.js' 8 | import CreateRectangle from './createRectangle' 9 | import CreatePolyline from './createPolyline.js' 10 | /* import CreateArrow from "./createArrow"; */ // 军事标绘 11 | import util from '../util.js' 12 | /** 13 | * 绘制控制类 14 | * 15 | * @class 16 | * @example 17 | * let drawTool = new easy3d.DrawTool(window.viewer, { 18 | canEdit: true, 19 | }); 20 | plotDrawTool.on("endCreate", function (entObj, ent) {}); 21 | plotDrawTool.start({ 22 | "name": "面", 23 | "type": "polygon", 24 | "style": { 25 | "color": "#0000ff", 26 | "outline": true, 27 | "outlineColor": "#ff0000", 28 | "heightReference": 1 29 | } 30 | }) 31 | */ 32 | class DrawTool { 33 | /** 34 | * 35 | * @param {Cesium.viewer} viewer 地图viewer对象 36 | * @param {Object} obj 相关属性配置 37 | * @param {Boolean} obj.canEdit 是否可编辑 38 | */ 39 | constructor(viewer, obj) { 40 | if (!viewer) { 41 | console.warn("缺少必要参数!--viewer"); 42 | return; 43 | } 44 | obj = obj || {}; 45 | this.viewer = viewer; 46 | /** 47 | * 48 | * @property {Array} entityObjArr 标绘对象数组 49 | */ 50 | this.entityObjArr = []; 51 | this.handler = null; 52 | this.removeHandler = new Cesium.ScreenSpaceEventHandler( 53 | this.viewer.scene.canvas 54 | ); 55 | /* this.show = obj.drawEndShow == undefined ? true : obj.drawEndShow; */ 56 | 57 | /** 58 | * @property {Object} nowEditEntityObj 当前编辑对象 59 | */ 60 | this.startEditFun = null; 61 | this.endEditFun = null; 62 | this.removeFun = null; 63 | this.editingFun = undefined; 64 | 65 | this.deleteEntityObj = null; 66 | 67 | // 无论如何 进来先监听点击修改 与 右键删除事件 通过控制canEdit来判断要不要向下执行 68 | this.bindEdit(); 69 | this.bindRemove(); 70 | 71 | /** 72 | * @property {Boolear} canEdit 绘制的对象,是否可编辑 73 | */ 74 | this.canEdit = obj.canEdit == undefined ? true : obj.canEdit;; // 是否可以编辑 75 | 76 | /** 77 | * @property {Boolear} fireEdit 绘制的对象,是否直接进入编辑状态(需要canEdit==true) 78 | */ 79 | this.fireEdit = obj.fireEdit == undefined ? true : obj.fireEdit;; 80 | 81 | this.nowDrawEntityObj = null; // 当前绘制的对象 82 | this.nowEditEntityObj = null; // 当前编辑的对象 83 | } 84 | 85 | /** 86 | * 事件绑定 87 | * @param {String} type 事件类型(startEdit 开始编辑时 / endEdit 编辑结束时 / remove 删除对象时 / endCreate 创建完成后) 88 | * @param {Function} fun 绑定函数 89 | */ 90 | on(type, fun) { 91 | if (type == "startEdit") { 92 | // 开始编辑事件 93 | this.startEditFun = fun; 94 | } 95 | if (type == "endEdit") { 96 | // 结束编辑事件 97 | this.endEditFun = fun; 98 | } 99 | if (type == "remove") { 100 | // 移除事件 101 | this.removeFun = fun; 102 | } 103 | if (type == "endCreate") { 104 | // 绘制完成事件 105 | this.endCreateFun = fun; 106 | } 107 | if (type == "editing") { 108 | // 正在编辑 109 | this.editingFun = fun; 110 | } 111 | } 112 | 113 | /** 114 | * 开启编辑功能 115 | */ 116 | openEdit() { 117 | this.canEdit = true; 118 | } 119 | 120 | /** 121 | * 关闭编辑功能 122 | */ 123 | closeEdit() { 124 | this.endEdit(); 125 | this.canEdit = false; 126 | } 127 | 128 | /** 129 | * 开始绘制 130 | * @param {Object} opt 相关属性 131 | * @param {String} opt.type 绘制类型 polyline、polygon、billboard、circle、rectangle、gltfModel、point、label、arrow 132 | * @param {Object} opt.style 当前绘制对象的样式配置,具体配置见{@link style}; 133 | * @returns {Object} entityObj 当前绘制对象 134 | */ 135 | start(opt) { 136 | if (!opt || !opt.type) { 137 | return; 138 | } 139 | opt.id = opt.id || Number((new Date()).getTime() + "" + Number(Math.random() * 1000).toFixed(0)); 140 | let that = this; 141 | this.endEdit(); // 绘制前 结束编辑 142 | 143 | if (this.nowDrawEntityObj && ( 144 | this.nowDrawEntityObj.state == "startCreate" || 145 | this.nowDrawEntityObj.state == "creating")) { // 禁止一次绘制多个 146 | this.nowDrawEntityObj.destroy(); 147 | this.nowDrawEntityObj = null; 148 | } 149 | let entityObj = this.createByType(opt); 150 | if (!entityObj) return; 151 | entityObj.attr = opt || {}; // 保存开始绘制时的属性 152 | 153 | // 开始绘制 154 | entityObj.start(function (entity) { 155 | // 绘制完成后 156 | that.nowDrawEntityObj = undefined; 157 | that.entityObjArr.push(entityObj); 158 | // endCreateFun 和 success 无本质区别,若构建时 两个都设置了 当心重复 159 | if (opt.success) opt.success(entityObj, entity); 160 | if (that.endCreateFun) that.endCreateFun(entityObj, entity); 161 | 162 | if (opt.show == false) entityObj.setVisible(false); 163 | 164 | // 如果可以编辑 则绘制完成打开编辑 165 | if (that.canEdit && that.fireEdit) { 166 | entityObj.startEdit(function () { 167 | if (that.editingFun) that.editingFun(entityObj, entityObj.entity); 168 | }); 169 | that.nowEditEntityObj = entityObj; 170 | if (that.startEditFun) that.startEditFun(entityObj, entity); 171 | } 172 | }); 173 | 174 | this.nowDrawEntityObj = entityObj; 175 | return entityObj; 176 | } 177 | 178 | /** 179 | * 结束当前操作 180 | */ 181 | end() { 182 | if (this.nowDrawEntityObj) { 183 | 184 | } 185 | } 186 | 187 | /** 188 | * 开始编辑绘制对象 189 | * @param {Object} entityObj 绘制的对象 190 | */ 191 | startEditOne(entityObj) { 192 | if (!this.canEdit) return; 193 | if (this.nowEditEntityObj) { 194 | // 结束除当前选中实体的所有编辑操作 195 | this.nowEditEntityObj.endEdit(); 196 | if (this.endEditFun) { 197 | this.endEditFun(this.nowEditEntityObj, this.nowEditEntityObj.getEntity()); // 结束事件 198 | } 199 | this.nowEditEntityObj = null; 200 | } 201 | let that = this; 202 | if (entityObj) { 203 | entityObj.startEdit(function () { 204 | if (that.editingFun) that.editingFun(entityObj, entityObj.entity); 205 | }); 206 | if (this.startEditFun) 207 | this.startEditFun(entityObj, entityObj.getEntity()); 208 | this.nowEditEntityObj = entityObj; 209 | } 210 | } 211 | 212 | /** 213 | * 修改绘制对象的样式 214 | * @param {Object} entityObj 绘制的对象 215 | * @param {Object} style 样式 216 | */ 217 | updateOneStyle(entityObj, style) { 218 | if (entityObj) { 219 | entityObj.setStyle(style); 220 | } 221 | } 222 | 223 | /** 224 | * 根据坐标构建绘制对象 225 | * @param {Object} opt 绘制的对象 226 | * @param {Cesium.Cartesian3[] | Array} opt.positions 坐标数组 227 | * @param {Object} opt.style 当前绘制对象的样式配置,具体配置见{@link style}; 228 | * @param {Funtion} opt.success 创建完成的回调函数 229 | * @param {Boolean} [opt.show] 创建完成后,是否展示 230 | */ 231 | createByPositions(opt) { 232 | opt = opt || {}; 233 | if (!opt) opt = {}; 234 | if (!opt.positions) return; 235 | opt.id = opt.id || Number((new Date()).getTime() + "" + Number(Math.random() * 1000).toFixed(0)); 236 | let that = this; 237 | let entityObj = this.createByType(opt); 238 | if (!entityObj) return; 239 | entityObj.attr = opt; // 保存开始绘制时的属性 240 | entityObj.createByPositions(opt.positions, function (entity) { 241 | that.entityObjArr.push(entityObj); 242 | entityObj.setStyle(opt.style); // 设置相关样式 243 | // endCreateFun 和 success 无本质区别,若构建时 两个都设置了 当心重复 244 | if (opt.success) opt.success(entityObj, entity); 245 | if (that.endCreateFun) that.endCreateFun(entityObj, entity); 246 | if (opt.show == false) entityObj.setVisible(false); 247 | // 如果可以编辑 则绘制完成打开编辑 248 | if (that.canEdit && that.fireEdit) { 249 | entityObj.startEdit(function () { 250 | if (that.editingFun) that.editingFun(entityObj, entityObj.entity); 251 | }); 252 | if (that.startEditFun) that.startEditFun(entityObj, entity); 253 | that.nowEditEntityObj = entityObj; 254 | } 255 | }); 256 | return entityObj; 257 | } 258 | 259 | /** 260 | * 由geojson格式数据创建对象 261 | * @param {Object} data geojson格式数据 262 | */ 263 | createByGeojson(data) { 264 | let { features } = data; 265 | let entObjArr = []; 266 | for (let i = 0; i < features.length; i++) { 267 | let feature = features[i]; 268 | const { properties, geometry } = feature; 269 | let plotType = properties.plotType; 270 | const geoType = geometry.type; 271 | const coordinates = geometry.coordinates; 272 | let positions = []; 273 | let drawType = ""; 274 | switch (geoType) { 275 | case "LineString": 276 | positions = util.lnglatsToCartesians(coordinates); 277 | drawType = "polyline"; 278 | break; 279 | case "Polygon": 280 | positions = util.lnglatsToCartesians(coordinates[0]); 281 | drawType = "polygon"; 282 | break; 283 | case "Point": 284 | positions = util.lnglatsToCartesians([coordinates])[0]; 285 | drawType = plotType; 286 | break; 287 | default: ; 288 | } 289 | this.fireEdit = false; 290 | let entObj = this.createByPositions({ 291 | type: drawType, 292 | styleType: plotType, 293 | positions: positions, 294 | style: properties.style 295 | }) 296 | if (entObj) entObjArr.push(entObj); 297 | } 298 | return entObjArr; 299 | } 300 | 301 | /** 302 | * 转为geojson格式 303 | * @returns {Object} featureCollection geojson格式数据 304 | */ 305 | toGeojson() { 306 | let featureCollection = { 307 | type: "FeatureCollection", 308 | features: [], 309 | }; 310 | if (this.entityObjArr.length == 0) return null; 311 | for (let i = 0; i < this.entityObjArr.length; i++) { 312 | let item = this.entityObjArr[i]; 313 | let lnglats = item.getPositions(true); 314 | // geojson中 单个坐标 不含高度 否则geojsondatasourece加载会有问题 315 | let coordinates = []; 316 | for (let step = 0; step < lnglats.length; step++) { 317 | coordinates.push([lnglats[step][0], lnglats[step][1]]) 318 | } 319 | let style = item.getStyle(); 320 | let geoType = this.transType(item.type); 321 | let feature = { 322 | "type": "Feature", 323 | "properties": { 324 | "plotType": item.type, 325 | "style": style, 326 | }, 327 | "geometry": { 328 | "type": geoType, 329 | "coordinates": [] 330 | } 331 | } 332 | switch (geoType) { 333 | case "Polygon": 334 | feature.geometry.coordinates = [coordinates]; 335 | break; 336 | case "Point": 337 | feature.geometry.coordinates = coordinates; 338 | break; 339 | case "LineString": 340 | feature.geometry.coordinates = coordinates; 341 | break; 342 | case "": 343 | 344 | default: ; 345 | } 346 | feature.properties = Object.assign(feature.properties, item.properties); 347 | featureCollection.features.push(feature); 348 | } 349 | return featureCollection; 350 | } 351 | 352 | // 标绘类型和geojson数据类型相互转换 353 | transType(plotType) { 354 | let geoType = ''; 355 | switch (plotType) { 356 | case "polyline": 357 | geoType = "LineString"; 358 | break; 359 | case "polygon": 360 | geoType = "Polygon"; 361 | break; 362 | case "point": 363 | case "gltfModel": 364 | case "label": 365 | case "billboard": 366 | geoType = "Point"; 367 | break; 368 | default: 369 | geoType = plotType; 370 | } 371 | return geoType; 372 | } 373 | 374 | /** 375 | * 销毁 376 | */ 377 | destroy() { 378 | // 取消当前绘制 379 | if (this.nowEditEntityObj) { 380 | this.nowEditEntityObj.destroy(); 381 | this.nowEditEntityObj = null; 382 | } 383 | if (this.nowDrawEntityObj) { 384 | this.nowDrawEntityObj.destroy(); 385 | this.nowDrawEntityObj = null; 386 | } 387 | 388 | for (let i = 0; i < this.entityObjArr.length; i++) { 389 | this.entityObjArr[i].destroy(); 390 | } 391 | this.entityObjArr = []; 392 | this.nowEditEntityObj = null; 393 | 394 | if (this.handler) { 395 | this.handler.destroy(); 396 | this.handler = null; 397 | } 398 | 399 | if (this.removeHandler) { 400 | this.removeHandler.destroy(); 401 | this.removeHandler = null; 402 | } 403 | } 404 | 405 | /** 406 | * 移除某个绘制对象 407 | * @param {Object} entityObj 已绘制完成绘制对象 408 | */ 409 | removeOne(entityObj) { 410 | if (!entityObj) return; 411 | if (!entityObj) return; 412 | if (entityObj.state != "endCreate" || entityObj.state != "endEdit") { 413 | entityObj.destroy(); 414 | } else { 415 | this.removeByObjId(entityObj.objId); 416 | } 417 | 418 | } 419 | 420 | /** 421 | * 移除全部绘制对象 422 | */ 423 | removeAll() { 424 | // 取消当前绘制 425 | if (this.nowDrawEntityObj) { 426 | this.nowDrawEntityObj.destroy(); 427 | this.nowDrawEntityObj = null; 428 | } 429 | 430 | if (this.nowEditEntityObj) { 431 | this.nowEditEntityObj.destroy(); 432 | this.nowEditEntityObj = null; 433 | } 434 | 435 | for (let i = 0; i < this.entityObjArr.length; i++) { 436 | let obj = this.entityObjArr[i]; 437 | obj.destroy(); 438 | } 439 | this.entityObjArr = []; 440 | this.nowEditEntityObj = null; 441 | } 442 | 443 | /** 444 | * 是否包含某个对象 445 | * @param {Object} entityObj 绘制对象 446 | */ 447 | hasEntityObj(entityObj) { 448 | if (!entityObj) return false; 449 | let obj = this.getEntityObjByObjId(entityObj.objId); 450 | return obj != {} ? true : false; 451 | } 452 | 453 | /** 454 | * 根据id移除创建的对象 455 | * @param {String | Number} id 对象id 456 | */ 457 | removeByObjId(id) { 458 | let obj = this.getEntityObjByObjId(id); 459 | this.entityObjArr.splice(obj.index, 1); 460 | // 触发on绑定的移除事件 461 | if (this.removeFun) 462 | this.removeFun(obj.entityObj, obj.entityObj.getEntity()); 463 | if (obj.entityObj) { 464 | obj.entityObj.destroy(); 465 | } 466 | } 467 | 468 | /** 469 | * 根据attr.id移除创建的对象 470 | * @param {String | Number} id 创建时的attr.id 471 | */ 472 | removeById(id) { 473 | let obj = this.getEntityObjById(id); 474 | this.entityObjArr.splice(obj.index, 1); 475 | // 触发on绑定的移除事件 476 | if (this.removeFun) 477 | this.removeFun(obj.entityObj, obj.entityObj.getEntity()); 478 | if (obj.entityObj) { 479 | obj.entityObj.destroy(); 480 | } 481 | } 482 | 483 | 484 | /** 485 | * 根据id缩放至绘制的对象 486 | * @param {String} id 对象id 487 | */ 488 | zoomToByObjId(id) { 489 | let obj = this.getEntityObjByObjId(id); 490 | if (obj.entityObj) { 491 | obj.entityObj.zoomTo(); 492 | } 493 | } 494 | 495 | 496 | /** 497 | * 根据attr属性字段获取对象 498 | * @param {String} fieldName 属性字段名称 499 | * @param {String} [fieldValue] 属性值,若不填,则默认以id进行查询 500 | * @returns {Object} obj 对象在数组中位置以及对象 501 | */ 502 | 503 | getEntityObjByField(fieldName, fieldValue) { 504 | let obj = {}; 505 | if (!fieldValue) { 506 | // 如果缺少第二个参数 则默认以attr.id进行查询 507 | for (let i = 0; i < this.entityObjArr.length; i++) { 508 | let item = this.entityObjArr[i]; 509 | if (item.attr.id == fieldName) { 510 | obj.entityObj = item; 511 | obj.index = i; 512 | break; 513 | } 514 | } 515 | } else { 516 | // 否则 以键值对的形式进行查询 517 | for (let ind = 0; ind < this.entityObjArr.length; ind++) { 518 | let item = this.entityObjArr[ind]; 519 | if (item.attr[fieldName] == fieldValue) { 520 | obj.entityObj = item; 521 | obj.index = ind; 522 | break; 523 | } 524 | } 525 | } 526 | return obj; 527 | } 528 | 529 | /** 530 | * 根据id设置对象的显示隐藏 531 | * @param {String | Number} id 对象id 532 | * @param {Boolean} visible 是否展示 533 | */ 534 | setVisible(id, visible) { 535 | let obj = this.getEntityObjByField("id", id); 536 | if (obj.entityObj) obj.entityObj.setVisible(visible); 537 | } 538 | 539 | /** 540 | * 根据id获取对象 541 | * @param {String | Number} id entityObj的objid 542 | * @returns {Object} obj 对象在数组中位置以及对象 543 | */ 544 | getEntityObjByObjId(id) { 545 | if (!id) return; 546 | let obj = {}; 547 | for (let i = 0; i < this.entityObjArr.length; i++) { 548 | let item = this.entityObjArr[i]; 549 | if (item.objId == id) { 550 | obj.entityObj = item; 551 | obj.index = i; 552 | break; 553 | } 554 | } 555 | return obj; 556 | } 557 | 558 | /** 559 | * 根据id获取对象,同getEntityObjByField('id',idvalue); 560 | * @param {String | Number} id 创建时的attr中的id 561 | * @returns {Object} obj 对象在数组中位置以及对象 562 | */ 563 | getEntityObjById(id) { 564 | if (!id) return; 565 | let obj = {}; 566 | for (let i = 0; i < this.entityObjArr.length; i++) { 567 | let item = this.entityObjArr[i]; 568 | if (item.attr.id == id) { 569 | obj.entityObj = item; 570 | obj.index = i; 571 | break; 572 | } 573 | } 574 | return obj; 575 | } 576 | 577 | 578 | // 绑定编辑 579 | bindEdit() { 580 | let that = this; 581 | // 如果是线 面 则需要先选中 582 | if (!this.handler) this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 583 | this.handler.setInputAction(function (evt) { 584 | if (!that.canEdit) return; 585 | // 若当前正在绘制 则无法进行编辑操作 586 | if (that.nowDrawEntityObj) return; 587 | let pick = that.viewer.scene.pick(evt.position); 588 | if (Cesium.defined(pick) && pick.id) { // 选中实体 589 | for (let i = 0; i < that.entityObjArr.length; i++) { 590 | if ( 591 | pick.id.objId == that.entityObjArr[i].objId && 592 | (that.entityObjArr[i].state != "startCreate" || 593 | that.entityObjArr[i].state != "creating" || 594 | that.entityObjArr[i].state != "endEdit") 595 | ) { 596 | // 结束上一个实体的编辑操作 597 | if (that.nowEditEntityObj) { 598 | that.nowEditEntityObj.endEdit(); 599 | if (that.endEditFun) { 600 | that.endEditFun( 601 | that.nowEditEntityObj, 602 | that.nowEditEntityObj.getEntity() 603 | ); 604 | } 605 | that.nowEditEntityObj = null; 606 | } 607 | // 开始当前实体的编辑 608 | that.entityObjArr[i].startEdit(function () { 609 | if (that.editingFun) that.editingFun(that.nowEditEntityObj, that.nowEditEntityObj.entity); 610 | }); 611 | if (that.startEditFun) that.startEditFun(that.entityObjArr[i], pick.id); // 开始编辑 612 | that.nowEditEntityObj = that.entityObjArr[i]; 613 | break; 614 | } 615 | } 616 | } else { // 未选中实体 则结束全部绘制 617 | if (that.nowEditEntityObj) { 618 | that.nowEditEntityObj.endEdit(); 619 | if (that.endEditFun) { 620 | that.endEditFun( 621 | that.nowEditEntityObj, 622 | that.nowEditEntityObj.getEntity() 623 | ); 624 | } 625 | that.nowEditEntityObj = undefined; 626 | } 627 | } 628 | }, Cesium.ScreenSpaceEventType.LEFT_CLICK); 629 | } 630 | 631 | // 绑定右键删除 632 | bindRemove() { 633 | let that = this; 634 | // 如果是线 面 则需要先选中 635 | if (!this.handler) this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); 636 | this.handler.setInputAction(function (evt) { 637 | if (!that.canEdit) return; 638 | // 若当前正在绘制 则无法进行删除 639 | if (that.nowDrawEntityObj) return; 640 | let pick = that.viewer.scene.pick(evt.position); 641 | if (!pick || !pick.id) return; 642 | /* let selectEntobj = undefined; */ 643 | /* for (let i = 0; i < that.entityObjArr.length; i++) { 644 | if (pick.id.objId == that.entityObjArr[i].objId) { 645 | selectEntobj = that.entityObjArr[i]; 646 | break; 647 | } 648 | } */ 649 | 650 | that.createDelteDom(evt.position, pick.id.objId); 651 | 652 | }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); 653 | } 654 | 655 | createDelteDom(px, objId) { 656 | if (!objId) return; 657 | let deleteDom = window.document.createElement("span"); 658 | deleteDom.style.background = "rgba(0,0,0,0.5)"; 659 | deleteDom.style.position = "absolute"; 660 | deleteDom.style.color = "white"; 661 | deleteDom.style.left = (px.x + 10) + "px"; 662 | deleteDom.style.top = (px.y + 10) + "px"; 663 | deleteDom.style.padding = "4px"; 664 | deleteDom.style.cursor = "pointer"; 665 | deleteDom.id = "easy3d-plot-delete"; 666 | deleteDom.setAttribute("objId", objId); 667 | deleteDom.innerHTML = `删除`; 668 | let mapDom = window.document.getElementById(this.viewer.container.id); 669 | mapDom.appendChild(deleteDom); 670 | 671 | const clsBtn = window.document.getElementById("easy3d-plot-delete"); 672 | if (!clsBtn) return; 673 | let that = this; 674 | clsBtn.addEventListener("click", (e) => { 675 | let id = deleteDom.getAttribute("objId"); 676 | that.removeByObjId(id); 677 | }); 678 | document.addEventListener("click", function () { 679 | clsBtn.remove(); 680 | }); 681 | } 682 | 683 | /** 684 | * 结束编辑 685 | */ 686 | endEdit() { 687 | if (this.nowEditEntityObj) { 688 | // 结束除当前选中实体的所有编辑操作 689 | this.nowEditEntityObj.endEdit(); 690 | if (this.endEditFun) { 691 | this.endEditFun( 692 | this.nowEditEntityObj, 693 | this.nowEditEntityObj.getEntity() 694 | ); // 结束事件 695 | } 696 | this.nowEditEntityObj = null; 697 | } 698 | for (let i = 0; i < this.entityObjArr.length; i++) { 699 | this.entityObjArr[i].endEdit(); 700 | } 701 | } 702 | 703 | done() { 704 | if (this.nowEditEntityObj) { 705 | this.nowEditEntityObj.done(); 706 | if (this.endEditFun) this.endEditFun(this.nowEditEntityObj, this.nowEditEntityObj.getEntity()); 707 | this.nowEditEntityObj = undefined; 708 | } 709 | 710 | if (this.nowDrawEntityObj) { 711 | this.nowDrawEntityObj.done(); 712 | this.entityObjArr.push(this.nowDrawEntityObj); 713 | if (this.endCreateFun) this.endCreateFun(this.nowDrawEntityObj, this.nowDrawEntityObj.getEntity()); 714 | this.nowDrawEntityObj = undefined; 715 | } 716 | } 717 | 718 | 719 | /** 720 | * 获取当前所有对象 721 | * @returns {Array} entityObjArr 722 | */ 723 | getEntityObjArr() { 724 | return this.entityObjArr; 725 | } 726 | createByType(opt) { 727 | let entityObj = undefined; 728 | let name = ""; 729 | opt = opt || {}; 730 | if (opt.type == "polyline") { 731 | entityObj = new CreatePolyline(this.viewer, opt.style); 732 | name = "折线_"; 733 | } 734 | 735 | if (opt.type == "polygon") { 736 | entityObj = new CreatePolygon(this.viewer, opt.style); 737 | name = "面_"; 738 | } 739 | 740 | if (opt.type == "billboard") { 741 | entityObj = new CreateBillboard(this.viewer, opt.style); 742 | name = "图标_"; 743 | } 744 | 745 | if (opt.type == "circle") { 746 | entityObj = new CreateCircle(this.viewer, opt.style); 747 | name = "圆_"; 748 | } 749 | 750 | if (opt.type == "rectangle") { 751 | entityObj = new CreateRectangle(this.viewer, opt.style); 752 | name = "矩形_"; 753 | } 754 | 755 | if (opt.type == "gltfModel") { 756 | entityObj = new CreateGltfModel(this.viewer, opt.style); 757 | name = "模型_"; 758 | } 759 | 760 | if (opt.type == "point") { 761 | entityObj = new CreatePoint(this.viewer, opt.style); 762 | name = "点_"; 763 | } 764 | if (opt.type == "label") { 765 | entityObj = new CreateLabel(this.viewer, opt.style); 766 | name = "文字_"; 767 | } 768 | 769 | // ========== 以下为付费功能 ============== 770 | // if (opt.type == "arrow") { 771 | // /** 772 | // * situationType值及对应的类型: 773 | // * 1-攻击箭头 2-攻击箭头(平尾)3-攻击箭头(燕尾)4-闭合曲面 5-钳击箭头 774 | // * 6-单尖直箭头 7-粗单尖直箭头(带燕尾) 8-集结地 9-弓形面 10-直箭头 775 | // * 11-矩形旗 12-扇形 13-三角旗 14-矩形波浪旗 17-多边形 18-圆形 776 | // */ 777 | // if (!opt.arrowType) { 778 | // console.log("缺少军事标绘类型"); 779 | // return; 780 | // } 781 | // entityObj = new CreateArrow(this.viewer, opt.arrowType, opt.style); 782 | // } 783 | 784 | if (entityObj) entityObj.name = name + new Date().getTime(); 785 | return entityObj; 786 | } 787 | } 788 | 789 | export default DrawTool; 790 | 791 | 792 | --------------------------------------------------------------------------------