vue openlayers实现台风轨迹示例详解

目录
  • 功能描述
  • 创建一个地图容器
    • 引入地图相关对象
    • 创建地图对象
  • 开始绘制
    • 准备台风数据和图层
    • 绘制台风名称
    • 绘制台风轨迹点和轨迹线
    • 添加台风风圈动画
    • 让台风轨迹动起来
  • 结尾

功能描述

  • 台风轨迹点实时绘制,根据不同点的类型绘制不同的轨迹点颜色
  • 轨迹线绘制,涉及实时轨迹线段与预报轨迹线,根据台风类型绘制成不同颜色
  • 当前正在发生的台风还需增加当前台风所风圈位置
  • 台风轨迹点点击弹框显示轨迹点信息

openlayers(简称ol)这里不做介绍,刚开始写此类文章,直接上代码

创建一个地图容器

引入地图相关对象

import Map from 'ol/Map';
import View from 'ol/View';
import XYZ from 'ol/source/XYZ';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';

创建地图对象

都是一些基本活

const center = [-5639523.95, -3501274.52];
const map = new Map({
  target: document.getElementById('map'),
  view: new View({
    center: center,
    zoom: 10,
    minZoom: 2,
    maxZoom: 19,
  }),
  layers: [ ],
});
this.addEventMapClick()

监听地图点击事件

 addEventMapClick () {
    const nameDom = document.createElement('div')
    nameDom.setAttribute('class', 'typhoon-popup')
    const nameOverlay = new ol.Overlay({
      element: nameDom,
      position: [0, 0],
      positioning: 'right-center',
      stopEvent: false,
      insertFirst: false,
      autoPanAnimation: {
        duration: 250
      }
    })
    this.viewer.addOverlay(nameOverlay)
    this._popup = nameOverlay
    // 监听地图点击事件
    this.viewer.on('singleclick', e => {
      this._popup.getElement().parentElement.style.display = 'none'
      this.viewer.forEachFeatureAtPixel(
        e.pixel,
        (result) => {
          if (result) {
            let Properties = result.get('properties')
            let layerType = result.get('layerType')
            // 台风点点击
            // && layerType === 'typhoonpoint'
            if (layerType === 'typhoonLyer') {
              let html = `<div class="typhoonLyer"><div class="con">名称: ${Properties.CODE || ''} ${Properties.NAME_CN || ''} ${Properties.NAME_EN || ''}</div>
              <div class="con">风速: ${Properties.MOVE_SPEED || '--'} km/h</div>
              <div class="con">中心气压: ${Properties.PRESS || '--'}</div>
              <div class="con">时间: ${Properties.time || '--'}</div>
              <div class="con">中心位置: ${Properties.LON}/${Properties.LAT}</div></div>`
              this._popup.getElement().innerHTML = html
              this._popup.setPosition([Properties.LON, Properties.LAT])
              // this._popup.setOffset([25, 0])
              this._popup.getElement().parentElement.style.display = 'block'
            } else {
              this._popup.getElement().parentElement.style.display = 'none'
            }
          }
        }
      )
    })
  }

开始绘制

准备台风数据和图层

台风数据我是用的JSON。这里就简单描述一下数据中只要用到的字段信息

[
      {
        CODE: "202122",//台风编号
        DB7: null,//七级东北
        DB10: null,//十级东北
        DB12: null,//十二级东北
        DN7: null,//七级东南
        DN10: null,//十级东南
        DN12: null,//十二级东南
        LAT: 5.5,//维度
        LON: 140.9,//经度
        MOVE_DIR: null,//风向
        MOVE_SPEED: null,//风向速度
        OBJECTID: 27848,//id
        PRESS: 998,//中心气压
        SHIJIAN: null,
        STRENGTH: "台风(热带风暴级)",//强度
        TH: null,
        TIME: "2021-12-13-14",//日期
        WIND: 18,//最大风速
        XB7: null,//七级西北
        XB10: null,//十级西北
        XB12: null,//十二级西北
        XN7: null,//七级西南
        XN10: null,//十级西南
        XN12: null,//十二级西南
      },
   ]
  let tfsource = new ol.source.Vector({
      crossOrigin: 'anonymous',
      features: []
    })
    let tflayer = new ol.layer.Vector({
      source: tfsource
    })
   map.addLayer(tflayer)

绘制台风名称

// 利用第一个点 创建名称Overlay层 显示台风名称
 const nameDom = document.createElement('div')
    nameDom.setAttribute('class', 'typhoon-name-panel')
    nameDom.classList.add(lx)
    nameDom.innerHTML = label
    const position = [point.LON, point.LAT]
    const nameOverlay = new ol.Overlay({
      element: nameDom,
      position: position,
      wz: position,
      positioning: 'center-left',
      offset: [15, 0]
    })
    map.addOverlay(nameOverlay)
    map.getView().setCenter(position)

绘制台风轨迹点和轨迹线

    //point 为数组对象中每一个点数据
    // 点颜色 根据强度区分不同点的颜色
    let pointColor = this.setPointFillColor(point.STRENGTH)
    // 添加点
    if (point.LON &amp;&amp; point.LAT) {
      const feature = new ol.Feature({
        geometry: new ol.geom.Point([point.LON, point.LAT]),
        layerType: 'typhoonLyer',
        properties: point
      })
      // this.tfStyle为我提前定义到的各种类型的点样式
      feature.setStyle(this.tfStyle[pointColor.index])
     tflayer.getSource().addFeature(feature)
    }
  // 添加线
  let startPoint = [point.LON, point.LAT] 开始点
  let endPonit = [points[index - 1].LON, points[index - 1].LAT] 结束点
  let coords = [startPoint, endPonit]
  let lineDash 线段样式 实线或者虚线
  if (lx !== 'ss') {
    lineDash = [0]
  } else {
    lineDash = (!point.predict &amp;&amp; !points[index - 1].predict) ? [0] : [10]
  }
// this.tfLinStyle 为提前定义好的线段样式
  let lineStyle = lineDash[0] === 0 ? this.tfLinStyle[pointColor.index] : this.tfLinStyle[6]
  let feature = new ol.Feature({
    geometry: new ol.geom.LineString(coords),
    layerType: 'typhoonLyer',
    properties: point
  })
  feature.setStyle(lineStyle)
  tflayer.getSource().addFeature(feature)

代码解析 文中提到的this.tfLinStyle 和 this.tfStyle 为提前定义好的点和线的样式,这么做的目的是为了提高性能,减少oplayer中new 一堆重复性的样式堆栈,消耗内存

this.tfStyle = [
      new ol.style.Style({
        image: new ol.style.Circle({
          radius: 6,
          fill: new ol.style.Fill({
            color: '#eed139'
          }),
          stroke: new ol.style.Stroke({
            color: 'rgba(0, 0, 0, 0.6)',
            width: 1
          })
        })
      }),
      new ol.style.Style({
        image: new ol.style.Circle({
          radius: 6,
          fill: new ol.style.Fill({
            color: '#0000ff'
          }),
          stroke: new ol.style.Stroke({
            color: 'rgba(0, 0, 0, 0.6)',
            width: 1
          })
        })
      }),
      new ol.style.Style({
        image: new ol.style.Circle({
          radius: 6,
          fill: new ol.style.Fill({
            color: '#0f8000'
          }),
          stroke: new ol.style.Stroke({
            color: 'rgba(0, 0, 0, 0.6)',
            width: 1
          })
        })
      }),
      new ol.style.Style({
        image: new ol.style.Circle({
          radius: 6,
          fill: new ol.style.Fill({
            color: '#fe9c45'
          }),
          stroke: new ol.style.Stroke({
            color: 'rgba(0, 0, 0, 0.6)',
            width: 1
          })
        })
      }),
      new ol.style.Style({
        image: new ol.style.Circle({
          radius: 6,
          fill: new ol.style.Fill({
            color: '#fe00fe'
          }),
          stroke: new ol.style.Stroke({
            color: 'rgba(0, 0, 0, 0.6)',
            width: 1
          })
        })
      }),
      new ol.style.Style({
        image: new ol.style.Circle({
          radius: 6,
          fill: new ol.style.Fill({
            color: '#fe0000'
          }),
          stroke: new ol.style.Stroke({
            color: 'rgba(0, 0, 0, 0.6)',
            width: 1
          })
        })
      })
    ]
    this.tfLinStyle = [
      new ol.style.Style({
        stroke: new ol.style.Stroke({
          color: '#eed139',
          width: 2,
          lineDash: [0]
        })
      }),
      new ol.style.Style({
        stroke: new ol.style.Stroke({
          color: '#0000ff',
          width: 2,
          lineDash: [0]
        })
      }),
      new ol.style.Style({
        stroke: new ol.style.Stroke({
          color: '#0f8000',
          width: 2,
          lineDash: [0]
        })
      }),
      new ol.style.Style({
        stroke: new ol.style.Stroke({
          color: '#fe9c45',
          width: 2,
          lineDash: [0]
        })
      }),
      new ol.style.Style({
        stroke: new ol.style.Stroke({
          color: '#fe00fe',
          width: 2,
          lineDash: [0]
        })
      }),
      new ol.style.Style({
        stroke: new ol.style.Stroke({
          color: '#fe0000',
          width: 2,
          lineDash: [0]
        })
      }),
      new ol.style.Style({
        stroke: new ol.style.Stroke({
          color: '#fe0000',
          width: 2,
          lineDash: [10]
        })
      })]

setPointFillColor函数判别点类型

setPointFillColor (type) {
    let pointFillColor = '#eed139'
    let index = 0
    switch (type) {
      case '台风(热带低压)':
      case '热带低压':
        pointFillColor = '#eed139'
        index = 0
        break
      case '热带风暴':
      case '热带风暴级':
      case '台风(热带风暴)':
      case '台风(热带风暴级)':
        pointFillColor = '#0000ff'
        index = 1
        break
      case '台风(强热带风暴级)':
      case '强热带风暴级':
      case '强热带风暴':
        pointFillColor = '#0f8000'
        index = 2
        break
      case '台风':
        pointFillColor = '#fe9c45'
        index = 3
        break
      case '强台风':
      case '台风(强台风级)':
      case '台风(强台风)':
        pointFillColor = '#fe00fe'
        index = 4
        break
      case '超强台风':
      case '台风(超强台风级)':
      case '台风(超强台风)':
        pointFillColor = '#fe0000'
        index = 5
        break
    }
    return {pointFillColor, index}
  }

以上代码很完整,我加了注释,整体思路总结如下:

  • 先获取台风数据
  • 构造台风轨迹图层并添加到地图容器
  • 循环构造点、线及名称要素对象 添加到台风图层数据源中
  • 添加风圈动画

添加台风风圈动画

根据判断台风类型是否是实时台风还是历史台风进行添加台风风圈,在数据中获取到最后一个实时点位数据,利用Overlay添加一个动态图标,我是利用的gif图片

    let key = LX + '-' + tfbh
    const points = this._typhoonData[key].point
    let fqindex = points.findIndex(item => !item.predict)
    // 添加风圈
    if (fqindex) {
      const nameDom = document.createElement('div')
      nameDom.setAttribute('class', 'typhoon-area')
      let nameOverlay = new ol.Overlay({
        position: [points[fqindex].LON, points[fqindex].LAT],
        positioning: 'center-bottom',
        element: nameDom, // 绑定上面添加的元素
        stopEvent: false,
        offset: [-15, -15]// 图片偏移量
      })
      this.viewer.addOverlay(nameOverlay)
      this._tfenterCollection[key]['areaoverlay'] = nameOverlay
    }

让台风轨迹动起来

加载的时候利用定时器,一个点位一个点位的绘制,这样看起来就有动画效果啦

 this._typhoonPlayFlag[key] = setInterval(() => {
      去干些事请
    }, 50)

结尾

这里我只是大致的描述了我绘制台风轨迹的一些思路和大致方法,具体项目中,我把整个过场都封装成一个class 类,毕竟台风可能是有多条的,而且还需要做一些显示隐藏等的一些操作,我这里不做过多描述,仅做为一些思路分享,更多关于vue openlayers台风轨迹的资料请关注我们其它相关文章!

(0)

相关推荐

  • vue使用天地图、openlayers实现多个底图叠加显示效果

    实现效果: 需求:根据返回的经纬度列表通过天地图.openlayers实现底图添加(航道图层.线图层.水深图层) tk:自己申请的密钥 安装opelayers cnpm i -S ol #或者 npm install ol <script> // openlayers地图 import "ol/ol.css"; import { Icon, Style, Stroke } from "ol/style"; import 'ol/ol.css' impor

  • vue-openlayers实现地图坐标弹框效果

    本文实例为大家分享了vue-openlayers实现地图坐标弹框的具体代码,供大家参考,具体内容如下 openlayers 这个效果是点击地图,弹出坐标信息. 点击地图边缘时,底图会跟着移动,使弹窗能完整显示出来. <template> <div class="vm"> <h2 class="h-title">弹窗 popup</h2> <div id="map" class="ma

  • vue+openlayers绘制省市边界线

    本文实例为大家分享了vue+openlayers绘制省市边界线的具体代码,供大家参考,具体内容如下 1.创建项目 vue init webpack ol_vue 2.安装ol依赖包 npm install ol 3.引入axios npm install axios --save 文件目录:src/main.js import Vue from 'vue' import router from './router' import App from './App' import axios fro

  • vue利用openlayers实现动态轨迹

    目录 实现效果 创建一个地图容器 引入地图相关对象 创建地图对象 创建一条线路 画一条线路 添加起.终点 添加小车 准备开车 完整代码 实现效果 今天介绍一个有趣的gis小功能:动态轨迹播放!效果就像这样: 这效果看着还很丝滑!别急,接下来教你怎么实现.代码示例基于parcel打包工具和es6语法,本文假设你已经掌握相关知识和技巧. gis初学者可能对openlayers(后面简称ol)不熟悉,这里暂时不介绍ol了,直接上代码,先体验下感觉. 创建一个地图容器 引入地图相关对象 import M

  • Vue+Openlayers自定义轨迹动画

    本文实例为大家分享了Vue+Openlayers实现轨迹动画的具体代码,供大家参考,具体内容如下 <template> <div class="map-warp"> <h3> <a href="https://openlayers.org/en/latest/examples/feature-move-animation.html?q=polyline" target="_bank" >Openla

  • vue利用openlayers加载天地图和高德地图

    目录 一.天地图部分 1.在vue中安装openlayers 二.高德地图部分 一.天地图部分 1.在vue中安装openlayers npm i --save ol 这里说的vue是基于脚手架构建的. 新建个页面,也就是vue文件,配置好路由.接着就是可以直接放入我的代码运行显示了. <template> <div class="wrapper"> <div>天地图</div> <div class="map"

  • vue openlayers实现台风轨迹示例详解

    目录 功能描述 创建一个地图容器 引入地图相关对象 创建地图对象 开始绘制 准备台风数据和图层 绘制台风名称 绘制台风轨迹点和轨迹线 添加台风风圈动画 让台风轨迹动起来 结尾 功能描述 台风轨迹点实时绘制,根据不同点的类型绘制不同的轨迹点颜色 轨迹线绘制,涉及实时轨迹线段与预报轨迹线,根据台风类型绘制成不同颜色 当前正在发生的台风还需增加当前台风所风圈位置 台风轨迹点点击弹框显示轨迹点信息 openlayers(简称ol)这里不做介绍,刚开始写此类文章,直接上代码 创建一个地图容器 引入地图相关

  • vue 之 .sync 修饰符示例详解

    在一些情况下,我们可能会需要对一个 prop (父子组件传递数据的属性) 进行"双向绑定". 在vue 1.x 中的 .sync 修饰符所提供的功能.当一个子组件改变了一个带 .sync 的prop的值时,这个变化也会同步到父组件中所绑定的值. 这很方便,但也会导致问题,因为它破坏了单向数据流.(数据自上而下流,事件自下而上走) 由于子组件改变 prop 的代码和普通的状体改动代码毫无区别,所以当你光看子组件的代码时,你完全不知道它合适悄悄地改变了父组件的状态. 这在 debug 复杂

  • Vue项目接入Paypal实现示例详解

    一.支付流程 在paypal的官网上给出了这个按钮内部封装的流程,整个流程只需要用户点击按钮,触发创建订单事件,然后我们再监听用户支付成功的回调,拿到订单id传给后端,让后端再进行一次校验. 二.实现方案 接入方式 优点 缺点 相关资料 在html中插入paypal的script脚本 实现方式比较简单 1.安全性问题:公司的client_id会暴露在代码中 2.引用的按钮样式比较难自定义 官方文档:https://developer.paypal.com/docs/checkout/integr

  • Vue响应式原理的示例详解

    Vue 最独特的特性之一,是非侵入式的响应系统.数据模型仅仅是普通的 JavaScript 对象.而当你修改它们时,视图会进行更新.聊到 Vue 响应式实现原理,众多开发者都知道实现的关键在于利用 Object.defineProperty , 但具体又是如何实现的呢,今天我们来一探究竟. 为了通俗易懂,我们还是从一个小的示例开始: <body> <div id="app"> {{ message }} </div> <script> v

  • Vue 服务端渲染SSR示例详解

    目录 手写Vue服务端渲染 一.开始vue-ssr之旅 二.采用模板渲染 三.ssr目录创建 四.通过webpack实现编译vue项目 app.js client-entry.js server-entry.js 五.配置客户端打包和服务端打包 六.配置运行脚本 七.服务端配置 七.通过json配置createBundleRenderer方法 八.集成VueRouter 配置入口文件 配置组件信息 防止刷新页面不存在 保证异步路由加载完成 十.集成vuex配置 在后端更新vuex 在浏览器运行时

  • vue前端实现打印下载示例详解

    目录 html2canvas介绍 jspdf介绍 printjs介绍 html2canvas介绍 分享一下几个后台管理系统比较常用的插件:下载.打印 html2canvas是在浏览器上对网页进行截图操作,实际上是操作DOM,这个插件也有好长时间了,比较稳定,目前使用还没有遇到什么bug jspdf介绍 如果下载出来是pdf文件,可以加上jspdf插件,会先通过html2canvas把页面转化成base64图片,再通过jspdf导出 安装 npm i html2canvas jspdf 或 yar

  • Vue extends 属性的用法示例详解

    目录 引言 App.vue Son.vue HelloWorld.vue 小结 引言 最近在看抖音——<小山与 bug>,看到一个很神奇的 Vue 继承组件的方法,后来专门去翻了 element 和 iview 的源码,发现这个属性的用法好像在这些框架里还没有用到过,怀着试一试的态度,我就自己搭建了个测试项目,发现其实还是挺好用的,甚至有望代替目前我们前端框架业务代码混入的底层实现.话不多说,直接上代码: App.vue <template> <div> <Son

  • vue 实现滑动块解锁示例详解

    目录 引言 下载需要用到的组件库 书写登录页面 template 结构: script 逻辑: style 样式: 登录页面效果展示: 写滑动解锁组件 template 模板: script 代码: style 样式: 将滑动组件运用到我们的 Login 组件中: 补充逻辑代码 最终效果: 引言 从0开始,写一个登录滑动解锁的功能. 首先,新创建一个 vue 项目. 或者在已有的项目写也可以. 将无用的代码删一下. 下载需要用到的组件库 1.下载 element-ui. yarn add ele

  • vue选项卡Tabs组件实现示例详解

    目录 概述 效果图 实现过程 组件分析 所需的前置知识 项目组件文件夹 Tabs.vue TabPane.vue render.js index.js 使用 总结 概述 前端项目中,多数页面涉及到选项卡切换,包括路由切换,指令v-if等,本质上其实和选项卡切换思想差不多,如果是个简单的选项卡,还是很简单的,我们也不需要什么组件库的组件,自己也能几行代码写出来,但是涉及到动画,尺寸计算,拖拽的功能的时候,多数情况下,自己写还是要花点时间的,组件库就提供了现成的,拿来改改样式就行,为了对这个组件更加

  • vue组合式API浅显入门示例详解

    目录 正文 组合式API setup 变量声明 目前比起选项式API的优点 生命周期 正文 在react推出了hook之后,vue也在vue3里面添加了组合式API,鉴于这个时间间隔,我有理由认为组合式api和hook还是有一些关系的.不过在我具体的使用中,我并没发现这两个方法太多的相同点,不过鉴于vue自动发布之后就与react之间那剪不断理还乱的量子力学关系,估计会有很多人会问及这俩之间的异同.我还没到能分辨出异同的地步,就简单的介绍一下vue的组合式API吧. 组合式API 在vue3.0

随机推荐