OpenLayers实现台风风圈及运动轨迹

500 阅读1分钟

如图,实现一个台风的运动轨迹。

图片

思路:实现一个台风的运动轨迹,可以从两方面考虑,首先绘制台风风圈,其次让风圈运动起来。

一.绘制风圈图片 后端接口获取到的风圈数据 radius7: "200|180|180|150"。(风圈四个方向上的半径,按照顺时针方向旋转。)

风圈本质上是特殊的多边形,形状由四个方向上不同圆弧构成。所以,实现上变成了在OpenLayers中,先绘制圆弧上的点,然后由点,用polygon生成面。(polygon填充黄色+半透明,边框线是黄色。)

function generateWKT(Configs) {
  const _interval = 6;
  const radians = Math.PI / 180;
  const circleCenterX = Configs.CIRCLE_CENTER_X;
  const circleCenterY = Configs.CIRCLE_CENTER_Y;
  const circleR = Configs.CIRCLE_R;

  let wkt = "POLYGON((";
  let wkt0 = "";

  for (let i = 0; i < 360 / _interval; i++) {
    let _r = 0;
    let _ang = i * _interval;

    if (_ang > 0 && _ang <= 90) {
      _r = circleR.NE;
    } else if (_ang > 90 && _ang <= 180) {
      _r = circleR.NW;
    } else if (_ang > 180 && _ang <= 270) {
      _r = circleR.SW;
    } else {
      _r = circleR.SE;
    }

    const cosValue = Math.cos(_ang * radians);
    const sinValue = Math.sin(_ang * radians);
    const x = circleCenterX + _r * cosValue;
    const y = circleCenterY + _r * sinValue;

    wkt += `${x} ${y}, `;

    if (i === 0) {
      wkt0 = `${x} ${y}`;
    }
  }

  wkt += wkt0 + "))";

  return wkt;
}

const Configs = {
  CIRCLE_CENTER_X: 104.21390114106414,
  CIRCLE_CENTER_Y: 35.847595169932646,
  CIRCLE_R: {
    "SE": 200,
    "NE": 180,
    "NW": 180,
    "SW": 150
  }
};
const wkt = generateWKT(Configs);

二.绘制风圈运动轨迹

风圈的运动轨迹通过定时器实现。在OpenLayers中,地图每次有变更,会拿一个全新的画布或者是清空画布,然后绘制所有的图元。只需要告诉图层,你当前的状态需要画什么即可。

this.rotationHandler=setInterval(function() {
  if(self._map&&!self._map.getView().getInteracting()) {//关闭交互过程的定时渲染
      //判断台风中心是否在范围内,才触发旋转
      //typhoonLayer.data["202001"].features[typhoonLayer.data["202001"].index].point
      const extent = self.getMapExtent_();
      let needChange = false;
      for (let name in self.data) {
          const tf = self.data[name];
          if(tf&&tf.features&&tf.features[tf.index]) {
              const center = tf.features[tf.index].point.getGeometry().extent_;
              if (ol.extent.intersects(extent, center)) {
                  needChange = true;
                  break;
              }
          }
      }
      if (needChange) {//减少渲染次数
          self.rotation -= (Math.PI / 18);
          self.changed();
      }
  }
},100)