Vue中开启关闭风场

<template>
  <div class="box">
    <div ref="emap" id="map"></div>
    <div id="popup" class="ol-popup">
      <a href="#" id="popup-closer" class="ol-popup-closer"></a>
      <div id="popup-content"></div>
    </div>
    <div class="close_on">
      <!-- <el-button type="primary" size="default" @click="addWind"></el-button>
      <el-button type="primary" size="default" @click="closeWind">关闭风场</el-button> -->
      <el-button :loading="loading" type="primary" size="mini">
        <span v-if="online" @click="addWind">开启风场</span>
        <span v-else @click="closeWind">关闭风场</span>
      </el-button>
    </div>
  </div>
</template>

<script>
import 'ol/ol.css'
import Map from 'ol/Map'
import Stamen from 'ol/source/Stamen'
import VectorSource from 'ol/source/Vector'
import View from 'ol/View'
import { Heatmap as HeatmapLayer, Tile as TileLayer, Vector as LayerVec } from 'ol/layer'
import GeoJSON from 'ol/format/GeoJSON'

import olsourceOSM from 'ol/source/OSM'
import { get as getProjection, transform, fromLonLat } from 'ol/proj'

import { Vector as SourceVec, Cluster } from 'ol/source'
import { Feature, Overlay } from 'ol'
import { Point } from 'ol/geom'
import { Style, Icon, Stroke, Fill, Text, Circle } from 'ol/style'

import { WindLayer } from 'ol-wind'

export default {
  name: 'heatmap',
  data() {
    return {
      map: null,
      center: [113.0521, 34.6006],
      heatData: {
        type: 'FeatureCollection',
        features: [
          { type: 'Point', coordinates: [104.4, 31.19], count: 100 },
          { type: 'Point', coordinates: [113.3, 30.6], count: 19 },
          { type: 'Point', coordinates: [123.3, 30.6], count: 419 },
          { type: 'Point', coordinates: [105.3, 30.6], count: 319 },
          { type: 'Point', coordinates: [106.3, 30.6], count: 719 },
          { type: 'Point', coordinates: [109.3, 31.6], count: 519 },
          { type: 'Point', coordinates: [109.3, 30.6], count: 319 },
          { type: 'Point', coordinates: [108.3, 32.6], count: 139 },
          { type: 'Point', coordinates: [118.3, 31.6], count: 129 },
          { type: 'Point', coordinates: [108.3, 33.6], count: 190 },
          { type: 'Point', coordinates: [108.3, 32.6], count: 189 },
          { type: 'Point', coordinates: [100.3, 30.6], count: 1 },
          { type: 'Point', coordinates: [109.3, 30.6], count: 119 },
          { type: 'Point', coordinates: [108.3, 31.6], count: 200 },
          { type: 'Point', coordinates: [118.3, 30.6], count: 300 },
        ],
      },
      view: null,
      points: [
        {
          address: '河南省商丘市',
          name: '测试',
          id: '1000',
          lon: ['113.28', '34.54'],
        },
        {
          address: '河南省郑州市',
          name: '同样是测试',
          id: '1001',
          lon: ['113.28', '35.54'],
        },
      ],
      layer: null,
      windLayers: null,
      online: true,
      loading: false,
    }
  },
  methods: {
    initMap() {
      let _this = this
      let projection = getProjection('EPSG:4326')
      // 热力图层
      let vector = new HeatmapLayer({
        source: new VectorSource({
          features: new GeoJSON().readFeatures(this.heatData, {
            dataProjection: 'EPSG:4326',
            featureProjection: 'EPSG:3857',
          }),
        }),
        blur: 20,
        radius: 10,
      })

      // 底图1
      let tile = new TileLayer({
        source: new olsourceOSM(),
      })

      // 地图中心
      let view = new View({
        center: transform(this.center, 'EPSG:4326', 'EPSG:3857'),
        zoom: 5,
        minZoom: 5,
        maxZoom: 13,
      })

      // 实例化底图
      this.map = new Map({
        layers: [tile, vector],
        target: 'map',
        view,
      })

      // 创建点标记样式
      let createLabelStyle = function(feature) {
        let imgs = ''
        if (feature.values_.id == '1000') {
          imgs = '/static/warning_icon/normal_green.png'
        } else {
          imgs = '/static/warning_icon/normal_red.png'
        }
        return new Style({
          image: new Icon({
            scale: 1,
            opacity: 1,
            src: imgs,
          }),
        })
      }

      // 显示点标记
      for (let i = 0; i < this.points.length; i++) {
        addMarker(this.points[i])
      }
      function addMarker(info) {
        let iconFeature = new Feature({
          geometry: new Point(fromLonLat(info.lon)),
          name: info.name,
          id: info.id,
          address: info.address,
          lon: info.lon,
        })

        // 调用 createLabelStyle, 添加样式
        iconFeature.setStyle(createLabelStyle(iconFeature))

        // 矢量图层数据源
        let vectorSource = new VectorSource({
          features: [iconFeature],
        })
        // 矢量标注图层
        let vectorLayer = new LayerVec({
          source: vectorSource,
        })
        _this.map.addLayer(vectorLayer)
      }

      /*********************显示弹出层**************************/
      let container = document.getElementById('popup')
      let content = document.getElementById('popup-content')
      let popupCloser = document.getElementById('popup-closer')

      // 创建覆盖物图层
      let overlay = new Overlay({
        element: container,
        autoPan: true,
      })

      // 鼠标移入改变样式
      this.map.on('pointermove', function(e) {
        let pixel = _this.map.getEventPixel(e.originalEvent)
        let hit = _this.map.hasFeatureAtPixel(pixel)
        _this.map.getTargetElement().style.cursor = hit ? 'pointer' : ''
      })

      // 设置显示内容
      function addInfo(info) {
        return (content.innerHTML =
          "<p class='info'>" +
          info.address +
          '</p>' +
          "<p class='info'>" +
          info.id +
          '</p>' +
          "<p class='info'>" +
          info.name +
          '</p>')
      }

      // 鼠标点击覆盖物
      this.map.on('click', function(e) {
        let feature = _this.map.forEachFeatureAtPixel(e.pixel, function(feature, layer) {
          return feature
        })
        if (feature) {
          if (!feature.values_.id) {
            return false
          }
          let coodinate = e.coordinate
          content.innerHTML = ''
          addInfo(feature.values_)
          overlay.setPosition(fromLonLat(feature.values_.lon))
          _this.map.addOverlay(overlay)
        }
      })
      // 点击关闭事件
      popupCloser.addEventListener('click', function() {
        overlay.setPosition(undefined)
      })
    },
    addWind() {
      // 开启风场
      let _this = this
      _this.loading = true
      _this.$ajax
        .get('https://sakitam-fdd.github.io/wind-layer/data/wind.json')
        .then(res => {
          let Data = res.data
          this.windLayers = new WindLayer(Data, {
            windOptions: {
              colorScale: [
                'rgb(36,104, 180)',
                'rgb(60,157, 194)',
                'rgb(128,205,193 )',
                'rgb(151,218,168 )',
                'rgb(198,231,181)',
                'rgb(238,247,217)',
                'rgb(255,238,159)',
                'rgb(252,217,125)',
                'rgb(255,182,100)',
                'rgb(252,150,75)',
                'rgb(250,112,52)',
                'rgb(245,64,32)',
                'rgb(237,45,28)',
                'rgb(220,24,32)',
                'rgb(180,0,35)',
              ],
              lineWidth: 2,
              frameRate: 20,
              globalAlpha: 0.6,
              velocityScale: 1 / 50,
              paths: 3000,
              generateParticleOption: false,
            },
          })
          _this.$nextTick(() => {
            _this.map.addLayer(_this.windLayers)
            _this.online = false
            _this.loading = false
            _this.$message({
              type: 'success',
              message: '开启风场成功',
            })
          })
        })
        .catch(e => {
          console.log(e)
        })
    },
    closeWind() {
      // 关闭风场
      this.map.removeLayer(this.windLayers)
      this.online = this.online ? false : true
      this.$message({
        type: 'success',
        message: '关闭风场成功!',
      })
    },
  },
  mounted() {
    this.initMap()
  },
}
</script>
<style>
#popup-content .info {
  margin: 0px;
  padding: 0px;
}
</style>
<style scoped>
.box {
  position: relative;
}

.label {
  font-size: 20px;
}
#map {
  width: 100%;
  height: 99vh;
}
.ol-popup {
  position: absolute;
  background-color: #eeeeee;
  -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
  filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
  padding: 15px;
  border-radius: 10px;
  border: 1px solid #cccccc;
  bottom: 12px;
  left: -100px;
  width: 180px;
}

.ol-popup:after,
.ol-popup:before {
  top: 100%;
  border: solid transparent;
  content: '';
  height: 0;
  width: 0;
  position: absolute;
  pointer-events: none;
}

.ol-popup:after {
  border-top-color: #eeeeee;
  border-width: 10px;
  left: 48px;
  margin-left: 40px;
}

.ol-popup:before {
  border-top-color: #cccccc;
  border-width: 10px;
  left: 48px;
  margin-left: 40px;
}

.ol-popup-closer {
  text-decoration: none;
  position: absolute;
  top: 2px;
  right: 8px;
}

.ol-popup-closer:after {
  content: '✖';
}

.close_on {
  position: absolute;
  top: 10px;
  right: 10px;
}
</style>


参考链接:
https://github.com/sakitam-fdd/wind-layer(官方github)
https://sakitam-fdd.github.io/wind-layer/ 参考文章:https://blog.csdn.net/u010065726/article/details/106338194/ 注意:需要安装ol和ol-wind, npm i ol ol-wind --save

 

posted @ 2020-11-24 16:35  yw3692582  阅读(506)  评论(4编辑  收藏  举报