Riku
2025-03-20 7d02024c5351e620dcc2d49f36331e4a37228ea4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
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 = new Map(),
  // 动画轨迹
  _sectorViewsAna = 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 };
}
 
/**
 * 可缩放的标记
 * 无法修改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
  });
}
 
/**
 * 文本标记
 * 可修改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'
    }
  });
}
 
function drawSectorMesh(sDeg, eDeg, lnglat, distance, distance2) {
  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);
    // 外侧扇形
    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);
 
    var 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);
  }
  object3Dlayer.add(sector);
  _sector = sector;
  return true;
}
 
function drawTextMaker(list, list2, distance, distance2) {
  //10分钟扇形
  const a = _sectorViews.get('text10-t');
  if (a == undefined) {
    const text10t = textMaker(list[2], '10分钟');
    _sectorViews.set('text10-t', text10t);
    const textM10t = textMaker(list[1], distance + 'm');
    _sectorViews.set('textM10-t', textM10t);
    map.add([text10t, textM10t]);
  } else {
    _sectorViews.get('text10-t').setPosition(list[2]);
    _sectorViews.get('textM10-t').setPosition(list[1]);
    _sectorViews.get('textM10-t').setText(distance + 'm');
  }
  //5分钟扇形
  const b = _sectorViews.get('text5-t');
  if (b == undefined) {
    const text5t = textMaker(list2[1], '5分钟');
    _sectorViews.set('text5-t', text5t);
    const textM5t = textMaker(list2[0], distance2 + 'm');
    _sectorViews.set('textM5-t', textM5t);
    map.add([text5t, textM5t]);
  } else {
    _sectorViews.get('text5-t').setPosition(list2[1]);
    _sectorViews.get('textM5-t').setPosition(list2[0]);
    _sectorViews.get('textM5-t').setText(distance2 + 'm');
  }
}
 
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();
  },
  /**
   * 只清空扇形
   */
  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);
    }
  }
};