Przeglądaj źródła

fix: 地图点位功能

lxf 1 tydzień temu
rodzic
commit
d7bc82ec41

+ 1 - 0
.eslintrc.js

@@ -23,6 +23,7 @@ module.exports = {
 
     parserOptions: {
         parser: "@babel/eslint-parser",
+        requireConfigFile: false,
         ecmaVersion: 2020,
         sourceType: 'module',
     },

BIN
src/assets/images/map/point_bg.png


BIN
src/assets/images/map/type/小麦.png


BIN
src/assets/images/map/type/水稻.png


BIN
src/assets/images/map/type/荔枝.png


BIN
src/assets/images/map/type/龙眼.png


+ 59 - 16
src/views/warningHome/index.vue

@@ -1,4 +1,3 @@
--+
 <template>
     <div class="base-container no-events">
         <fnHeader showDate :autoGo="true" hideSwitch></fnHeader>
@@ -61,6 +60,7 @@
                     :default-expanded-keys="[2]"
                     :default-checked-keys="[5]"
                     :props="defaultProps"
+                    @check="getTreeChecks"
                 >
                 <template #default="{ node, data }">
                     <div class="custom-tree-node">
@@ -148,6 +148,7 @@ import { onMounted, onUnmounted, ref, reactive } from "vue";
 import fnHeader from "@/components/fnHeader.vue";
 import WarningMap from "./warningMap";
 import AlarmLayer from "./map/alarmLayer";
+import DistributionLayer from "./map/distributionLayer";
 import trackDialog from "./components/trackDialog.vue";
 import alarmList from "./components/alarmList.vue";
 import timeLine from "./components/timeLine.vue";
@@ -164,7 +165,7 @@ let warningMap = new WarningMap();
 let alarmLayer = null;
 let staticMapLayers = null;
 let staticMapPointLayers = null;
-
+let distributionLayer = null;
 const areaVal = ref(["3"]);
 const mapRef = ref(null);
 const showDetail = ref(false);
@@ -173,19 +174,36 @@ const defaultProps = {
   label: 'label',
 }
 
+import lz from "@/assets/images/map/type/荔枝.png";
+import ly from "@/assets/images/map/type/龙眼.png";
+import sd from "@/assets/images/map/type/水稻.png";
+import xm from "@/assets/images/map/type/小麦.png";
+import bc from "@/assets/images/map/type/小麦.png";
+import lb from "@/assets/images/map/type/小麦.png";
+
 const treeActionData = ref([
   {
     id: 1,
     label: '果类',
     color: '#51B2FF',
+    fillColor: 'rgba(5, 49, 84, 0.5)',
+    geom: "MULTIPOLYGON (((113.58668302396221 23.244659822289524, 113.32095411231998 23.24298858095617, 112.99338890476295 23.002328435946534, 113.13878785387456 22.604570799124076, 113.59503930394511 22.86862839611681, 113.58668302396221 23.244659822289524)))",
     children: [
       {
         id: 4,
         label: '荔枝',
+        color: "#2199F8",
+        imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E8%8D%94%E6%9E%9D.png",
+        imgName: lz,
+        wktArr: ["POINT(113.33722309500006 23.204074978290652)", "POINT(113.53593237057355 23.188789823486065)", "POINT(113.36970447853234 23.064596505297875)"],
       },
       {
         id: 55,
         label: '龙眼',
+        color: "#2199F8",
+        imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E7%99%BD%E7%B3%96.png",
+        imgName: ly,
+        wktArr: ["POINT(113.29900983080294 22.949956545068478)", "POINT(113.10412186488536 22.800924630297875)", "POINT(113.32384842738536 22.776086033715462)", "POINT(113.22640444442656 22.90983245840535)"],
       },
     ],
   },
@@ -193,28 +211,38 @@ const treeActionData = ref([
     id: 2,
     label: '粮食',
     color: '#FF8E1C',
+    fillColor: 'rgba(83, 46, 8, 0.5)',
+    geom: "MULTIPOLYGON (((112.42256410334443 23.14863707066071, 112.09584019992684 22.842930537988664, 112.25060416300033 22.62511471413565, 112.80278650958275 22.749307864685775, 112.75119857777094 23.13144100957107, 112.42256410334443 23.14863707066071)))",
     children: [
       {
         id: 5,
         label: '水稻',
-        children: [
-          {
-            id: 10,
-            label: '拔节期',
-          },
-          {
-            id: 11,
-            label: '孕穗期',
-          },
-          {
-            id: 12,
-            label: '抽穗期',
-          },
-        ],
+        color: "#FAA53D",
+        imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E6%8C%82%E7%BB%BF.png",
+        imgName: sd,
+        wktArr: ["POINT(112.70843577567298 22.969169477864167)", "POINT(112.23636397199755 22.85839626464389)", "POINT(112.35889247053002 23.008153324438585)", "POINT(112.47894566011911 22.9017143340381)"],
+        // children: [
+        //   {
+        //     id: 10,
+        //     label: '拔节期',
+        //   },
+        //   {
+        //     id: 11,
+        //     label: '孕穗期',
+        //   },
+        //   {
+        //     id: 12,
+        //     label: '抽穗期',
+        //   },
+        // ],
       },
       {
         id: 6,
         label: '小麦',
+        color: "#FAA53D",
+        imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E6%97%A0%E6%A0%B8.png",
+        imgName: xm,
+        wktArr: ["POINT(112.36777193304151 22.73892833157863)", "POINT(112.26684873669083 22.71150357559281)", "POINT(112.65408646638161 22.84862740364581)"],
       },
     ],
   },
@@ -222,14 +250,23 @@ const treeActionData = ref([
     id: 3,
     label: '蔬菜',
     color: '#25BC07',
+    fillColor: 'rgba(0, 69, 4, 0.5)',
     children: [
       {
         id: 7,
         label: '白菜',
+        color: "#7ABB00",
+        imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E7%99%BD%E8%8F%9C.png",
+        imgName: bc,
+        wktArr: ["POINT(110.34100329503417 21.516399336978793)", "POINT(113.89499662443995 22.653799122199416)", "POINT(113.9329988323152 22.653600638732314)", "POINT(113.94400024786592 22.614900553599)"],
       },
       {
         id: 8,
         label: '萝卜',
+        color: "#7ABB00",
+        imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E8%90%9D%E8%8F%9C.png",
+        imgName: lb,
+        wktArr: ["POINT(110.34100329503417 21.516399336978793)", "POINT(113.89499662443995 22.653799122199416)", "POINT(113.9329988323152 22.653600638732314)", "POINT(113.94400024786592 22.614900553599)"],
       },
     ],
   },
@@ -247,6 +284,7 @@ onMounted(() => {
     alarmLayer = new AlarmLayer(warningMap.kmap);
     staticMapLayers = new StaticMapLayers(warningMap.kmap);
     staticMapPointLayers = new StaticMapPointLayers(warningMap.kmap);
+    distributionLayer = new DistributionLayer(warningMap.kmap);
     // 添加 10 个测试点位(从 warningMap 中调用)
     warningMap.addTestPointsAroundCenter();
     // setTimeout(() => {
@@ -386,6 +424,11 @@ const remoteMethod = async (keyword) => {
         locationOptions.list = [];
     }
 };
+
+const getTreeChecks = (node, data) => {
+    console.log('getCheckedNodes', data.checkedNodes);
+    distributionLayer.initData(data.checkedNodes);
+}
 </script>
 
 <style lang="scss" scoped>

+ 135 - 0
src/views/warningHome/map/distributionLayer.js

@@ -0,0 +1,135 @@
+import * as KMap from "@/utils/ol-map/KMap";
+import { Vector as VectorSource } from "ol/source.js";
+import { Feature } from "ol";
+import { WKT } from "ol/format";
+import { Circle, Fill, Stroke, Style, Text, Icon, RegularShape } from "ol/style.js";
+import Photo from "ol-ext/style/Photo";
+
+import pointBgImg from "@/assets/images/map/point_bg.png";
+
+class DistributionLayer {
+    constructor(kmap) {
+        let that = this;
+        this.kmap = kmap
+        let vectorStyle = new KMap.VectorStyle()
+        this.distributionLayer = new KMap.VectorLayer("distributionLayer", 99, {
+            source: new VectorSource({}),
+            style: function (f) {
+                let style2 = vectorStyle.getPolygonStyle(f.get("color") + "30", f.get("fillColor"), 2)
+                return [style2]
+            }
+        });
+        this.kmap.addLayer(this.distributionLayer.layer)
+
+        this.distributionPointLayer = new KMap.VectorLayer("distributionPointLayer", 99, {
+            source: new VectorSource({}),
+            style: function (f) {
+                const label = f.get("label") || "";
+                const baseColor = f.get("color") || "#2199F8";
+                const imgUrl = f.get("imgUrl") || "";
+                const imgName = f.get("imgName") || "";
+
+                // 方块填充色背景(在白色描边 PNG 底图下方,参考 UI)
+                const squareBgStyle = new Style({
+                    image: new RegularShape({
+                        points: 4,
+                        radius: 34, // 控制方块大小
+                        angle: Math.PI / 4, // 旋转 45°,让正方形对齐
+                        fill: new Fill({
+                            color: baseColor,
+                        }),
+                        // 向上平移一点,让方块主要位于指针上方
+                        displacement: [0, 4],
+                    }),
+                });
+
+                const iconAndTextStyle = new Style({
+                    image: new Icon({
+                        src: pointBgImg,
+                        scale: 0.45,
+                    }),
+                    // 文字 + 背景(参考 UI:白色圆角矩形 + 彩色文字)
+                    text: new Text({
+                        text: label,
+                        font: "normal 14px sans-serif",
+                        offsetY: -46, // 文字整体上移,避免和图片重叠
+                        textAlign: "center",
+                        fill: new Fill({
+                            color: baseColor,
+                        }),
+                        backgroundFill: new Fill({
+                            color: "rgba(255,255,255,1)",
+                        }),
+                        backgroundStroke: new Stroke({
+                            color: baseColor,
+                            width: 1,
+                        }),
+                        padding: [2, 14, 2, 14],
+                    }),
+                });
+                const typeImgStyle = new Style({
+                    // image: new Photo({
+                    //     // src: imgUrl,
+                    //     src: imgName,
+                    //     radius: 23,
+                    //     shadow: 0,
+                    //     crop: false,
+                    //     displacement: [0, 4],
+                    // }),
+                    image: new Icon({
+                        // src: imgUrl,
+                        src: imgName,
+                        scale: 0.8,
+                        displacement: [0, 4],
+                    }),
+                });
+
+                // 先画纯色方块,再画白色描边 PNG 和文字
+                return [squareBgStyle, iconAndTextStyle, typeImgStyle];
+            },
+        });
+        this.kmap.addLayer(this.distributionPointLayer.layer)
+    }
+
+    initData(data) {
+        let that = this;
+        that.distributionLayer.source.clear();
+        that.distributionPointLayer.source.clear();
+        for (let item of data) {
+            if (item.geom) {
+                const f = new Feature({
+                    geometry: new WKT().readGeometry(item.geom),
+                });
+                f.set("color", item.color);
+                f.set("fillColor", item.fillColor);
+                this.distributionLayer.source.addFeature(f);
+            }
+
+            if (item.wktArr) {
+                for (let wkt of item.wktArr) {
+                    const f = new Feature({
+                        geometry: new WKT().readGeometry(wkt),
+                    });
+                    f.set("imgUrl", item.imgUrl);
+                    f.set("imgName", item.imgName);
+                    f.set("label", item.label);
+                    f.set("color", item.color);
+                    this.distributionPointLayer.source.addFeature(f);
+                }
+            }
+        }
+
+        // 所有点位添加完成后,地图范围自适应到包含 distributionPointLayer 的所有点
+        const pointExtent = this.distributionPointLayer.source.getExtent();
+        if (pointExtent && !isNaN(pointExtent[0])) {
+            this.kmap.map.getView().fit(pointExtent, {
+                padding: [280, 400, 200, 150],
+                duration: 500,
+            });
+        }
+    }
+}
+
+
+
+export default DistributionLayer;

+ 1 - 1
src/views/warningHome/warningMap.js

@@ -28,7 +28,7 @@ class HomeMap {
     let level = 9;
     let coordinate = util.wktCastGeom(location).getFirstCoordinate();
     this.kmap = new KMap.Map(target, level, coordinate[0], coordinate[1], null, 9, 22);
-    // this.addMapListen()
+    this.addMapListen()
     // 添加比例尺控件
     const scaleLine = new ScaleLine({
       units: 'metric' // 可以选择 'imperial' 或 'metric'