zoukankan      html  css  js  c++  java
  • Vue中使用openlayer做风场图

    <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 :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, XYZ } 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,
          windData: null,
          center: [113.629225, 34.638611],
          heatData: {
            type: 'FeatureCollection',
            features: [
              { type: 'Point', coordinates: [104.4, 31.19] },
              { type: 'Point', coordinates: [113.3, 30.6] },
              { type: 'Point', coordinates: [123.3, 30.6] },
              { type: 'Point', coordinates: [105.3, 30.6] },
              { type: 'Point', coordinates: [106.3, 30.6] },
              { type: 'Point', coordinates: [109.3, 31.6] },
              { type: 'Point', coordinates: [109.3, 30.6] },
              { type: 'Point', coordinates: [108.3, 32.6] },
              { type: 'Point', coordinates: [118.3, 31.6] },
              { type: 'Point', coordinates: [108.3, 33.6] },
              { type: 'Point', coordinates: [108.3, 32.6] },
              { type: 'Point', coordinates: [100.3, 30.6] },
              { type: 'Point', coordinates: [109.3, 30.6] },
              { type: 'Point', coordinates: [108.3, 31.6] },
              { type: 'Point', coordinates: [118.3, 30.6] },
            ],
          },
          view: null,
          points: [
            {
              address: '河南省商丘市',
              name: '测试',
              id: '1000',
              lon: [113.629225, 34.638611],
            },
            {
              address: '河南省郑州市',
              name: '同样是测试',
              id: '1001',
              lon: [113.28, 35.54],
            },
          ],
          layer: null,
          windLayers: null,
          online: true,
          loading: false,
        }
      },
      methods: {
        initMap() {
          let _this = this
          // 热力图层
          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(),
          })
          // [12648360.426730713, 4130742.144151326]
          // 地图中心
          let view = new View({
            center: transform(this.center, 'EPSG:4326', 'EPSG:3857'),
            zoom: 5,
            minZoom: 5,
            maxZoom: 15,
          })
    
          // 高德地图
          var gaodeLayer = new TileLayer({
            source: new XYZ({
              url: 'http://webst0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}',
            }),
          })
          // 实例化底图
          this.map = new Map({
            layers: [tile, vector],
            target: 'map',
            view,
          })
    
          // 创建点标记样式
          function createLabelStyle(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: 0.7,
                opacity: 1,
                anchor: [0.5, 1], // 解决缩放过程中点标记偏移问题
                src: imgs,
              }),
            })
          }
    
          // 显示点标记
          for (let i = 0; i < this.points.length; i++) {
            addMarker(this.points[i])
          }
          // 添加点标记
          function addMarker(info) {
            // 解决 openlayers 坐标偏移问题
            let originalLon = fromLonLat(info.lon)
            let conversionLon = [originalLon[0] - 667.1484120152891, originalLon[1] + 156.9580022119917]
    
            let iconFeature = new Feature({
              geometry: new Point(conversionLon),
              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,
            offset: [0, -10],
          })
    
          // 设置显示内容
          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', e => {
            let coodinate = e.coordinate
            let feature = _this.map.forEachFeatureAtPixel(e.pixel, function(feature, layer) {
              return feature
            })
            if (feature) {
              if (!feature.values_.id) {
                return false
              }
              content.innerHTML = ''
              addInfo(feature.values_)
              overlay.setPosition(fromLonLat(feature.values_.lon))
              _this.map.addOverlay(overlay)
            }
          })
          // 点击关闭事件
          popupCloser.addEventListener('click', () => {
            overlay.setPosition(undefined)
          })
    
          // 鼠标移入改变样式
          this.map.on('pointermove', e => {
            let pixel = _this.map.getEventPixel(e.originalEvent)
            let hit = _this.map.hasFeatureAtPixel(pixel)
            _this.map.getTargetElement().style.cursor = hit ? 'pointer' : ''
          })
        },
        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.windData = Data
              this.windLayers = new WindLayer(_this.windData, {
                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: 16,
                  globalAlpha: 0.6,
                  velocityScale: 1 / 50,
                  paths: 2000,
                  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>
    @import url('../../static/css/openlayers.css');
    </style>
  • 相关阅读:
    如何准备面试复试(1)
    如何应对糟糕的面试官(2)
    美国:经济危机让烟民吸烟量增加
    MOV 指令的注意事项
    一个简单的ajax无刷新翻页的程序
    SQL注入漏洞全接触
    php+mysql非暴力查表的注入语句写法总结
    在你的成长过程中,有五个人非常重要
    爱就在那里,不增不减
    php的一些书籍
  • 原文地址:https://www.cnblogs.com/lyt520/p/14025839.html
Copyright © 2011-2022 走看看