authenticMap.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. import config from "@/api/config.js";
  2. import * as KMap from "@/utils/ol-map/KMap";
  3. import * as util from "@/common/ol_common.js";
  4. import Style from "ol/style/Style";
  5. import Icon from "ol/style/Icon";
  6. import VectorLayer from "ol/layer/Vector.js";
  7. import WKT from "ol/format/WKT.js";
  8. import { reactive } from "vue";
  9. import Point from "ol/geom/Point.js";
  10. import Feature from "ol/Feature";
  11. import { newPoint } from "@/utils/map.js";
  12. import { Fill, Text,Circle,Stroke } from "ol/style";
  13. import { getArea } from "ol/sphere.js";
  14. import * as proj from "ol/proj";
  15. import proj4 from "proj4";
  16. import { register } from "ol/proj/proj4";
  17. import GeometryCollection from 'ol/geom/GeometryCollection.js';
  18. import { ElMessage } from "element-plus";
  19. import { useStore } from "vuex";
  20. proj4.defs(
  21. "EPSG:38572",
  22. "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs"
  23. );
  24. register(proj4);
  25. export let mapData = reactive({
  26. isEdit: false,
  27. isEditArea: false,
  28. curPointData: {},
  29. point: null,
  30. selectPointArr: [],
  31. isPointHide: null,
  32. disabledForm : false,
  33. selectPoint:''
  34. });
  35. function resetMapData(){
  36. mapData.isEdit= false
  37. mapData.isEditArea= false
  38. mapData.curPointData= {}
  39. mapData.point= null
  40. mapData.selectPointArr= []
  41. mapData.isPointHide= null
  42. mapData.disabledForm= false
  43. mapData.selectPoint= ''
  44. }
  45. /**
  46. * @description 地图层对象
  47. */
  48. class AuthenticMap {
  49. constructor() {
  50. let that = this;
  51. that.store = useStore();
  52. let vectorStyle = new KMap.VectorStyle();
  53. this.vectorStyle = vectorStyle;
  54. // 位置图标
  55. this.clickPointLayer = new KMap.VectorLayer("clickPointLayer", 9999, {
  56. style: (f) => {
  57. const style1 = new Style({
  58. image: new Icon({
  59. src: require(`@/assets/images/map/${f.get("icon")}-icon.png`),
  60. scale: 0.45,
  61. }),
  62. });
  63. const style2 = new Style({
  64. text: new Text({
  65. font: "16px sans-serif",
  66. text: f.get("masterName"),
  67. offsetY: -40,
  68. padding: [4, 3, 2, 106],
  69. fill: new Fill({ color: "#fff" }), // 字体颜色
  70. }),
  71. });
  72. const style3 = new Style({
  73. image: new Icon({
  74. src: require(`@/assets/images/map/${f.get("iconBg")}.png`),
  75. scale: 0.45,
  76. displacement: [0, 90],
  77. }),
  78. });
  79. return [style1, style2, style3];
  80. },
  81. });
  82. this.locationLayer = new KMap.VectorLayer("locationLayer", 9999, {
  83. style: () => {
  84. return new Style({
  85. image: new Icon({
  86. src: require("@/assets/images/map/location.png"),
  87. scale: 0.45,
  88. }),
  89. });
  90. },
  91. });
  92. this.selectPointLayer = new KMap.VectorLayer("selectPointLayer", 9999, {
  93. style: () => {
  94. return new Style({
  95. // geometry: new Point(coord[0][i]),
  96. image: new Circle({
  97. radius: 6,
  98. fill: new Fill({
  99. color: 'red'
  100. }),
  101. stroke: new Stroke({
  102. color: '#fff',
  103. width: 1
  104. }),
  105. }),
  106. });
  107. },
  108. });
  109. // 存储绘制的地块特征
  110. // this.drawnFeatures = [];
  111. }
  112. initMap(location, target) {
  113. let that = this
  114. let level = 16;
  115. let coordinate = util.wktCastGeom(location).getFirstCoordinate();
  116. this.kmap = new KMap.Map(
  117. target,
  118. level,
  119. coordinate[0],
  120. coordinate[1],
  121. null,
  122. 6,
  123. 22
  124. );
  125. this.kmap.initDraw((e) => {
  126. if (e.type === "drawend") {
  127. mapData.isEdit = true;
  128. mapData.point = e.feature;
  129. }
  130. });
  131. this.kmap.modifyDraw((e) => {
  132. if(e.type === "modifyend"){
  133. mapData.isEditArea = false;
  134. mapData.isEditArea = true;
  135. }
  136. }, function(e){
  137. let f = null
  138. that.kmap.map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
  139. f= feature
  140. },{hitTolerance:10});
  141. if(!f){
  142. return false
  143. }
  144. let res = f.get("id") === mapData.curPointData.id || !f.get("id")
  145. if(!res){
  146. ElMessage.warning("编辑中")
  147. }
  148. console.log('f.get("height")',f);
  149. res = f.get("height").length>0?false:res
  150. return res
  151. });
  152. this.kmap.addLayer(this.clickPointLayer.layer);
  153. this.kmap.addLayer(this.locationLayer.layer);
  154. this.kmap.addLayer(this.selectPointLayer.layer);
  155. this.addMapSingerClick();
  156. }
  157. fit(geometriesWkt){
  158. let geometries = []
  159. let f = new WKT();
  160. for(let wkt of geometriesWkt){
  161. geometries.push(f.readGeometry(wkt))
  162. }
  163. let extent = new GeometryCollection(geometries).getExtent()
  164. this.kmap.fit(extent)
  165. }
  166. //撤销上一个点
  167. undoLastDraw() {
  168. // const coordinates = this.kmap.getLayerFeatures()[0].getGeometry().getCoordinates()
  169. // coordinates[0][0].pop()
  170. // this.kmap.getLayerFeatures()[0].getGeometry().getCoordinates(coordinates)
  171. }
  172. // 取消地块
  173. cancelDraw() {
  174. this.kmap.polygonLayer.source.removeFeature(mapData.point);
  175. }
  176. // 添加点位
  177. addPoint(points) {
  178. const arrPoints = [];
  179. if (points && points.length > 0) {
  180. points.forEach((item) => {
  181. let f = newPoint({ ...item, icon: "point", iconBg: "name-bg" }, "point");
  182. arrPoints.push(f);
  183. });
  184. this.clickPointLayer.source.addFeatures(arrPoints);
  185. }
  186. }
  187. // 设置地图中心点位
  188. setMapCenter(v,isPoint = true) {
  189. let arrayOfNumbers = [];
  190. const arrayOfStrings = v.split(",");
  191. arrayOfNumbers = [arrayOfStrings[1], arrayOfStrings[0]];
  192. this.kmap.map.getView().setCenter(arrayOfNumbers);
  193. if(!isPoint) return
  194. this.locationLayer.source.clear();
  195. let point = new Feature(new Point(arrayOfNumbers));
  196. this.locationLayer.addFeature(point);
  197. }
  198. // 开始勾画
  199. startDraw() {
  200. this.kmap.setDefaultCursor("crosshair");
  201. this.kmap.startDraw();
  202. this.kmap.endModify();
  203. }
  204. //结束勾画
  205. endDraw() {
  206. this.kmap.endDraw();
  207. this.kmap.endModify();
  208. }
  209. // 开始编辑
  210. startModify(type) {
  211. this.kmap.startModify();
  212. this.kmap.endDraw();
  213. if(type==='upload'){
  214. const arr = this.kmap.getLayerFeatures()
  215. const lastItem = arr[arr.length - 1]
  216. mapData.point = lastItem
  217. mapData.point.set("icon", "point-act");
  218. this.kmap.polygonStyle(mapData.point);
  219. mapData.isPointHide = mapData.point;
  220. }else{
  221. mapData.point.set("icon", "point-act");
  222. }
  223. }
  224. //结束编辑
  225. endModify() {
  226. this.kmap.endModify();
  227. }
  228. // 清空单个数据
  229. clearMapData(name, val, id) {
  230. name && (mapData[name] = val);
  231. this.clickPointLayer.source.forEachFeature((feature) => {
  232. feature.set("icon", "point");
  233. feature.set("iconBg", "name-bg");
  234. });
  235. const points = this.kmap.getLayerFeatures();
  236. points.forEach((feature) => {
  237. feature.set("icon", "point");
  238. });
  239. resetMapData()
  240. }
  241. //全选
  242. allSelect(ids){
  243. let arr = []
  244. this.clickPointLayer.source.forEachFeature((feature) => {
  245. if(!ids || ids.findIndex((id)=> id == feature.get('id')) > -1){
  246. feature.set("icon", "point-act");
  247. feature.set("iconBg", "name-act-bg");
  248. }
  249. });
  250. const points = this.kmap.getLayerFeatures();
  251. points.forEach((feature) => {
  252. if(!ids || ids.findIndex((id)=> id == feature.get('id')) > -1) {
  253. feature.set("icon", "point-act");
  254. this.kmap.polygonStyle(feature);
  255. mapData.isPointHide = feature;
  256. arr.push(feature)
  257. }
  258. });
  259. mapData.selectPointArr = arr;
  260. }
  261. //no全选
  262. allUnSelect(){
  263. this.clickPointLayer.source.forEachFeature((feature) => {
  264. feature.set("icon", "point");
  265. feature.set("iconBg", "name-bg");
  266. });
  267. const points = this.kmap.getLayerFeatures();
  268. points.forEach((feature) => {
  269. feature.set("icon", "point");
  270. this.kmap.polygonStyle(feature);
  271. mapData.isPointHide = feature;
  272. });
  273. mapData.selectPointArr = [];
  274. }
  275. //选中高亮样式
  276. //选中点位方法
  277. selectPonitFun(map,evt){
  278. let that = this
  279. map.forEachFeatureAtPixel(evt.pixel, function (f, layer) {
  280. if (
  281. layer instanceof VectorLayer &&
  282. (
  283. layer.get("name") === "defaultPolygonLayer")
  284. ) {
  285. const features = map.getFeaturesAtPixel(evt.pixel);
  286. if (features.length > 0) {
  287. const feature = features[0];
  288. const geometry = feature.getGeometry();
  289. const coordinates = geometry.getCoordinates()[0]; // 获取多边形的顶点坐标
  290. if(Array.isArray(coordinates)){
  291. ElMessage.warning("编辑中")
  292. }else{
  293. ElMessage.success("已选择该点位")
  294. const features = f
  295. //代码可优化,明天优化
  296. if(mapData.selectPointArr.length>0){
  297. if(features.get("id")===mapData.selectPointArr[0].get("id")){
  298. const list = features.getGeometry().getCoordinates();
  299. const arr = list[0][0].find(subArray => subArray.includes(coordinates))
  300. that.selectPointLayer.source.clear();
  301. let point = new Feature(new Point(arr));
  302. that.selectPointLayer.addFeature(point);
  303. }
  304. }else{
  305. const list = mapData.point.getGeometry().getCoordinates();
  306. const arr = list[0][0].find(subArray => subArray.includes(coordinates))
  307. that.selectPointLayer.source.clear();
  308. let point = new Feature(new Point(arr));
  309. that.selectPointLayer.addFeature(point);
  310. }
  311. mapData.selectPoint = coordinates
  312. }
  313. }
  314. }
  315. });
  316. }
  317. // 地图点击事件
  318. addMapSingerClick() {
  319. let that = this;
  320. that.kmap.on("singleclick", (evt) => {
  321. if(mapData.curPointData.id && !mapData.disabledForm && mapData.selectPointArr.length===1){
  322. that.selectPonitFun(that.kmap.map,evt)
  323. return;
  324. }
  325. if(!mapData.curPointData.id && mapData.isEdit){
  326. that.selectPonitFun(that.kmap.map,evt)
  327. return;
  328. }
  329. //判断是否是导入的数据
  330. if(that.store.state.authentic.isEditStatus){
  331. that.selectPonitFun(that.kmap.map,evt)
  332. return;
  333. }
  334. let num = 0;
  335. that.kmap.map.forEachFeatureAtPixel(evt.pixel, function (feature, layer) {
  336. // 点击的图层是否是VectorLayer
  337. if (
  338. layer instanceof VectorLayer &&
  339. (layer.get("name") === "clickPointLayer" ||
  340. layer.get("name") === "defaultPolygonLayer")
  341. ) {
  342. // 每次点击,只走一遍该方法
  343. num = num + 1;
  344. if (num === 1) {
  345. that.getSelectPointArr(feature.get("id"));
  346. that.kmap.endDraw();
  347. }
  348. }
  349. });
  350. });
  351. }
  352. clearSelectPoint(){
  353. this.selectPointLayer.source.clear();
  354. }
  355. setPoint(name) {
  356. const arr = mapData.selectPointArr.filter(
  357. (item) => item.values_.icon === "point-act"
  358. );
  359. if (arr.length > 0) {
  360. mapData.point = arr[0];
  361. mapData.point.set("icon", name);
  362. mapData.isPointHide.set("icon", name);
  363. mapData.point.set("iconBg", "name-bg");
  364. }
  365. if (arr.length === 1) {
  366. mapData.selectPointArr = [];
  367. }
  368. }
  369. //添加地块
  370. setAreaGeometry(geometryArr) {
  371. let that = this;
  372. geometryArr.map((item) => {
  373. item.icon = "point";
  374. item.iconHide = "false";
  375. that.kmap.setLayerWkt(item.featureWkt, item);
  376. });
  377. }
  378. deletePointFun(point,callback){
  379. const coordinates = point.getGeometry().getCoordinates();
  380. let array = coordinates[0][0]
  381. const index = array.findIndex(subArray => subArray.includes(mapData.selectPoint))
  382. // 如果点存在,则删除它
  383. if (index > -1) {
  384. coordinates[0][0].splice(index, 1); // 删除点
  385. // 更新多边形的坐标
  386. point.getGeometry().setCoordinates(coordinates); // 更新几何形状
  387. }
  388. this.clearSelectPoint()
  389. callback && callback(index)
  390. }
  391. // 移除点的功能
  392. removePoint(callback) {
  393. // 获取多边形的所有坐标
  394. const features = this.kmap.getLayerFeatures()
  395. if(mapData.selectPointArr.length>0){
  396. features.forEach(item =>{
  397. if(item.get("id")===mapData.selectPointArr[0].get("id")){
  398. this.deletePointFun(item,callback)
  399. }
  400. })
  401. }else{
  402. this.deletePointFun(mapData.point,callback)
  403. }
  404. }
  405. // 获取所有选中点位
  406. getSelectPointArr(id) {
  407. const arr = [];
  408. this.clickPointLayer.source.forEachFeature((feature) => {
  409. if (feature.get("id") === id) {
  410. // 修改当前点位高亮
  411. const icon = feature.get("icon") === "point" ? "point-act" : "point";
  412. const iconBg =
  413. feature.get("iconBg") === "name-bg" ? "name-act-bg" : "name-bg";
  414. feature.set("icon", icon);
  415. feature.set("iconBg", iconBg);
  416. mapData.point = feature;
  417. mapData.curPointData = feature.values_;
  418. }
  419. if (feature.get("icon") === "point-act") {
  420. arr.push(feature);
  421. }
  422. });
  423. const points = this.kmap.getLayerFeatures();
  424. points.forEach((feature) => {
  425. if (feature.get("id") === id) {
  426. const icon = feature.get("icon") === "point" ? "point-act" : "point";
  427. feature.set("icon", icon);
  428. this.kmap.polygonStyle(feature);
  429. mapData.isPointHide = feature;
  430. }
  431. });
  432. mapData.selectPointArr = arr;
  433. }
  434. hidePoint() {
  435. const feature = mapData.isPointHide;
  436. feature.set("iconHide", "true");
  437. this.kmap.polygonStyle(feature);
  438. }
  439. clearLayer() {
  440. this.clickPointLayer.source.clear();
  441. this.kmap.polygonLayer.source.clear();
  442. }
  443. addLayer() {
  444. this.kmap.addLayer(this.kmap.polygonLayer.layer);
  445. this.kmap.addLayer(this.clickPointLayer.layer);
  446. }
  447. //获取地块信息
  448. getAreaGeometry(type) {
  449. let features = null
  450. if(type==='add') {
  451. features = [mapData.point]
  452. }else if(type==='upload'){
  453. features = this.kmap.getLayerFeatures()
  454. }else{
  455. if(mapData.curPointData.id){
  456. features = [this.kmap.getFeatureById(mapData.curPointData.id)];
  457. }else{
  458. features = [mapData.point]
  459. }
  460. }
  461. let geometryArr = [];
  462. let area = 0;
  463. // 获取图层上的Polygon,转成geoJson用于回显
  464. features.forEach((item) => {
  465. geometryArr.push({ featureWkt: new WKT().writeFeature(item) });
  466. let geom = item.getGeometry().clone();
  467. geom.transform(proj.get("EPSG:4326"), proj.get("EPSG:38572"));
  468. let areaItem = getArea(geom);
  469. area = (areaItem + areaItem / 2) / 1000;
  470. });
  471. return { geometryArr, area: area.toFixed(2) };
  472. }
  473. /**
  474. address
  475. farmName
  476. masterName
  477. masterTel
  478. speciesTypeName
  479. ""
  480. * @param form
  481. */
  482. search(form){
  483. const points = this.kmap.getLayerFeatures();
  484. let arr = []
  485. let geomWkt = []
  486. points.forEach((feature) => {
  487. let condition = []
  488. if(form.address != ''){
  489. condition.push(feature.get("address").includes(form.address))
  490. }
  491. if(form.farmName != ''){
  492. const text = feature.get("farmName")
  493. if(text!==form.farmName) return
  494. condition.push(feature.get("farmName").includes(form.farmName))
  495. }
  496. if(form.masterName != ''){
  497. const text = feature.get("masterName")
  498. if(text!==form.masterName) return
  499. condition.push(feature.get("masterName").includes(form.masterName))
  500. }
  501. if(form.masterTel != ''){
  502. const text = feature.get("masterTel")
  503. if(text!==form.masterTel) return
  504. condition.push(feature.get("masterTel").includes(form.masterTel))
  505. }
  506. if(form.speciesTypeName != ''){
  507. const text = feature.get("speciesTypeName")
  508. if(text!==form.speciesTypeName) return
  509. condition.push(feature.get("speciesTypeName").includes(form.speciesTypeName))
  510. }
  511. let b = false
  512. for(let item of condition){
  513. if(item){
  514. b = true
  515. }else{
  516. b = false
  517. break
  518. }
  519. }
  520. if(b){
  521. arr.push(feature.get("id"))
  522. geomWkt.push(new WKT().writeGeometry(feature.getGeometry()))
  523. }
  524. });
  525. this.allUnSelect()
  526. this.allSelect(arr)
  527. if(geomWkt.length>0){
  528. this.fit(geomWkt)
  529. }
  530. }
  531. }
  532. export default AuthenticMap;