From adc9abd145c24f2d3e7033bb738e1e8641eaf4cf Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期二, 02 九月 2025 17:30:43 +0800
Subject: [PATCH] 2025.9.2

---
 src/utils/map/grid.js |  477 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 455 insertions(+), 22 deletions(-)

diff --git a/src/utils/map/grid.js b/src/utils/map/grid.js
index 351bd2c..dba3ced 100644
--- a/src/utils/map/grid.js
+++ b/src/utils/map/grid.js
@@ -2,51 +2,484 @@
  * 缃戞牸缁樺埗
  */
 import { map } from './index_old';
+import calculate from './calculate';
+import { Legend } from '@/model/Legend';
+import { getGridDataDetailFactorValue } from '@/model/GridDataDetail';
+import { getHexColor, getColorBetweenTwoColors } from '../color';
+
+/**
+ * 瑙掑害澧炲噺锛岀‘淇濊搴﹀浜�0 - 360搴︿箣闂�
+ * @param {number} angle 鍘熻搴�
+ * @param {number} offset 鍋忕Щ閲�
+ */
+function plusAngle(angle, offset) {
+  const result = angle + offset;
+  if (result > 360) {
+    return result - 360;
+  } else if (result < 0) {
+    return result + 360;
+  } else {
+    return result;
+  }
+}
+
+/**
+ * 鏍规嵁缃戞牸涓績鐐癸紝鐢熸垚姝f柟褰㈢綉鏍�4涓《鐐圭殑鍧愭爣
+ * @param {Array} points 缃戞牸涓績鐐圭粡绾害鏁扮粍
+ */
+function parseGridPoint(points) {
+  if (points.length < 2) throw new Error('鍧愭爣鐐规暟閲忓皬浜�2');
+  const p1 = points[0];
+  const p2 = points[1];
+  // 涓や腑蹇冪偣闂寸殑瑙掑害
+  const angle = calculate.getAngle(p1[0], p1[1], p2[0], p2[1]);
+  // const angle = calculate.bearing(
+  //   { latitude: p1[0], longitude: p1[1] },
+  //   { latitude: p2[0], longitude: p2[1] }
+  // );
+  // 涓や腑蹇冪偣闂寸殑璺濈
+  const dis = calculate.getDistance(p1[0], p1[1], p2[0], p2[1]);
+  // 缃戞牸姝f柟褰㈠瑙掔嚎鐨勪竴鍗婇暱搴�
+  const halfDiagonal = Math.sqrt((dis / 2) * (dis / 2) * 2);
+  // 璁$畻棣栦釜姝f柟褰㈠悇椤剁偣鐩稿浜庝腑蹇冪偣鐨勮搴︼紝寰楀埌姝f柟褰㈠悇椤剁偣鐨勫潗鏍�
+  const angle1 = plusAngle(angle, 45);
+  const gp1 = calculate.getLatLon(p1, halfDiagonal, angle1);
+  const angle2 = plusAngle(angle1, 90);
+  const gp2 = calculate.getLatLon(p1, halfDiagonal, angle2);
+  const angle3 = plusAngle(angle2, 90);
+  const gp3 = calculate.getLatLon(p1, halfDiagonal, angle3);
+  const angle4 = plusAngle(angle3, 90);
+  const gp4 = calculate.getLatLon(p1, halfDiagonal, angle4);
+  // 璁$畻4涓《鐐瑰垎鍒笌涓績鐐圭殑缁忕含搴﹀樊鍊�
+  const diff = {
+    diff1: {
+      dx: gp1[0] - p1[0],
+      dy: gp1[1] - p1[1]
+    },
+    diff2: {
+      dx: gp2[0] - p1[0],
+      dy: gp2[1] - p1[1]
+    },
+    diff3: {
+      dx: gp3[0] - p1[0],
+      dy: gp3[1] - p1[1]
+    },
+    diff4: {
+      dx: gp4[0] - p1[0],
+      dy: gp4[1] - p1[1]
+    }
+  };
+
+  // 寰楀埌鎵�鏈夋鏂瑰舰缃戞牸鐨�4涓《鐐逛俊鎭�
+  return points.map((p) => {
+    return [
+      [p[0] + diff.diff1.dx, p[1] + diff.diff1.dy],
+      [p[0] + diff.diff2.dx, p[1] + diff.diff2.dy],
+      [p[0] + diff.diff3.dx, p[1] + diff.diff3.dy],
+      [p[0] + diff.diff4.dx, p[1] + diff.diff4.dy]
+    ];
+  });
+}
+
+function textMakerStyle({ type, color }) {
+  let style = {};
+  if (type == 'data') {
+    style = {
+      'font-size': '12px',
+      'text-align': 'center',
+      'font-weight': 600,
+      color: color ? color : 'white',
+      background: '#122b54a9',
+      // background: 'white',
+      'text-shadow': 'black 1px 1px 1px',
+      border: '0px',
+      'margin-top': '4px'
+    };
+  } else if (type == 'rank') {
+    style = {
+      'font-size': '14px',
+      'text-align': 'center',
+      color: color ? color : 'white',
+      background: 'transparent',
+      'text-shadow': 'black 2px 2px 2px',
+      'border-radius': '2px',
+      border: '1px solid #122b54a9',
+      // border: '1px solid rgba(255, 255, 255, 0.62)',
+      'margin-bottom': '4px'
+    };
+  }
+  return style;
+}
+
+/**
+ * 鏂囨湰鏍囪
+ * 鍙慨鏀筽osition
+ */
+function textMaker({ position, text, anchor, type, color }) {
+  let style = textMakerStyle({ type, color });
+  // eslint-disable-next-line no-undef
+  return new AMap.Text({
+    text: text,
+    anchor,
+    position: position,
+    style: style
+  });
+}
+
+/**
+ * 娴烽噺鏂囨湰鏍囨敞
+ */
+function textLabelMarker(position, text, direction, style) {
+  // eslint-disable-next-line no-undef
+  return new AMap.LabelMarker({
+    position: position,
+    zooms: [10, 20],
+    opacity: 1,
+    zIndex: 2,
+    // icon: {
+    //   image: 'https://a.amap.com/jsapi_demos/static/images/poi-marker.png',
+    //   anchor: 'bottom-center',
+    //   size: [25, 34],
+    //   clipOrigin: [459, 92],
+    //   clipSize: [50, 68]
+    // },
+    text: {
+      // 娉ㄦ剰鍐呭鏍煎紡蹇呴』鏄痵tring
+      content: text ? text + '' : '',
+      direction: direction ? direction : 'center',
+      style: {
+        'border-radius': '.25rem',
+        fontSize: 12,
+        fillColor: '#fff',
+        strokeColor: 'rgba(0, 0, 0, 1)',
+        strokeWidth: 4,
+        // backgroundColor: '#122b54a9',
+        padding: [3, 10],
+        // backgroundColor: 'yellow',
+        borderColor: '#ccc',
+        borderWidth: 30
+      }
+    }
+  });
+}
+
+/**
+ * 璁$畻姣忎釜缃戞牸棰滆壊
+ */
+function calGridColor({ factorName, data, isCustomColor }) {
+  let _colorList = [];
+  if (isCustomColor) {
+    var max, min;
+    data.forEach((t) => {
+      if (!t) return;
+      if (!max || t > max) {
+        max = t;
+      }
+      if (!min || t < min) {
+        min = t;
+      }
+    });
+    data.forEach((d) => {
+      if (d) {
+        // 鏍规嵁閬ユ祴鏁版嵁璁$畻缃戞牸棰滆壊
+        const { color, nextColor, range, nextRange } =
+          Legend.getCustomColorAndNext(d, min, max);
+        const ratio = (d - range) / (nextRange - range);
+
+        const _color = getColorBetweenTwoColors(
+          color.map((v) => v * 255),
+          nextColor.map((v) => v * 255),
+          ratio
+        );
+        _colorList.push(_color);
+      } else {
+        _colorList.push(undefined);
+      }
+    });
+  } else {
+    data.forEach((d) => {
+      if (d) {
+        // 鏍规嵁閬ユ祴鏁版嵁璁$畻缃戞牸棰滆壊
+        const { color, nextColor, range, nextRange } =
+          Legend.getStandardColorAndNext(factorName, d);
+        const ratio = (d - range) / (nextRange - range);
+        const _color = getColorBetweenTwoColors(
+          color.map((v) => v * 255),
+          nextColor.map((v) => v * 255),
+          ratio
+        );
+        _colorList.push(_color);
+      } else {
+        _colorList.push(undefined);
+      }
+    });
+  }
+  return _colorList;
+}
 
 export default {
+  parseGridPoint,
+
   /**
    * 缁樺埗缃戞牸椋庨櫓鍥�
    * @param {*} points
    */
-  drawRectangle: function (points) {
+  drawRectangle(points) {
     const gridViews = [];
     points.forEach((p) => {
       const { lb, rt, c } = p;
 
-      // eslint-disable-next-line no-undef
-      let pList = [lb, rt].map((v) => new AMap.LngLat(v[0], v[1]));
+      let pList = [lb, rt].map((v) => {
+        // eslint-disable-next-line no-undef
+        return new AMap.LngLat(v[0], v[1]);
+      });
       // eslint-disable-next-line no-undef
       var bounds = new AMap.Bounds(...pList);
       // eslint-disable-next-line no-undef
       var rectangle = new AMap.Rectangle({
         bounds: bounds,
-        // strokeColor: '#ffffffff',
-        strokeWeight: 0,
-        strokeOpacity: 0,
+        strokeColor: '#ffffffff',
+        strokeWeight: 1,
+        strokeOpacity: 1,
         // strokeStyle杩樻敮鎸� solid
         strokeStyle: 'solid',
-        fillColor: '990D0D',
+        fillColor: '#990D0D',
         fillOpacity: 0.8,
         cursor: 'pointer',
         zIndex: 50
       });
-
-      // var text = new AMap.Text({
-      //   text: p.value,
-      //   anchor: 'center', // 璁剧疆鏂囨湰鏍囪閿氱偣
-      //   draggable: false,
-      //   style: {
-      //     'background-color': 'transparent',
-      //     'border-width': 0,
-      //     'text-align': 'center',
-      //     'font-size': '12px',
-      //     color: 'white'
-      //   },
-      //   position: c
-      // });
       gridViews.push(rectangle);
-      // that.textView.push(text);
     });
     map.add(gridViews);
+    map.setFitView(gridViews);
+  },
+
+  /**
+   * 缁樺埗涓�缁勫杈瑰舰
+   * @param {Array} points 缃戞牸鍧愭爣鐐规暟缁�
+   * @param {Boolean} draw 鏄惁鍒涘缓瀹屾垚鍚庡悓鏃剁粯鍒�
+   */
+  drawPolylines({ points, draw, event }) {
+    const gridViews = [];
+    points.forEach((p) => {
+      //鍒涘缓澶氳竟褰� Polygon 瀹炰緥
+      // eslint-disable-next-line no-undef
+      var polygon = new AMap.Polygon({
+        path: p.path, //璺緞
+        fillColor: '#fff', //澶氳竟褰㈠~鍏呴鑹�
+        strokeWeight: 1, //绾挎潯瀹藉害锛岄粯璁や负 2
+        strokeColor: 'white', //绾挎潯棰滆壊
+        fillOpacity: 0,
+        extData: p.extData,
+        zIndex: 11
+      });
+
+      if (typeof event === 'function') {
+        event(polygon);
+      }
+      gridViews.push(polygon);
+    });
+    if (draw) {
+      map.add(gridViews);
+      map.setFitView(gridViews);
+    }
+    return gridViews;
+  },
+
+  drawGridText({
+    points,
+    textViews,
+    anchor,
+    type,
+    isCustomColor,
+    useColor,
+    factorName = 'PM25'
+  }) {
+    let colorList = [];
+    if (useColor) {
+      colorList = calGridColor({
+        factorName,
+        data: points.map((p) => p.data),
+        isCustomColor: isCustomColor
+      });
+    }
+    if (textViews) {
+      map.remove(textViews);
+    }
+    const _textViews = [];
+    points.forEach((p, i) => {
+      const m = textMaker({
+        position: p.lnglat_GD,
+        text: p.data,
+        anchor,
+        type,
+        color: useColor ? colorList[i] : 'white'
+      });
+      _textViews.push(m);
+    });
+    // map.add(_textViews);
+    return { textViews: _textViews };
+  },
+
+  changeGridText({
+    points,
+    textViews,
+    type,
+    isCustomColor,
+    useColor,
+    factorName = 'PM25'
+  }) {
+    let colorList = [];
+    if (useColor) {
+      colorList = calGridColor({
+        factorName,
+        data: points.map((p) => p.data),
+        isCustomColor: isCustomColor
+      });
+    }
+    if (textViews) {
+      textViews.forEach((t, i) => {
+        t.setText(points[i].data);
+        t.setStyle(
+          textMakerStyle({ type, color: useColor ? colorList[i] : 'white' })
+        );
+      });
+    }
+    return { textViews };
+  },
+
+  drawGridTextLabel(points, textViews, labelsLayer, direction) {
+    if (textViews) {
+      points.forEach((p, i) => {
+        textViews[i].setPosition(p.lnglat_GD);
+        textViews[i].setText({
+          content: p.data ? p.data + '' : ''
+        });
+      });
+      return { textViews, labelsLayer };
+    } else {
+      // 鍒涘缓涓�涓� LabelsLayer 瀹炰緥鏉ユ壙杞� LabelMarker锛孾LabelsLayer 鏂囨。](https://lbs.amap.com/api/jsapi-v2/documentation#labelslayer)
+      // eslint-disable-next-line no-undef
+      const labelsLayer = new AMap.LabelsLayer({
+        zooms: [12, 20],
+        zIndex: 1000,
+        // 寮�鍚爣娉ㄩ伩璁╋紝榛樿涓哄紑鍚紝v1.4.15 鏂板灞炴��
+        collision: false,
+        // 寮�鍚爣娉ㄦ贰鍏ュ姩鐢伙紝榛樿涓哄紑鍚紝v1.4.15 鏂板灞炴��
+        animation: false
+      });
+      const _textViews = [];
+      points.forEach((p) => {
+        const m = textLabelMarker(p.lnglat_GD, p.data, direction);
+        _textViews.push(m);
+        // 灏� LabelMarker 瀹炰緥娣诲姞鍒� LabelsLayer 涓�
+        labelsLayer.add(m);
+      });
+      map.add(labelsLayer);
+      // map.on('zoomend', () => {
+      //   console.log(map.getZoom());
+      // });
+      return { textViews: _textViews, labelsLayer };
+    }
+  },
+
+  /**
+   * 鏍规嵁閬ユ祴鏁版嵁锛岃缃搴旂綉鏍肩殑鏍囧噯鑹诧紝杩斿洖鏈夋暟鎹殑缃戞牸
+   * @param {Array} gridViews 缃戞牸澶氳竟褰㈠璞℃暟缁�
+   * @param {Array} gridDataDetail 鍗槦閬ユ祴鏁版嵁鏁扮粍
+   * @param {string} factorName 鐩戞祴鍥犲瓙鍚嶇О
+   * @param {number} opacity 閫忔槑搴�
+   */
+  drawGridColor(gridViews, gridDataDetail, factorName, style) {
+    let {
+      strokeWeight = 1,
+      strokeColor = 'white',
+      opacity = 1,
+      zIndex = 11
+    } = style;
+    const res = [];
+    // 閬嶅巻鍗槦閬ユ祴鏁版嵁鏁扮粍
+    gridDataDetail.forEach((d, i) => {
+      const data = getGridDataDetailFactorValue(d, factorName);
+      if (data) {
+        const grid = gridViews[i];
+
+        // 鏍规嵁閬ユ祴鏁版嵁璁$畻缃戞牸棰滆壊
+        const { color, nextColor, range, nextRange } =
+          Legend.getStandardColorAndNext(factorName, data);
+        const ratio = (data - range) / (nextRange - range);
+        const _color = getColorBetweenTwoColors(
+          color.map((v) => v * 255),
+          nextColor.map((v) => v * 255),
+          ratio
+        );
+
+        const _extData = grid.getExtData();
+        grid.setOptions({
+          strokeWeight,
+          strokeColor,
+          zIndex,
+          fillColor: _color, //澶氳竟褰㈠~鍏呴鑹�
+          fillOpacity: opacity,
+          extData: {
+            ..._extData,
+            gridData: d
+          }
+        });
+        if (d.gridStyle && style.isMixGridHighlight) {
+          const _strokeWeight = d.gridStyle.strokeWeight;
+          const _strokeColor = d.gridStyle.strokeColor;
+          grid.setOptions({
+            strokeWeight: _strokeWeight, //绾挎潯瀹藉害锛岄粯璁や负 1
+            strokeColor: _strokeColor //绾挎潯棰滆壊
+          });
+        }
+
+        res.push(grid);
+      }
+    });
+
+    return res;
+  },
+
+  drawGridColorCustom(gridViews, gridDataDetail, factorName) {
+    var max, min;
+    gridDataDetail.forEach((t) => {
+      const data = getGridDataDetailFactorValue(t, factorName);
+      if (!data) return;
+      if (!max || data > max) {
+        max = data;
+      }
+      if (!min || data < min) {
+        min = data;
+      }
+    });
+    const res = [];
+    // 閬嶅巻鍗槦閬ユ祴鏁版嵁鏁扮粍
+    gridDataDetail.forEach((d, i) => {
+      const data = getGridDataDetailFactorValue(d, factorName);
+      if (data) {
+        const grid = gridViews[i];
+
+        // 鏍规嵁閬ユ祴鏁版嵁璁$畻缃戞牸棰滆壊
+        const { color, nextColor, range, nextRange } =
+          Legend.getCustomColorAndNext(data, min, max);
+        const ratio = (data - range) / (nextRange - range);
+
+        const _color = getColorBetweenTwoColors(
+          color.map((v) => v * 255),
+          nextColor.map((v) => v * 255),
+          ratio
+        );
+        grid.setOptions({
+          fillColor: _color //澶氳竟褰㈠~鍏呴鑹�
+          // fillOpacity: style.opacity ? style.opacity : color[3] == 0 ? 0 : 1
+        });
+
+        res.push(grid);
+      }
+    });
+
+    return res;
   }
 };

--
Gitblit v1.9.3