vue項目中在openlayers地圖上展示echarts圖表

思路:

1、創建一個地圖組件mapView,使用openlayers進行地圖展示
2、創建一個圖表組件chart,用於呈現圖表
3、創建一個overlay組件,在模板中使用chart組件;利用openlayers的ol.Overlay類來把overlay組件添加到地圖上。

示例代碼

1、數據

以這次新冠病毒數據爲例,這裏是今年2月份全國新增新冠肺炎患者的數據(數據源來自百度),分爲全國的新增數量和湖北省內的新增數量。

ncovData.js

const ncovData = {
  add: {
    startDate: '2.1',
    endDate: '2.29',
    quanguoTotal: [2590, 2829, 3235, 3887, 3694, 3151, 3399, 2653, 3073, 2484, 2022, 15153, 5093, 2644, 2009, 2051, 1891, 1751, 825, 892, 399, 649, 416, 517, 411, 440, 329, 430, 579],
    hubeiTotal: [1921, 2103, 2345, 3156, 2987, 2447, 2841, 2147, 2618, 2097, 1638, 14840, 4823, 2420, 1843, 1933, 1807, 1693, 775, 631, 366, 630, 398, 499, 401, 409, 318, 423, 570]
  }
}

export default ncovData

2、圖表組件

在圖表組件中,以折線圖的形式來展示數據。
chart.vue

<template>
  <div>
    <div ref="chart" class="overlay-chart"></div>
  </div>
</template>
<script>
import echarts from 'echarts'
export default {
  data () {
    return {
    }
  },
  props: ['source'],
  mounted () {
    this.chart = echarts.init(this.$refs['chart'])
    if (this.source) {
      this.drawChart(this.source)
    }
  },
  methods: {
    drawChart (data) {
      let dateLine = Array.apply(null, { length: 29 }).map((item, index) => {
        return '2.' + (index + 1).toString()
      })

      let option = {
        title: {
          text: '全國/湖北疫情趨勢'
        },
        tooltip: {
          trigger: 'axis'
        },
        legend: {
          data: ['全國新增', '湖北新增']
        },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: dateLine
        },
        yAxis: {
          type: 'value'
        },
        series: [
          {
            name: '全國新增',
            type: 'line',
            data: data.addTotal
          },
          {
            name: '湖北新增',
            type: 'line',
            data: data.hubeiAddTotal
          }
        ]
      }

      this.chart.setOption(option)
    }
  }
}
</script>
<style lang="less" scoped>
  .overlay-chart{
    width: 100%;
    height: 100%;
  }
</style>

3、overlay組件

overlayChart .vue

<template>
  <div v-if="visible" class="overlay-container">
    <div class="overlay-header">
      <span>{{name}}</span>
    </div>
    <div>
      <chart class="chart-container" v-if="overlay" :source="chartData"></chart>
    </div>
  </div>
</template>
<script>
import Overlay from 'ol/Overlay'
import chart from './chart'
export default {
  data () {
    return {
      visible: false,
      name: '疫情趨勢',
      overlay: undefined
    }
  },
  components: {chart},
  methods: {
    show () {
      let overlay = new Overlay({
        element: this.$mount().$el,
        stopEvent: false, // 設爲false,允許事件傳播
        autoPanAnimation: {
          duration: 250
        },
        // offset: [20,0],
        position: this.position,
        positioning: 'center-left',
        className: 'point-overlay'
      })
      this.map.addOverlay(overlay)
      this.overlay = overlay
      this.visible = true
    },
    close () {
      this.visible = false
    }
  }
}
</script>
<style lang="less">
  .overlay-container{
    width: 480px;
    min-height: 320px;
    background-color: #f5f5f5;
    .overlay-header{
      height: 20px;
      position: relative;
      background-color: #171819;
      color: #cec3ce;
      text-align: center;
      .name{
        font-size: 16px;
				font-weight: bold;
				line-height: 1.2;
        width: 95%;
      }
    }
    .chart-container{
      height: 360px;
      width: 100%;
    }
  }
</style>

這個組件中,我們引入了上面的chart組件,並向其中傳遞數據。另外,在show方法中,創建了一個ol.Overlay實例,把它添加到map地圖對象上。

4、地圖組件

mapView.vue

<template>
  <div id="map">
  </div>
</template>
<script>
import Vue from 'vue'
import { Map, View } from 'ol'
import TileLayer from 'ol/layer/Tile'
import XYZ from 'ol/source/XYZ'
import overlayChart from './overlayChart'
import ncovData from './ncovData'

const OverlayChart = Vue.extend(overlayChart)

export default {
  data () {
    return {
      map: undefined,
      overlayChartObj: undefined,
      data: {

      }
    }
  },
  mounted () {
    this.init()
  },
  methods: {
    /**
     * 地圖初始化
     */
    init () {
      let baseLayer = new TileLayer({
        source: new XYZ({
          url: 'https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}'
        })
      })
      this.map = new Map({
        target: 'map',
        layers: [baseLayer],
        view: new View({
          projection: 'EPSG:4326',
          zoom: 5,
          center: [114, 32]
        })
      })

      console.log(ncovData)
      this.map.on('click', (evt) => {
        let data = ncovData.add
        this.showOverlayChart(evt.coordinate, data)
      })
    },

    /**
     * 顯示圖表
     */
    showOverlayChart (position, data) {
      if (this.overlayChartObj) {
        this.overlayChartObj.close()
        this.overlayChartObj = null
      }

      this.overlayChartObj = this.createOverlay({
        position,
        data
      })
      this.overlayChartObj.show()
    },

    /**
     * 創建一個overlay組件實例
     */
    createOverlay (params) {
      let obj = new OverlayChart({
        data: {
          map: this.map,
          position: params.position,
          chartData: params.data
        }
      })

      return obj
    }
  }
}
</script>

在這個mapview組件中,以vue.extend方式引入了overlayChart組件,然後再在必要的時候,new出一個overlayChart的實例,通過overlayChart的show方法來呈現想要的圖表。
這裏,當我在地圖上任意位置點擊時,即彈出圖表。

參數傳遞

從mapView -> overlayChart, 通過在new對象時傳入data參數,數據包裝在data內,不要再overlayChart中使用props
從overlayChart -> chart,props方式傳遞。

最終效果

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章