8f7cce68800be320b01a758c03cbaf3a2df35abc.svn-base 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. <template>
  2. <div class="measure" v-drag="'.measure .ant-card-head'">
  3. <a-card v-show='value' title="测量" style="width: 284px; box-shadow: 0 0 5px #357ee5;">
  4. <a-icon slot="extra" type="close" style='cursor: pointer; color: #FFFFFF;' @click="$emit('input',false)"/>
  5. <a-radio-group v-model="type" @change="onChange">
  6. <a-radio value="LineString">
  7. <img src="../../../assets/MeasureTool16.png">
  8. 测量距离
  9. </a-radio>
  10. <a-radio value="Polygon">
  11. <img src="../../../assets/MeasureAreaTool16.png">
  12. 测量面积
  13. </a-radio>
  14. </a-radio-group>
  15. <div style="margin: 16px 0px;">
  16. <span class="ant-input-group-wrapper">
  17. <span class="ant-input-wrapper ant-input-group">
  18. <span class="ant-input-group-addon">测量结果:</span>
  19. <input type="text" style="cursor: text" v-model="output" readonly class="ant-input ant-input-disabled">
  20. </span>
  21. </span>
  22. </div>
  23. </a-card>
  24. </div>
  25. </template>
  26. <script>
  27. import 'ol/ol.css';
  28. import {Vector as VectorSource} from "ol/source";
  29. import {Vector as VectorLayer} from "ol/layer";
  30. import {Circle, Fill, Stroke, Style} from "ol/style";
  31. import {LineString, Polygon} from "ol/geom";
  32. import {getArea, getLength} from "ol/sphere";
  33. import {Draw} from "ol/interaction";
  34. import {unByKey} from "ol/Observable";
  35. import Overlay from "ol/Overlay";
  36. export default {
  37. name: 'measureTool',
  38. inject: ['baseMap'],
  39. mounted() {
  40. },
  41. data() {
  42. return {
  43. type: 'LineString',
  44. continuePolygonMsg: '单击继续绘制图形,双击结束',
  45. continueLineMsg: '单击继续绘制图形,双击结束',
  46. sketch: '',
  47. helpTooltipElement: '',
  48. helpTooltip: '',
  49. measureTooltipElement: '',
  50. measureTooltip: '',
  51. draw: '',
  52. source: '',
  53. vector: '',
  54. map: '',
  55. figure: ''
  56. }
  57. },
  58. props: {
  59. value: {
  60. type: Boolean,
  61. default: false,
  62. required: true
  63. },
  64. output: ''
  65. },
  66. methods: {
  67. onChange() {
  68. this.map = this.baseMap.map;
  69. // this.type = e.target.value;
  70. if (this.draw !== '') {
  71. this.map.removeInteraction(this.draw);
  72. }
  73. this.addInteraction();
  74. },
  75. initVectorLayer() {
  76. this.source = new VectorSource();
  77. this.vector = new VectorLayer({
  78. source: this.source,
  79. style: new Style({
  80. fill: new Fill({
  81. color: 'rgba(255, 255, 255, 0.2)',
  82. }),
  83. stroke: new Stroke({
  84. color: '#ffcc33',
  85. width: 2,
  86. }),
  87. image: new Circle({
  88. radius: 7,
  89. fill: new Fill({
  90. color: '#ffcc33',
  91. }),
  92. }),
  93. }),
  94. });
  95. this.map.addLayer(this.vector);
  96. },
  97. /**
  98. * 创建鼠标移动事件处理方案
  99. * */
  100. pointerMoveHandler(evt) {
  101. if (evt.dragging) {
  102. return;
  103. }
  104. /** @type {string} */
  105. let helpMsg = '单击开始绘制';
  106. if (this.sketch) {
  107. const geom = this.sketch.getGeometry();
  108. if (geom instanceof Polygon) {
  109. helpMsg = this.continuePolygonMsg;
  110. } else if (geom instanceof LineString) {
  111. helpMsg = this.continueLineMsg;
  112. }
  113. }
  114. this.helpTooltipElement.innerHTML = helpMsg;
  115. this.helpTooltip.setPosition(evt.coordinate);
  116. this.helpTooltipElement.classList.remove('hidden');
  117. },
  118. /**
  119. * 初始化测量工具
  120. * */
  121. initMeasureTool() {
  122. this.map.on('pointermove', this.pointerMoveHandler);
  123. this.map.getViewport().addEventListener('mouseout', () => {
  124. this.helpTooltipElement.classList.add('hidden');
  125. });
  126. },
  127. /**
  128. * 关闭测量工具
  129. * */
  130. closeMeasureTool(theMap) {
  131. theMap.removeInteraction(this.draw);
  132. if (this.vector) {
  133. this.vector.getSource().clear();
  134. }
  135. debugger;
  136. },
  137. /**
  138. * 添加绘制交互
  139. * */
  140. addInteraction() {
  141. if (this.source === '' || this.vector === '') {
  142. this.initVectorLayer();
  143. }
  144. this.draw = new Draw({
  145. source: this.source,
  146. type: this.type,
  147. style: new Style({
  148. fill: new Fill({
  149. color: 'rgba(255, 255, 255, 0.2)',
  150. }),
  151. stroke: new Stroke({
  152. color: 'rgba(0, 0, 0, 0.5)',
  153. lineDash: [10, 10],
  154. width: 2,
  155. }),
  156. image: new Circle({
  157. radius: 5,
  158. stroke: new Stroke({
  159. color: 'rgba(0, 0, 0, 0.7)',
  160. }),
  161. fill: new Fill({
  162. color: 'rgba(255, 255, 255, 0.2)',
  163. }),
  164. }),
  165. }),
  166. });
  167. this.map.addInteraction(this.draw);
  168. this.initMeasureTool();
  169. this.createMeasureTooltip();
  170. this.createHelpTooltip();
  171. let listener;
  172. this.draw.on('drawstart', (evt) => {
  173. this.sketch = evt.feature;
  174. /** @type {import("../src/ol/coordinate.js").Coordinate|undefined} */
  175. let tooltipCoord = evt.coordinate;
  176. listener = this.sketch.getGeometry().on('change', (evt) => {
  177. const geom = evt.target;
  178. if (geom instanceof Polygon) {
  179. this.figure = this.formatArea(geom);
  180. tooltipCoord = geom.getInteriorPoint().getCoordinates();
  181. } else if (geom instanceof LineString) {
  182. this.figure = this.formatLength(geom);
  183. tooltipCoord = geom.getLastCoordinate();
  184. }
  185. this.measureTooltipElement.innerHTML = this.figure;
  186. this.measureTooltip.setPosition(tooltipCoord);
  187. });
  188. });
  189. this.draw.on('drawend', () => {
  190. this.$emit('update:output', this.figure);
  191. this.measureTooltipElement.className = 'ol-tooltip ol-tooltip-static';
  192. this.measureTooltip.setOffset([0, -7]);
  193. // 清空sketch,这样就可以新建一个sketch
  194. this.sketch = null;
  195. this.measureTooltipElement = null;
  196. this.createMeasureTooltip();
  197. unByKey(listener);
  198. });
  199. },
  200. formatLength(line) {
  201. const length = getLength(line, {
  202. projection: "EPSG:4490"
  203. });
  204. let output;
  205. if (length > 1000) {
  206. output = Math.round((length / 1000) * 100) / 100 + ' ' + 'km';
  207. } else {
  208. output = Math.round(length * 100) / 100 + ' ' + 'm';
  209. }
  210. return output;
  211. },
  212. formatArea(polygon) {
  213. const area = getArea(polygon, {
  214. projection: "EPSG:4490"
  215. });
  216. let output;
  217. if (area > 10000) {
  218. output = Math.round((area / 1000000) * 100) / 100 + ' ' + 'km²';
  219. } else {
  220. output = Math.round(area * 100) / 100 + ' ' + 'm²';
  221. }
  222. return output;
  223. },
  224. /**
  225. * 创建新的帮助提示
  226. */
  227. createHelpTooltip() {
  228. if (this.helpTooltipElement) {
  229. this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement);
  230. this.map.removeOverlay(this.map.getOverlayById('helpTooltip_overlay'));
  231. }
  232. this.helpTooltipElement = document.createElement('div');
  233. this.helpTooltipElement.className = 'ol-tooltip hidden';
  234. this.helpTooltip = new Overlay({
  235. id: 'helpTooltip_overlay',
  236. element: this.helpTooltipElement,
  237. offset: [15, 0],
  238. positioning: 'center-left',
  239. });
  240. this.map.addOverlay(this.helpTooltip);
  241. },
  242. /**
  243. * 创建新的测量提示
  244. */
  245. createMeasureTooltip() {
  246. if (this.measureTooltipElement) {
  247. this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement);
  248. this.map.removeOverlay(this.map.getOverlayById('measureTooltip_overlay'));
  249. }
  250. this.measureTooltipElement = document.createElement('div');
  251. this.measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure';
  252. this.measureTooltip = new Overlay({
  253. id: 'measureTooltip_overlay',
  254. element: this.measureTooltipElement,
  255. offset: [0, -15],
  256. positioning: 'bottom-center',
  257. stopEvent: false,
  258. insertFirst: false,
  259. });
  260. this.map.addOverlay(this.measureTooltip);
  261. },
  262. }
  263. }
  264. </script>
  265. <style>
  266. .ol-control button {
  267. background-color: rgba(24, 129, 253, 0.6);
  268. }
  269. .ol-control button:focus, .ol-control button:hover {
  270. text-decoration: none;
  271. background-color: rgba(24, 129, 253, .8)
  272. }
  273. .ol-scale-line {
  274. background-color: rgba(24, 129, 253, 0.6);
  275. }
  276. .ol-tooltip {
  277. position: relative;
  278. background: rgba(0, 0, 0, 0.5);
  279. border-radius: 4px;
  280. color: white;
  281. padding: 4px 8px;
  282. opacity: 0.7;
  283. white-space: nowrap;
  284. font-size: 12px;
  285. cursor: default;
  286. user-select: none;
  287. }
  288. .ol-tooltip-measure {
  289. opacity: 1;
  290. font-weight: bold;
  291. }
  292. .ol-tooltip-static {
  293. background-color: #ffcc33;
  294. color: black;
  295. border: 1px solid white;
  296. }
  297. .ol-tooltip-measure:before,
  298. .ol-tooltip-static:before {
  299. border-top: 6px solid rgba(0, 0, 0, 0.5);
  300. border-right: 6px solid transparent;
  301. border-left: 6px solid transparent;
  302. content: "";
  303. position: absolute;
  304. bottom: -6px;
  305. margin-left: -7px;
  306. left: 50%;
  307. }
  308. .ol-tooltip-static:before {
  309. border-top-color: #ffcc33;
  310. }
  311. </style>