<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>