Draw.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. <template>
  2. <view class="openlayer-map-draw">
  3. <view :pos="position" :change:pos="olMap.createPolygon" style="display: none;"></view>
  4. <view :domId="mapId" :change:domId="olMap.initMap" style="display: none;"></view>
  5. <view :id="mapId" class="map"></view>
  6. <view class="btns">
  7. <button class="btn" type="default" @tap="olMap.handleStart">开始绘制</button>
  8. <button class="btn" type="default" @tap="olMap.handleClear">清除绘制</button>
  9. <button class="btn" type="default" @tap="olMap.handleSubmit">完成绘制</button>
  10. </view>
  11. </view>
  12. </template>
  13. <script>
  14. export default {
  15. name: "openlayer-map-draw",
  16. props: {
  17. coordinates: {
  18. type: Array,
  19. required: false,
  20. default: () => {
  21. return []
  22. }
  23. }
  24. },
  25. data() {
  26. return {
  27. position: [],
  28. mapId: 'ol-map' + ('000000' + Math.floor(Math.random() * 999999)).slice(-6),
  29. };
  30. },
  31. methods: {
  32. //给renderJS调用的方法
  33. methodForRenderJs: async function(val) {
  34. if (val.type === 'startInitOlMap') {
  35. uni.showLoading({
  36. title: "地图加载中..."
  37. })
  38. }
  39. // 地图初始化完成,绘制传入坐标
  40. if (val.type === 'changeSize') {
  41. this.position = this.coordinates;
  42. uni.hideLoading()
  43. }
  44. if (val.type === 'isStop') {
  45. uni.$msg('已有范围,请先清除后重新绘制')
  46. }
  47. if (val.type === 'needStart') {
  48. uni.$msg('请先绘制范围')
  49. }
  50. if (val.type === 'submit') {
  51. uni.$msg('提交')
  52. console.log(val.coords)
  53. if(val.coords && val.coords.length){
  54. this.$emit('onSubmit', val.coords)
  55. }
  56. }
  57. }
  58. }
  59. }
  60. </script>
  61. <script lang="renderjs" module="olMap">
  62. import Map from 'ol/Map.js';
  63. import View from 'ol/View.js';
  64. import {
  65. defaults as defaultControls
  66. } from 'ol/control.js';
  67. import {
  68. getWidth,
  69. getTopLeft
  70. } from 'ol/extent.js';
  71. import TileLayer from 'ol/layer/Tile.js';
  72. import {
  73. get as getProjection
  74. } from 'ol/proj.js';
  75. import {
  76. fromLonLat
  77. } from "ol/proj";
  78. import WMTS from 'ol/source/WMTS.js';
  79. import WMTSTileGrid from 'ol/tilegrid/WMTS.js';
  80. import Feature from 'ol/Feature';
  81. import Point from 'ol/geom/Point';
  82. import Polygon from 'ol/geom/Polygon';
  83. import {
  84. Icon,
  85. Style
  86. } from 'ol/style';
  87. import VectorSource from 'ol/source/Vector';
  88. import {
  89. Vector as VectorLayer
  90. } from 'ol/layer';
  91. import Fill from 'ol/style/Fill';
  92. import Text from 'ol/style/Text';
  93. import Stroke from 'ol/style/Stroke';
  94. import Circle from 'ol/style/Circle';
  95. import { Draw } from "ol/interaction";
  96. export default {
  97. name: "openlayer-map",
  98. data() {
  99. return {
  100. map: null,
  101. points: [],
  102. polygonLayer: null,
  103. pointsLayer: null,
  104. drawStatus: 'start',
  105. drawSource: null,
  106. draw: null
  107. };
  108. },
  109. methods: {
  110. WMTS_Layer(url) {
  111. if (!url) return null
  112. let projection = getProjection('EPSG:4326')
  113. let extent = projection.getExtent()
  114. let width = getWidth(extent)
  115. let resolutions = [],
  116. matrixIds = []
  117. for (let z = 1; z < 19; z++) {
  118. resolutions[z] = width / (256 * Math.pow(2, z))
  119. matrixIds[z] = z
  120. }
  121. let tileGrid = new WMTSTileGrid({
  122. origin: getTopLeft(extent),
  123. resolutions,
  124. matrixIds
  125. })
  126. // 匹配坐标系、图层类型
  127. let type = url.match(new RegExp(/\/(.{3})_(c|w)\//))
  128. return new TileLayer({
  129. source: new WMTS({
  130. crossOrigin: 'anonymous',
  131. url: url,
  132. layer: type[1],
  133. matrixSet: type[2],
  134. format: 'tiles',
  135. style: 'default',
  136. wrapX: true,
  137. projection: projection,
  138. tileGrid
  139. })
  140. })
  141. },
  142. initMap(domId) {
  143. var webKey = '15f7b01aababbb39ab568f4ba12ea21c';
  144. let wmtsUrl_1 = 'http://t{0-7}.tianditu.gov.cn/vec_c/wmts?tk=' + webKey;
  145. let wmtsUrl_2 = 'http://t{0-7}.tianditu.gov.cn/cva_c/wmts?tk=' + webKey;
  146. let center = [104.93616806129798, 33.38784018924233]
  147. this.$ownerInstance.callMethod('methodForRenderJs', {
  148. type: 'startInitOlMap'
  149. });
  150. setTimeout(() => {
  151. this.map = new Map({
  152. target: domId,
  153. view: new View({
  154. projection: 'EPSG:4326',
  155. center: center,
  156. zoom: 16,
  157. maxZoom: 22,
  158. minZoom: 1
  159. }),
  160. controls: defaultControls({
  161. zoom: false,
  162. rotate: false,
  163. attribution: false
  164. })
  165. });
  166. let layer = this.WMTS_Layer(wmtsUrl_1)
  167. this.map.addLayer(layer)
  168. let layer1 = this.WMTS_Layer(wmtsUrl_2)
  169. this.map.addLayer(layer1)
  170. this.map.updateSize()
  171. // 先注册一下绘制面图层
  172. this.drawSource = new VectorSource({});
  173. this.map.addLayer(new VectorLayer({
  174. source: this.drawSource
  175. }))
  176. this.$ownerInstance.callMethod('methodForRenderJs', {
  177. type: 'changeSize'
  178. });
  179. }, 3000);
  180. },
  181. handleClear() {
  182. this.drawStatus = 'clear'
  183. this.map.removeLayer(this.polygonLayer)
  184. this.map.removeLayer(this.pointsLayer)
  185. this.map.removeInteraction(this.draw)
  186. this.draw = null
  187. this.polygonLayer = null
  188. this.pointsLayer = null
  189. this.drawSource.clear()
  190. },
  191. handleSubmit() {
  192. if(!this.draw || this.drawStatus !== 'start'){
  193. this.$ownerInstance.callMethod('methodForRenderJs', {
  194. type: 'needStart'
  195. });
  196. return;
  197. }
  198. this.draw.finishDrawing()
  199. let features = this.drawSource.getFeatures()
  200. if(!features.length){
  201. this.$ownerInstance.callMethod('methodForRenderJs', {
  202. type: 'needStart'
  203. });
  204. return;
  205. }
  206. let coords = features[0].getGeometry().getCoordinates()
  207. this.$ownerInstance.callMethod('methodForRenderJs', {
  208. type: 'submit',
  209. coords: coords
  210. });
  211. this.drawStatus = 'stop'
  212. },
  213. handleStart() {
  214. if(this.drawStatus === 'stop'){
  215. this.$ownerInstance.callMethod('methodForRenderJs', {
  216. type: 'isStop'
  217. });
  218. return;
  219. }
  220. this.draw = new Draw({
  221. source: this.drawSource,
  222. type: 'Polygon',
  223. style: new Style({
  224. stroke: new Stroke({
  225. color: 'red',
  226. width: 2
  227. }),
  228. fill: new Fill({
  229. color: 'pink'
  230. })
  231. })
  232. })
  233. this.map.addInteraction(this.draw);
  234. this.draw.on("drawend", (evt) => {
  235. console.log("结束绘制");
  236. console.log(evt);
  237. });
  238. this.drawStatus = 'start'
  239. },
  240. createPolygon(coordinates) {
  241. if (!coordinates.length || !this.map) {
  242. return
  243. }
  244. this.drawStatus = 'stop'
  245. this.points = JSON.parse(JSON.stringfy(coordinates))
  246. // 绘制顶点
  247. let pointStyle = new Style({
  248. image: new Circle({
  249. radius: 20,
  250. fill: new Fill({
  251. color: 'yellow'
  252. })
  253. })
  254. })
  255. let pointsVector = new VectorSource({});
  256. coordinates.forEach(item => {
  257. let pointFeature = new Feature({
  258. geometry: new Point(item)
  259. });
  260. pointFeature.setStyle(pointStyle)
  261. pointsVector.addFeature(pointFeature)
  262. })
  263. this.pointsLayer = new VectorLayer({
  264. source: pointsVector
  265. });
  266. this.map.addLayer(this.pointsLayer);
  267. // 绘制面
  268. var iconFeature = new Feature({
  269. geometry: new Polygon(coordinates)
  270. });
  271. var iconStyle = new Style({
  272. fill: new Fill({
  273. color: 'pink'
  274. })
  275. });
  276. iconFeature.setStyle(iconStyle);
  277. var vectorSource = new VectorSource({});
  278. vectorSource.addFeature(iconFeature)
  279. this.polygonLayer = new VectorLayer({
  280. source: vectorSource
  281. });
  282. this.map.addLayer(this.polygonLayer);
  283. }
  284. },
  285. beforeUnmount() {
  286. this.map && this.map.dispose();
  287. this.map = null;
  288. }
  289. }
  290. </script>
  291. <style lang="scss" scoped>
  292. .openlayer-map-draw {
  293. width: 100%;
  294. height: 100%;
  295. position: relative;
  296. .map {
  297. width: 100%;
  298. height: 100%;
  299. }
  300. .btns {
  301. position: absolute;
  302. bottom: 0;
  303. right: 0;
  304. width: 100%;
  305. display: flex;
  306. justify-content: space-between;
  307. align-items: center;
  308. .btn {
  309. height: 35px;
  310. line-height: 35px;
  311. flex: 0 0 30%;
  312. }
  313. }
  314. }
  315. </style>