customize_leaflet.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. import * as L from 'leaflet'
  2. import 'leaflet/dist/leaflet.css'
  3. import 'leaflet-editable/src/Leaflet.Editable'
  4. import 'leaflet-draw/dist/leaflet.draw'
  5. import 'leaflet-draw/dist/leaflet.draw.css'
  6. import visualization_icon_camera from '@/assets/images/visualControl/visualization_icon_camera.png'
  7. import visualization_icon_equipments from '@/assets/images/visualControl/visualization_icon_equipments.png'
  8. export default function(config) {
  9. const defaultConfig = {
  10. el: 'map',
  11. defaultColor: '#11b9e8',
  12. activeColor: 'orange',
  13. addColor: '#f90',
  14. editColor: '#ff0000',
  15. maxBounds: [[-40000, -40000], [40000, 40000]],
  16. mapReadonly: false,
  17. zoomControl: true,
  18. updateDataEvent: function() {
  19. return true
  20. },
  21. clickDataEvent: function() {
  22. },
  23. contextmenu: function() {
  24. },
  25. saveResult: function() {
  26. },
  27. mapclick: function() {
  28. }
  29. }
  30. const currentConfig = {}
  31. for (const key in defaultConfig) {
  32. try {
  33. if (config[key] !== undefined) {
  34. currentConfig[key] = config[key]
  35. } else {
  36. currentConfig[key] = defaultConfig[key]
  37. }
  38. } catch (e) {
  39. currentConfig[key] = defaultConfig[key]
  40. }
  41. }
  42. const _this = this
  43. const DATA_CONST = {
  44. READ_ONLY: -1,
  45. DEFAULT: 0,
  46. ADD: 1,
  47. EDITOR: 2
  48. }
  49. this.editType = 0
  50. let currentEditorCover = null
  51. if (currentConfig.mapReadonly) {
  52. this.editType = DATA_CONST.READ_ONLY
  53. }
  54. function setCurrentEditorCover(editorCover) {
  55. if (editorCover) {
  56. currentEditorCover = editorCover
  57. }
  58. }
  59. function disableCurrentEditorCover() {
  60. if (currentEditorCover) {
  61. currentEditorCover.disableEdit()
  62. }
  63. }
  64. function getDataMap(layerItem) {
  65. const dataMap = new LayerItem()
  66. dataMap.set('type', layerItem.options.type)
  67. dataMap.set('options', layerItem.options)
  68. switch (layerItem.options.type) {
  69. case 'polygon': // 多边形
  70. dataMap.set('latlngs', layerItem._latlngs[0])
  71. break
  72. case 'marker':
  73. dataMap.set('latlngs', layerItem._latlngs || layerItem['_latlng'])
  74. break
  75. }
  76. return dataMap
  77. }
  78. this.saveEditorCover = function(callback) {
  79. const dataMap = new LayerItem()
  80. var type = 'polygon'
  81. var latlngs = null
  82. if (_this.layerType === 'facility' || _this.layerType === 'camera' || _this.layerType === 'marker') {
  83. type = 'marker'
  84. latlngs = currentEditorCover._latlng
  85. } else {
  86. latlngs = currentEditorCover._latlngs[0]
  87. }
  88. dataMap.set('type', type)
  89. dataMap.set('latlngs', latlngs)
  90. dataMap.set('options', currentEditorCover.options)
  91. dataMap.set('layerType', _this.layerType)
  92. currentConfig.updateDataEvent(dataMap).then((flag) => {
  93. if (flag) {
  94. disableCurrentEditorCover()
  95. _this.editType = DATA_CONST.DEFAULT
  96. arr.push(dataMap)
  97. if (callback) {
  98. callback(dataMap)
  99. return
  100. }
  101. addData()
  102. }
  103. })
  104. }
  105. this.getEditType = function() {
  106. return _this.editType
  107. }
  108. this.addArea = function() {
  109. _this.layerType = 'area'
  110. _this.editType = DATA_CONST.ADD
  111. }
  112. /** 更换标记点 */
  113. this.changeLayerType = function(type, _editType = DATA_CONST.ADD) {
  114. _this.layerType = type
  115. _this.editType = _editType
  116. }
  117. this.setEditType = function(type) {
  118. _this.editType = type
  119. }
  120. const map = L.map(currentConfig.el, {
  121. crs: L.CRS.Simple, // 一个简单的CRS,可将经度和纬度直接映射到x其中y。可用于平面地图(例如游戏地图)
  122. zoom: 0,
  123. center: L.latLng(0, 0),
  124. maxBounds: currentConfig.maxBounds,
  125. doubleClickZoom: false,
  126. drawControl: false,
  127. attributionControl: false,
  128. zoomControl: currentConfig.zoomControl,
  129. editable: true
  130. })
  131. // L.EditControl = L.Control.extend({
  132. //
  133. // options: {
  134. // position: 'topleft',
  135. // callback: null,
  136. // kind: '',
  137. // html: ''
  138. // },
  139. //
  140. // onAdd: function (mapLayer) {
  141. // var container = L.DomUtil.create('div', 'leaflet-control leaflet-bar'),
  142. // link = L.DomUtil.create('a', '', container);
  143. //
  144. // link.href = '#';
  145. // link.title = 'Create a new ' + this.options.kind;
  146. // link.innerHTML = this.options.html;
  147. // L.DomEvent.on(link, 'click', L.DomEvent.stop)
  148. // .on(link, 'click', function () {
  149. // window.LAYER = this.options.callback.call(mapLayer.editTools);
  150. // }, this);
  151. //
  152. // return container;
  153. // }
  154. //
  155. // });
  156. //
  157. //
  158. // var drawnItems = new L.FeatureGroup();
  159. // mapLayer.addLayer(drawnItems);
  160. // var drawControl = new L.Control.Draw({
  161. // edit: {
  162. // featureGroup: drawnItems
  163. // }
  164. // });
  165. // mapLayer.addControl(drawControl);
  166. let arr = []
  167. function LayerItem() {
  168. this.type = null
  169. this.latlngs = null
  170. this.options = null
  171. this.set = (key, value) => {
  172. this[key] = value
  173. }
  174. this.get = (key) => {
  175. return this[key]
  176. }
  177. }
  178. var layerGroup = L.layerGroup().addTo(map)
  179. var layerImageCoverGroup = L.layerGroup().addTo(map)
  180. this.setRasterLayer = function(imagePath) {
  181. const imageFile = new Image()
  182. imageFile.src = imagePath
  183. imageFile.onload = function() {
  184. // 设定图片视图的范围为当前的图片宽高
  185. const height = imageFile.height; const width = imageFile.width
  186. const imageOverlay = L.imageOverlay(imagePath, [[-(height / 2), -(width / 2)], [(height / 2), (width / 2)]])
  187. layerImageCoverGroup.clearLayers()
  188. imageOverlay.addTo(layerImageCoverGroup)
  189. }
  190. clearData()
  191. }
  192. this.setMapData = function(layerArr) {
  193. arr = []
  194. layerArr.forEach((item) => {
  195. const tempLayerItem = new LayerItem()
  196. for (const k in item) {
  197. tempLayerItem.set(k, item[k])
  198. }
  199. arr.push(tempLayerItem)
  200. })
  201. addData(arr)
  202. }
  203. // mapLayer.on(L.Draw.Event.CREATED, function (e) {
  204. // var type = e.layerType,
  205. // layer = e.layer;
  206. // let dataMap = new Map();
  207. // dataMap.set("type", type);
  208. // switch (type) {
  209. // case 'polyline':
  210. // case 'polygon':
  211. // case 'rectangle':
  212. // dataMap.set("latlngs", layer._latlngs);
  213. // break;
  214. // case 'marker':
  215. // case 'circlemarker':
  216. // dataMap.set("latlngs", layer._latlng);
  217. // break;
  218. // case 'circle':
  219. // dataMap.set("latlngs", layer._latlng);
  220. // dataMap.set("radius", layer._mRadius);
  221. // break;
  222. // }
  223. // arr.push(dataMap);
  224. // console.log(e.layer)
  225. // console.log(type)
  226. // // 由于部分其他效果直接每次重绘
  227. // addData();
  228. //
  229. // // 图层组
  230. // // layerGroup.addLayer(layer)
  231. // // 直接在地图添加不方便管理,所以选择图层组存放数据
  232. // // mapLayer.addLayer(layer);
  233. // });
  234. function clearData() {
  235. layerGroup.clearLayers()
  236. L.popup()
  237. .setLatLng([1, 2])
  238. .setContent(`<p>1212</p>`)
  239. .openOn(map)
  240. .remove()
  241. }
  242. function addData() {
  243. // 默认先清楚数据
  244. clearData()
  245. const fn = function(ary, key) {
  246. return ary.reduce((total, next) => {
  247. const index = total.findIndex((item) => {
  248. return item[key] === 'marker'
  249. })
  250. return index === -1 ? total.push(next) && total : total.splice(index, 0, next) && total
  251. }, [])
  252. }
  253. arr = fn(arr, 'type')// 按照类型组合arr
  254. var items = document.getElementById(currentConfig.el)
  255. .getElementsByClassName('leaflet-interactive')
  256. for (let i = 0; i < arr.length; i++) {
  257. switch (arr[i].get('type')) {
  258. case 'polyline': // 折线
  259. L.polyline(arr[i].get('latlngs'), { color: 'red' }).addTo(layerGroup)
  260. break
  261. case 'marker': // 标记
  262. // eslint-disable-next-line no-case-declarations
  263. const layerType = arr[i].layerType
  264. // eslint-disable-next-line no-case-declarations
  265. const title = layerType === 'camera' ? '摄像头' : '设备'
  266. var myimage = L.icon({
  267. iconUrl: layerType === 'camera' ? visualization_icon_camera : visualization_icon_equipments,
  268. iconSize: [38, 38],
  269. popupAnchor: [50, 0]
  270. })
  271. L.marker(arr[i].get('latlngs'), {
  272. layerId: arr[i].get('layerId'),
  273. id: arr[i].get('id'),
  274. equipId: arr[i].get('equipId'),
  275. icon: myimage,
  276. title: title
  277. // draggable:true
  278. }).on('click', function(item) {
  279. for (let j = 0; j < items.length; j++) {
  280. items[j].classList.remove('stroke-dasharray')
  281. }
  282. this.options.type = 'marker'
  283. const tempDataMap = getDataMap(this)
  284. currentConfig.clickDataEvent(tempDataMap)
  285. L.popup()
  286. .setLatLng(item.latlng)
  287. .setContent(`<p>${title}</p>`)
  288. .openOn(map)
  289. }).on('mouseover', function() {
  290. // L.popup()
  291. // .setLatLng(item.latlng)
  292. // .setContent('<p>Hello world!<br />This is a nice popup.</p>')
  293. // .openOn(mapLayer);
  294. }).on('dragend', function() {
  295. // 拖拽回调
  296. // let latlng=item.target['_latlng'];
  297. // this.setLatLng([latlng.lat,latlng.lng]);
  298. // setCurrentEditorCover(this)
  299. // _this.layerType='marker';
  300. // currentConfig.saveResult();
  301. })
  302. .addTo(layerGroup)
  303. break
  304. case 'polygon':
  305. break
  306. case 'rectangle': // 矩形
  307. L.rectangle(arr[i].get('latlngs'), { color: 'red' }).addTo(layerGroup)
  308. break
  309. case 'circle': // 圆圈
  310. L.circle(arr[i].get('latlngs'), { radius: arr[i].get('radius') }).addTo(layerGroup)
  311. break
  312. case 'circlemarker': // 圆圈标记
  313. L.circleMarker(arr[i].get('latlngs'), { radius: 10 }).addTo(layerGroup)
  314. break
  315. default:
  316. break
  317. }
  318. }
  319. }
  320. // 点击添加点位
  321. map.on('click', function(ev) {
  322. const x1 = {
  323. lat: ev.latlng.lat - 50,
  324. lng: ev.latlng.lng
  325. }
  326. const x2 = {
  327. lat: ev.latlng.lat + 50,
  328. lng: ev.latlng.lng
  329. }
  330. const y1 = {
  331. lat: ev.latlng.lat,
  332. lng: ev.latlng.lng - 50
  333. }
  334. const y2 = {
  335. lat: ev.latlng.lat,
  336. lng: ev.latlng.lng + 50
  337. }
  338. const latlngs = []
  339. latlngs.push(x1)
  340. latlngs.push(y1)
  341. latlngs.push(x2)
  342. latlngs.push(y2)
  343. if (_this.editType === DATA_CONST.ADD) {
  344. const layerType = _this.layerType
  345. console.log(layerType)
  346. if (layerType === 'facility' || layerType === 'camera' || layerType === 'marker') {
  347. var myimage = L.icon({
  348. iconUrl: layerType === 'camera' ? visualization_icon_camera : visualization_icon_equipments,
  349. iconSize: [38, 38],
  350. popupAnchor: [50, 0]
  351. })
  352. var marker = L.marker([ev.latlng.lat, ev.latlng.lng], {
  353. icon: myimage,
  354. title: layerType === 'camera' ? '摄像头' : '设备点',
  355. // draggable:true,
  356. type: _this.layerType
  357. }).addTo(layerGroup)
  358. setCurrentEditorCover(marker)
  359. currentConfig.mapclick({ marker, type: 'marker', layerType: layerType, remove: function() {
  360. marker.remove()
  361. } })
  362. } else {
  363. const polygon = L.polygon(latlngs, { color: currentConfig.addColor }).on('click', function() {
  364. }).on('dblclick', function() {
  365. if (_this.editType === DATA_CONST.EDITOR) {
  366. this.disableEdit()
  367. this.enableEdit()
  368. this.setStyle({
  369. color: currentConfig.editColor
  370. })
  371. this.redraw()
  372. }
  373. })
  374. .addTo(layerGroup)
  375. setCurrentEditorCover(polygon)
  376. currentConfig.mapclick({ polygon, type: 'polygon' })
  377. }
  378. _this.editType = DATA_CONST.EDITOR
  379. }
  380. })
  381. }