riku
2025-09-03 b2392458ebf42594b9fc5390fda40d7a0a12f923
src/utils/map/sector.js
@@ -1,232 +1,329 @@
import { map, object3Dlayer } from './index_old';
import calculate from './calculate';
import imgLocation from '@/assets/mipmap/location.png';
import { FactorDatas } from '@/model/FactorDatas';
var _defaultDeg = 30,
  _sector = undefined,
  _sectorViews = {};
  _sectorViews = new Map(),
  // 动画轨迹
  _sectorViewsAna = new Map();
function clearSector() {
  var list = [];
  for (const key in _sectorViews) {
    list.push(_sectorViews[key]);
  }
  if (list.length > 0) {
    map.remove(list);
    _sectorViews = {};
  }
  if (_sector) {
    object3Dlayer.remove(_sector);
  }
var _ptSector = undefined,
  _ptSectorViews = new Map();
const zoomStyleMapping = {
  14: 0,
  15: 0,
  16: 0,
  17: 0,
  18: 0,
  19: 0,
  20: 0
};
function sectorParams(fDatas, i) {
  const lnglat = fDatas.lnglats_GD[i];
  let windDir = fDatas.factor[17].datas[i].factorData;
  let windSpeed = fDatas.factor[16].datas[i].factorData;
  if (!windDir) windDir = 0;
  if (!windSpeed) windSpeed = 0;
  // if (windSpeed > 10) {
  //   return;
  // }
  var sDeg = windDir - _defaultDeg; //扇形起始角度(以上方作为0度)
  // sDeg = sDeg < 0 ? sDeg + 360 : sDeg
  var eDeg = windDir + _defaultDeg; //扇形结束角度
  // eDeg = eDeg < 0 ? eDeg + 360 : eDeg
  var distance = windSpeed * 10 * 60; //半径(风速*时间)
  var lnglat2 = calculate.getLatLon(lnglat, distance, sDeg);
  var lnglat3 = calculate.getLatLon(lnglat, distance, windDir);
  var lnglat4 = calculate.getLatLon(lnglat, distance, eDeg);
  var list = calculate.parse2LngLat([lnglat, lnglat2, lnglat3, lnglat4]);
  var distance2 = windSpeed * 5 * 60; //半径(风速*时间)
  var lnglat2_2 = calculate.getLatLon(lnglat, distance2, sDeg);
  var lnglat2_3 = calculate.getLatLon(lnglat, distance2, windDir);
  var lnglat2_4 = calculate.getLatLon(lnglat, distance2, eDeg);
  var list2 = calculate.parse2LngLat([lnglat2_2, lnglat2_3, lnglat2_4]);
  distance = distance.toFixed(0);
  distance2 = distance2.toFixed(0);
  return { sDeg, eDeg, lnglat, distance, distance2, list, list2 };
}
export default {
  drawSector(fDatas, i) {
    const lnglat = fDatas.lnglats_GD[i];
    let windDir = fDatas.factor[17].datas[i].factorData;
    let windSpeed = fDatas.factor[16].datas[i].factorData;
    if (!windDir) windDir = 0;
    if (!windSpeed) windSpeed = 0;
/**
 * 可缩放的标记
 * 无法修改position(官网未找到相关api)
 */
function elasticMarker(position, content) {
  // eslint-disable-next-line no-undef
  return new AMap.ElasticMarker({
    zoom: [14, 20],
    position: position,
    styles: [
      {
        icon: {
          img: imgLocation,
          size: [16, 16], //可见区域的大小
          ancher: [8, 16], //锚点
          fitZoom: 18, //最合适的级别
          scaleFactor: 1, //地图放大一级的缩放比例系数
          maxScale: 2, //最大放大比例
          minScale: 1 //最小放大比例
        },
        label: {
          content: content,
          offset: [-35, 0],
          position: 'BM',
          minZoom: 10
        }
      }
    ],
    zoomStyleMapping: zoomStyleMapping
  });
}
    if (windSpeed > 10) {
      return;
/**
 * 文本标记
 * 可修改position
 */
function textMaker(position, text) {
  // eslint-disable-next-line no-undef
  return new AMap.Text({
    text: text,
    position: position,
    style: {
      'font-size': '13px',
      'text-align': 'center',
      color: 'white',
      'background-color': 'transparent',
      'text-shadow': 'black 2px 2px 2px',
      'border-radius': '2px',
      border: '0px',
      padding: '4px'
    }
    if (_sector != undefined) {
      clearSector();
  });
}
function drawSectorMesh(
  sDeg,
  eDeg,
  lnglat,
  distance,
  distance2,
  isPollutinTrace
) {
  if (distance == 0 || distance2 == 0) {
    return false;
  }
  // eslint-disable-next-line no-undef
  var sector = new AMap.Object3D.Mesh();
  sector.transparent = true;
  sector.backOrFront = 'both';
  var unit = 5;
  var p0 = calculate.lngLatToGeodeticCoord([lnglat])[0];
  var geometry = sector.geometry;
  var count = distance / unit;
  var unitDeg = (eDeg - sDeg) / count;
  for (let i = 0; i < count; i++) {
    var angle1 = sDeg + unitDeg * i;
    var angle2 = sDeg + unitDeg * (i + 1);
    var p1 = calculate.getLatLon(lnglat, distance, angle1);
    var p2 = calculate.getLatLon(lnglat, distance, angle2);
    var p3 = calculate.getLatLon(lnglat, distance2, angle1);
    var p4 = calculate.getLatLon(lnglat, distance2, angle2);
    var coors = calculate.lngLatToGeodeticCoord([p1, p2, p3, p4]);
    const l1 = coors[0];
    const l2 = coors[1];
    const l3 = coors[2];
    const l4 = coors[3];
    // 内测扇形
    geometry.vertices.push(p0.x, p0.y, 0);
    geometry.vertices.push(l3.x, l3.y, 0);
    geometry.vertices.push(l4.x, l4.y, 0);
    if (!isPollutinTrace) {
      // 内测扇形颜色
      geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
      geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
      geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
    } else {
      geometry.vertexColors.push(0.25, 0.11, 1, 0.6);
      geometry.vertexColors.push(0.25, 0.11, 1, 0.6);
      geometry.vertexColors.push(0.25, 0.11, 1, 0.6);
    }
    // eslint-disable-next-line no-undef
    var sector = new AMap.Object3D.Mesh();
    sector.transparent = true;
    sector.backOrFront = 'both';
    var unit = 5;
    var sDeg = windDir - _defaultDeg; //扇形起始角度(以上方作为0度)
    // sDeg = sDeg < 0 ? sDeg + 360 : sDeg
    var eDeg = windDir + _defaultDeg; //扇形结束角度
    // eDeg = eDeg < 0 ? eDeg + 360 : eDeg
    var distance = windSpeed * 10 * 60; //半径(风速*时间)
    var lnglat2 = calculate.getLatLon(lnglat, distance, sDeg);
    var lnglat3 = calculate.getLatLon(lnglat, distance, windDir);
    var lnglat4 = calculate.getLatLon(lnglat, distance, eDeg);
    var list = calculate.parse2LngLat([lnglat, lnglat2, lnglat3, lnglat4]);
    var distance2 = windSpeed * 5 * 60; //半径(风速*时间)
    var lnglat2_2 = calculate.getLatLon(lnglat, distance2, sDeg);
    var lnglat2_3 = calculate.getLatLon(lnglat, distance2, windDir);
    var lnglat2_4 = calculate.getLatLon(lnglat, distance2, eDeg);
    var list2 = calculate.parse2LngLat([lnglat2_2, lnglat2_3, lnglat2_4]);
    var p0 = calculate.lngLatToGeodeticCoord([lnglat])[0];
    var geometry = sector.geometry;
    var count = distance / unit;
    var unitDeg = (eDeg - sDeg) / count;
    for (let i = 0; i < count; i++) {
      var angle1 = sDeg + unitDeg * i;
      var angle2 = sDeg + unitDeg * (i + 1);
      var l1 = calculate.getLatLon(lnglat, distance, angle1);
      var l2 = calculate.getLatLon(lnglat, distance, angle2);
      var l3 = calculate.getLatLon(lnglat, distance2, angle1);
      var l4 = calculate.getLatLon(lnglat, distance2, angle2);
      var coors = calculate.lngLatToGeodeticCoord([l1, l2, l3, l4]);
      l1 = coors[0];
      l2 = coors[1];
      l3 = coors[2];
      l4 = coors[3];
      // 内测扇形
      geometry.vertices.push(p0.x, p0.y, 0);
      geometry.vertices.push(l3.x, l3.y, 0);
      geometry.vertices.push(l4.x, l4.y, 0);
    if (!isPollutinTrace) {
      // 外侧扇形
      geometry.vertices.push(l3.x, l3.y, 0);
      geometry.vertices.push(l4.x, l4.y, 0);
      geometry.vertices.push(l1.x, l1.y, 0);
      geometry.vertices.push(l2.x, l2.y, 0);
      // console.log(l3.x + ',' + l3.y + ' | ' + l1.x + ',' + l1.y);
      // 内测扇形颜色
      geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
      geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
      geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
      //外侧扇形颜色
      geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
      geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
      geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
      geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
    }
    // console.log(l3.x + ',' + l3.y + ' | ' + l1.x + ',' + l1.y);
      var index = i * 7;
    if (!isPollutinTrace) {
      const index = i * 7;
      geometry.faces.push(index, index + 1, index + 2);
      geometry.faces.push(index + 3, index + 4, index + 5);
      geometry.faces.push(index + 4, index + 5, index + 6);
    } else {
      const index = i * 3;
      geometry.faces.push(index, index + 1, index + 2);
      // geometry.faces.push(index + 3, index + 4, index + 5);
      // geometry.faces.push(index + 4, index + 5, index + 6);
    }
    object3Dlayer.add(sector);
    _sector = sector;
  }
  object3Dlayer.add(sector);
  isPollutinTrace ? (_ptSector = sector) : (_sector = sector);
  return true;
}
    distance = distance.toFixed(0);
    distance2 = distance2.toFixed(0);
    const zoomStyleMapping = {
      14: 0,
      15: 0,
      16: 0,
      17: 0,
      18: 0,
      19: 0,
      20: 0
    };
    //10分钟扇形
    // eslint-disable-next-line no-undef
    var text15 = new AMap.ElasticMarker({
      zoom: [14, 20],
      position: list[2],
      styles: [
        {
          icon: {
            img: './asset/mipmap/location.png',
            size: [16, 16], //可见区域的大小
            ancher: [8, 16], //锚点
            fitZoom: 18, //最合适的级别
            scaleFactor: 1, //地图放大一级的缩放比例系数
            maxScale: 2, //最大放大比例
            minScale: 1 //最小放大比例
          },
          label: {
            content: '<div>10分钟</div>',
            offset: [-35, 0],
            position: 'BM',
            minZoom: 15
          }
        }
      ],
      zoomStyleMapping: zoomStyleMapping
    });
    _sectorViews['text10'] = text15;
    // eslint-disable-next-line no-undef
    var textM = new AMap.ElasticMarker({
      zoom: [14, 20],
      position: list[1],
      styles: [
        {
          icon: {
            img: './asset/mipmap/location.png',
            size: [16, 16], //可见区域的大小
            ancher: [8, 16], //锚点
            fitZoom: 18, //最合适的级别
            scaleFactor: 1, //地图放大一级的缩放比例系数
            maxScale: 2, //最大放大比例
            minScale: 1 //最小放大比例
          },
          label: {
            content: `<div>${distance}m</div>`,
            offset: [-35, 0],
            position: 'BM',
            minZoom: 15
          }
        }
      ],
      zoomStyleMapping: zoomStyleMapping
    });
    _sectorViews['textM'] = textM;
    map.add(_sectorViews['text10']);
    map.add(_sectorViews['textM']);
function drawTextMaker(list, list2, distance, distance2, isPollutinTrace) {
  const _sectorViewsTmp = isPollutinTrace ? _ptSectorViews : _sectorViews;
  //10分钟扇形
  if (!isPollutinTrace) {
    const a = _sectorViewsTmp.get('text10-t');
    if (a == undefined) {
      const text10t = textMaker(list[2], '10分钟');
      _sectorViewsTmp.set('text10-t', text10t);
      const textM10t = textMaker(list[1], distance + 'm');
      _sectorViewsTmp.set('textM10-t', textM10t);
      map.add([text10t, textM10t]);
    } else {
      _sectorViewsTmp.get('text10-t').setPosition(list[2]);
      _sectorViewsTmp.get('textM10-t').setPosition(list[1]);
      _sectorViewsTmp.get('textM10-t').setText(distance + 'm');
    }
  }
  //5分钟扇形
  const b = _sectorViewsTmp.get('text5-t');
  if (b == undefined) {
    const text5t = textMaker(list2[1], '5分钟');
    _sectorViewsTmp.set('text5-t', text5t);
    const textM5t = textMaker(list2[0], distance2 + 'm');
    _sectorViewsTmp.set('textM5-t', textM5t);
    map.add([text5t, textM5t]);
  } else {
    _sectorViewsTmp.get('text5-t').setPosition(list2[1]);
    _sectorViewsTmp.get('textM5-t').setPosition(list2[0]);
    _sectorViewsTmp.get('textM5-t').setText(distance2 + 'm');
  }
}
    //5分钟扇形
    let pList = list2;
    // eslint-disable-next-line no-undef
    var text5 = new AMap.ElasticMarker({
      position: pList[1],
      styles: [
        {
          icon: {
            img: './asset/mipmap/location.png',
            size: [16, 16], //可见区域的大小
            ancher: [8, 16], //锚点
            fitZoom: 18, //最合适的级别
            scaleFactor: 1, //地图放大一级的缩放比例系数
            maxScale: 2, //最大放大比例
            minScale: 1 //最小放大比例
          },
          label: {
            content: `<div>5分钟</div>`,
            offset: [-35, 0],
            position: 'BM',
            minZoom: 15
          }
        }
      ],
      zoomStyleMapping: zoomStyleMapping
    });
    _sectorViews['text5'] = text5;
    // eslint-disable-next-line no-undef
    var textM5 = new AMap.ElasticMarker({
      position: pList[0],
      styles: [
        {
          icon: {
            img: './asset/mipmap/location.png',
            size: [16, 16], //可见区域的大小
            ancher: [8, 16], //锚点
            fitZoom: 18, //最合适的级别
            scaleFactor: 1, //地图放大一级的缩放比例系数
            maxScale: 2, //最大放大比例
            minScale: 1 //最小放大比例
          },
          label: {
            content: `<div>${distance2}m</div>`,
            offset: [-35, 0],
            position: 'BM',
            minZoom: 15
          }
        }
      ],
      zoomStyleMapping: zoomStyleMapping
    });
    _sectorViews['textM5'] = textM5;
    map.add(_sectorViews['textM5']);
    map.add(_sectorViews['text5']);
function drawElasticMarker(list, list2, distance, distance2) {
  //10分钟扇形
  const text10 = elasticMarker(list[2], '<div>10分钟</div>');
  _sectorViews.set('text10', text10);
  const textM = elasticMarker(list[1], `<div>${distance}m</div>`);
  _sectorViews.set('textM10', textM);
  map.add([text10, textM]);
  //5分钟扇形
  const text5 = elasticMarker(list2[1], '<div>5分钟</div>');
  _sectorViews.set('text5', text5);
  const textM5 = elasticMarker(list2[0], `<div>${distance2}m</div>`);
  _sectorViews.set('textM5', textM5);
  map.add([text5, textM5]);
}
export default {
  /**
   * 清空扇形和文本标记
   */
  clearSector() {
    var list = [];
    for (const iterator of _sectorViews) {
      list.push(iterator[1]);
    }
    for (const iterator of _sectorViewsAna) {
      list.push(iterator[1]);
    }
    if (list.length > 0) {
      map.remove(list);
      _sectorViews.clear();
    }
    this.clearSectorMesh();
  },
  clearSectorPt() {
    var list = [];
    for (const iterator of _ptSectorViews) {
      list.push(iterator[1]);
    }
    if (list.length > 0) {
      map.remove(list);
      _ptSectorViews.clear();
    }
    if (_ptSector) {
      object3Dlayer.remove(_ptSector);
    }
  },
  /**
   * 只清空扇形
   */
  clearSectorMesh() {
    if (_sector) {
      object3Dlayer.remove(_sector);
    }
  },
  sectorParams: sectorParams,
  /**
   * 绘制扇形
   * @param {FactorDatas} fDatas
   * @param {number} i
   * @returns 数据坐标点和扇形最大半径
   */
  drawSector(fDatas, i) {
    this.clearSector();
    const { sDeg, eDeg, lnglat, distance, distance2, list, list2 } =
      sectorParams(fDatas, i);
    if (drawSectorMesh(sDeg, eDeg, lnglat, distance, distance2)) {
      // 当风速大于0绘制了扇形时,才绘制对应的距离等文本标记
      // drawElasticMarker(list, list2, distance, distance2);
      drawTextMaker(list, list2, distance, distance2);
    }
    return { p: lnglat, r: distance };
  },
  /**
   * 绘制轨迹动画中的扇形
   * @param {FactorDatas} fDatas
   * @param {number} i
   */
  drawSectorAna(fDatas, i) {
    this.clearSectorMesh();
    const { sDeg, eDeg, lnglat, distance, distance2, list, list2 } =
      sectorParams(fDatas, i);
    if (drawSectorMesh(sDeg, eDeg, lnglat, distance, distance2)) {
      drawTextMaker(list, list2, distance, distance2);
    }
  },
  drawSectorPt(fDatas, i) {
    if (_ptSector) {
      object3Dlayer.remove(_ptSector);
    }
    const { sDeg, eDeg, lnglat, distance, distance2, list, list2 } =
      sectorParams(fDatas, i);
    if (drawSectorMesh(sDeg, eDeg, lnglat, distance, distance2, true)) {
      drawTextMaker(list, list2, distance, distance2, true);
    }
    return { p: lnglat, r: distance };
  }
};