fence.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <template>
  2. <div id="fence">
  3. <el-row>
  4. <el-col :span="24" class="main">
  5. <el-col :span="3" style="margin-bottom: 10px">
  6. <slot name="back"></slot>
  7. </el-col>
  8. <template v-if="type === 'draw'">
  9. <el-col :span="6">
  10. <el-button size="small" @click="drawPolygon" v-if="!isDraw()">绘制多边形</el-button>
  11. <el-button size="small" @click="drawRectangle" v-if="!isDraw()">绘制矩形</el-button>
  12. <el-button size="small" @click="clearDraw" v-if="isDraw()">重新绘制</el-button>
  13. <el-button size="small" @click="returnToDraw" v-if="isDraw()">重新选择绘制图形</el-button>
  14. <el-button size="small" type="primary" @click="toSave" v-if="isDraw()">保存</el-button>
  15. </el-col>
  16. <el-col :span="8">
  17. <span style="color: red" v-if="isDraw() === 'polygon'">您处于绘制多边形状态.双击最后的位置结束绘制</span>
  18. <span style="color: red" v-if="isDraw() === 'rectangle'">您处于绘制矩形状态.点击后进行拖拽,松开结束绘制</span>
  19. </el-col>
  20. </template>
  21. <template v-if="type === 'edit'">
  22. <el-col :span="6">
  23. <el-button size="small" type="primary" @click="toStart" v-if="!editing">编辑</el-button>
  24. <el-button size="small" type="primary" @click="toEnd" v-if="editing">保存</el-button>
  25. <el-button size="small" type="primary" @click="reDraw">重新绘制</el-button>
  26. </el-col>
  27. </template>
  28. <el-col :span="6">
  29. <el-input v-model="keyword" size="small" id="input" placeholder="请输入要查询的地点">
  30. <template #append>
  31. <el-button type="primary" @click="mapSearch">查询</el-button>
  32. </template>
  33. </el-input>
  34. </el-col>
  35. <el-col :span="24" class="one">
  36. <div id="container"></div>
  37. </el-col>
  38. </el-col>
  39. </el-row>
  40. </div>
  41. </template>
  42. <script>
  43. import drawTools from '@/util/draw';
  44. import MapLoader from '@/plugins/amap';
  45. export default {
  46. name: 'fence',
  47. props: {
  48. form: { type: Object, default: () => {} },
  49. drawList: { type: Array },
  50. },
  51. model: {
  52. prop: 'form',
  53. event: 'change',
  54. },
  55. components: {},
  56. data: function () {
  57. return {
  58. map: undefined,
  59. center: [125.324667, 43.883476],
  60. mapStyle: 'amap://styles/387f96e0666b7d5aec6e11cffa97c91a',
  61. // 绘制
  62. mouseTool: undefined,
  63. drawForm: {},
  64. dialog: false,
  65. levelList: drawTools.levelList,
  66. editor: undefined,
  67. editing: false,
  68. type: 'draw', // 类型模式:draw--画;edit--改
  69. keyword: undefined,
  70. searchPlugins: undefined,
  71. };
  72. },
  73. created() {},
  74. mounted() {
  75. this.init();
  76. },
  77. methods: {
  78. async toSave() {
  79. const fence = _.cloneDeep(this.drawForm);
  80. this.$emit('save', fence);
  81. },
  82. async init() {
  83. if (!_.get(window, 'AMap')) await MapLoader();
  84. if (this.map) this.map.destroy();
  85. let that = this;
  86. let map = new AMap.Map('container', {
  87. zoom: '11.5',
  88. resizeEnable: true,
  89. viewMode: '2D',
  90. center: this.center,
  91. // mapStyle: this.mapStyle,
  92. });
  93. await this.initMapSearch();
  94. await drawTools.initSearchAutoComplete('input');
  95. // 无围栏信息,画
  96. AMap.plugin(['AMap.MouseTool'], function () {
  97. that.mouseTool = new AMap.MouseTool(map);
  98. });
  99. map.on('complete', () => {
  100. this.map = map;
  101. this.mouseTool.on('draw', this.drawFinish);
  102. if (_.get(this.form, 'fence.type')) {
  103. // 有围栏信息,复现,改
  104. this.initGraphic();
  105. this.type = 'edit';
  106. }
  107. this.drawInMap(this.drawList);
  108. });
  109. },
  110. drawInMap(list = []) {
  111. if (!_.isArray(list)) return;
  112. for (const i of list) {
  113. const { type } = i;
  114. let obj;
  115. if (type === 'polygon') obj = drawTools.initPolygon(i);
  116. else obj = drawTools.initRectangle(i);
  117. this.map.add(obj);
  118. }
  119. },
  120. async initMapSearch() {
  121. this.searchPlugins = await drawTools.initSearch({ city: '长春' });
  122. },
  123. mapSearch() {
  124. // 根据关键字进行搜索
  125. this.searchPlugins.search(this.keyword, (status, result) => {
  126. // 先做简单的.只拿第一个,然后将中心点定过去
  127. if (result.info !== 'OK') return;
  128. const list = _.get(result, 'poiList.pois');
  129. const poi = _.head(list);
  130. const point = [_.get(poi, 'location.lng'), _.get(poi, 'location.lat')];
  131. this.map.setCenter(point, true, 0);
  132. const mark = drawTools.initMark({ position: point });
  133. this.map.add(mark);
  134. });
  135. },
  136. // 改
  137. async initGraphic() {
  138. const data = _.get(this.form, 'fence');
  139. if (!data) return;
  140. const { type } = data;
  141. let obj;
  142. // 生成画过的图形
  143. if (type === 'polygon') obj = drawTools.initPolygon(data);
  144. else obj = drawTools.initRectangle(data);
  145. // 加入地图
  146. this.map.add(obj);
  147. // 加载插件
  148. let editor;
  149. if (type === 'polygon') {
  150. this.drawForm.type = 'polygon';
  151. editor = new AMap.PolyEditor(this.map, obj);
  152. editor.on('end', (e) => {
  153. this.editDrawFinish(e);
  154. this.toSave();
  155. });
  156. } else {
  157. this.drawForm.type = 'rectangle';
  158. editor = new AMap.RectangleEditor(this.map, obj);
  159. editor.on('end', (e) => {
  160. this.editDrawFinish(e);
  161. this.toSave();
  162. });
  163. }
  164. this.editor = editor;
  165. },
  166. toStart() {
  167. this.editor.open();
  168. this.editing = true;
  169. },
  170. toEnd() {
  171. this.editor.close();
  172. this.editing = false;
  173. },
  174. // 画
  175. // 结束绘制事件触发
  176. clearDraw() {
  177. this.mouseTool.close(true);
  178. const type = _.get(this.drawForm, 'type');
  179. if (type === 'polygon') this.drawPolygon();
  180. else this.drawRectangle();
  181. },
  182. returnToDraw() {
  183. this.mouseTool.close(true);
  184. this.$set(this, 'drawForm', {});
  185. },
  186. // 结束绘制数据处理部分
  187. drawFinish(e) {
  188. let path;
  189. if (_.get(this.drawForm, 'type') === 'polygon') {
  190. path = _.get(e, 'obj._opts.path');
  191. if (!path) {
  192. this.$message.error('未获取到绘制图形的坐标');
  193. return false;
  194. }
  195. } else if (_.get(this.drawForm, 'type') === 'rectangle') {
  196. path = _.chunk(_.flattenDeep(_.get(e, 'obj.aE')), 2);
  197. }
  198. this.drawForm.range = path;
  199. },
  200. // 结束绘制数据处理部分
  201. editDrawFinish(e) {
  202. let path;
  203. if (_.get(this.drawForm, 'type') === 'polygon') {
  204. path = _.get(e, 'target._opts.path');
  205. if (!path) {
  206. this.$message.error('未获取到绘制图形的坐标');
  207. return false;
  208. }
  209. } else if (_.get(this.drawForm, 'type') === 'rectangle') {
  210. path = _.chunk(_.flattenDeep(_.get(e, 'target.aE')), 2);
  211. if (!path) {
  212. this.$message.error('未获取到绘制图形的坐标');
  213. return false;
  214. }
  215. }
  216. this.drawForm.range = path;
  217. },
  218. // 画多边形
  219. drawPolygon() {
  220. drawTools.drawPolygon(this.mouseTool);
  221. this.$set(this.drawForm, 'type', 'polygon');
  222. },
  223. // 画矩形
  224. drawRectangle() {
  225. drawTools.drawRectangle(this.mouseTool);
  226. this.$set(this.drawForm, 'type', 'rectangle');
  227. },
  228. isDraw() {
  229. const r = _.get(this.drawForm, 'type');
  230. return r;
  231. },
  232. // 重新绘制
  233. reDraw() {
  234. this.type = 'draw';
  235. this.map.clearMap();
  236. this.drawForm = {};
  237. this.form.fencen = {};
  238. },
  239. },
  240. metaInfo() {
  241. return { title: this.$route.meta.title };
  242. },
  243. beforeDestroy() {
  244. this.map.destroy();
  245. },
  246. };
  247. </script>
  248. <style lang="less" scoped>
  249. #container {
  250. width: 100%;
  251. height: 750px;
  252. overflow: hidden;
  253. }
  254. </style>