引用ol7.4 包找不到ol.css的问题可以尝试在package.json中添加 "autoprefixer": "^9.8.8",或固定这个插件版本
主要实现画点、线、多边形、轨迹图、热力图功能、高亮分区;
代码主要结构关系图如下
<template>
<div class="demo01">
<div span="24" type="flex" align="center">
<!--分区管理显示 -->
<div v-if="showGroupBtn.zoomBtn">
<Button type="primary" @click="beginDrawZoom">开始绘画分区</Button>
<Button type="primary" @click="endDrawZoom">结束绘画分区</Button>
<Button type="primary" @click="clearCurZoom">清除绘画分区</Button>
<Button type="primary" @click="beginDrawCenterIcon">开始画区域中心点</Button>
<Button type="primary" @click="endDrawCenterIcon">结束画区域中心点</Button>
</div>
<!-- 鸟情 -->
<div v-if="showGroupBtn.positionBtn">
<Button type="primary" @click="clearLayerByName('pointPosition')">清除</Button>
</div>
<!-- <Button type="primary" @click="setScale('max')">放大</Button>
<Button type="primary" @click="setScale('min')">缩小</Button> -->
<!-- <Button type="primary" @click="beginDraw">开始绘画</Button> -->
<!-- <Button type="primary" @click="endDraw">结束绘画</Button> -->
<!-- <Button type="primary" @click="clearSelectDraw">清除选定区域</Button> -->
<!-- <Button type="primary" @click="clearAllDraw">清空所有区域</Button>
<Button type="primary" @click="drawData">加载已有区域</Button> -->
<!-- <Button type="primary" @click="drawPoint">加载图标点</Button> -->
<!-- <Button type="primary" @click="beginDrawCustomIcon">开始画自定义图标</Button> -->
<!-- <Button type="primary" @click="endDrawCustomIcon">结束画自定义图标</Button> -->
<!-- <Button type="primary" @click="notLoadTitle">不加载标注(默认)</Button>
<Button type="primary" @click="loadTitle">加载标注(字体模糊)</Button>
<Button type="primary" @click="showFlashPoint">显示闪烁点</Button>
<Button type="primary" @click="heatMap">显示热力图</Button>
<Button type="primary" @click="loadTj">加载天津机场</Button>
<Button type="primary" @click="loadHz">加载杭州机场</Button>
<Button type="primary" @click="drawText">标注点测试</Button> -->
</div>
<div :id="mapId" class="map" v-bind:style="{ height: dynamicHeight }"></div>
<msg-model ref="msgForm" :data="data" @changeShow="changeshow()"></msg-model>
</div>
</template>
<script>
/*
地图的内网引用
手动放大缩小
*/
import {never} from 'ol/events/condition'
import {singleClick} from 'ol/events/condition'
import Collection from 'ol/Collection'
import Modify from 'ol/interaction/Modify'
import Map from 'ol/Map'
import XYZ from 'ol/source/XYZ'
// import TileLayer from 'ol/layer/Tile';
import View from 'ol/View'
import { Fill, Style, Stroke, Icon, Circle, Text } from 'ol/style'
import 'ol/ol.css'
import { Tile as TileLayer, Vector as VectorLayer, Heatmap as HeatmapLayer } from 'ol/layer'
import { TileWMS, Vector as VectorSource } from 'ol/source'
import { Select, Draw } from 'ol/interaction'
import { getArea } from 'ol/sphere'
import Feature from 'ol/Feature'
import { Polygon, Point,LineString } from 'ol/geom'
import Overlay from 'ol/Overlay'
import { getVectorContext } from 'ol/render'
import houseIcon from '@/assets/house.png'
import icon63 from '@/assets/survey/63.png'
import icon64 from '@/assets/survey/64.png'
import icon65 from '@/assets/survey/65.png'
import icon66 from '@/assets/survey/66.png'
import icon67 from '@/assets/survey/67.png'
import icon68 from '@/assets/survey/68.png'
import LineArrowIcon from '@/assets/line_arrow.png'
import msgModel from './msgModel'
import { transform } from 'ol/proj'
import { getAction } from '../../api/manage'
import { FLOAT } from 'ol/webgl'
const vector = new VectorLayer({
source: new VectorSource(),
style: {
'fill-color': 'rgba(255, 255, 255, 0.2)',
'stroke-color': '#ffcc33',
'stroke-width': 2,
'circle-radius': 7,
'circle-fill-color': '#ffcc33',
},
})
const defaultZoomStyleObj = {
nomal:{
fillColor:'#FFFFFF00',
strokeColor:'yellow'
},
notice:{
fillColor:'rgba(0, 255, 255, 0.5)',
strokeColor:'#00ffff'
},
waiwei:{
fillColor:'#FFFFFF00',
strokeColor:'red'
}
};
const highLightStyle = new Style({
fill: new Fill({
color: 'rgba(144, 238, 144, 0.5)'
}),
stroke: new Stroke({
color: '#90EE90',
width: 4
})
});
//定义一些常量
var x_PI = (3.14159265358979324 * 3000.0) / 180.0
var PI = 3.1415926535897932384626
var a = 6378245.0
var ee = 0.00669342162296594323
export default {
name: 'OpenLayerMap',
components: {
msgModel,
},
props: {
//按钮组
showGroupBtn: {
type: Object,
default: function () {
return {
zoomBtn: false,
positionBtn:false
}
}
},
dynamicHeight: {
type: String,
default: '95vh',
},
//是否展示设备
showDevice: {
type: Boolean,
default: false,
},
//点击分区高亮
highLight: {
type: Boolean,
default:false
}
},
data() {
return {
centerPoint:window._CONFIG['centerPoint'],//中心点
GaodeMapLayerUrl:window._CONFIG['GaodeMapLayerUrl'],
GaodeMapLayerUrl2:window._CONFIG['GaodeMapLayerUrl2'],
selectedFeatures:[],//高亮分区
deviceData:[],//全部设备坐标点
zoomCenterData:[],//分区中心点
zoomData:[],//全部分区坐标
curDevicePoint:[],//新增设备坐标
curZoomCenter:[],//某个分区中心点位置
curPolygon:[],//当前绘画多边形
map: null,
Polygon: new Draw({
source: vector.getSource(),
type: 'Polygon',
}),
Point: new Draw({
source: vector.getSource(),
type: 'Point',
}),
corrdinatesCollection: [],
data: '',
canShowTip: false,
editIcon: false,
layers: [],
loadTitleLayer: null,
notLoadTitleLayer: null,
heatLayer: null,
feature: null,
popup: null,
mapId: '',
centerVector: new VectorLayer({
source: new VectorSource(),
style: {
'fill-color': 'rgba(255, 255, 255, 0.2)',
'stroke-color': '#ffcc33',
'stroke-width': 2,
'circle-radius': 7,
'circle-fill-color': '#ffcc33',
},
}),
deviceVector: new VectorLayer({
source: new VectorSource(),
style: {
'fill-color': 'rgba(255, 255, 255, 0.2)',
'stroke-color': '#ffcc33',
'stroke-width': 2,
'circle-radius': 7,
'circle-fill-color': '#ffcc33',
},
})
}
},
mounted() {
this.mapId = 'mapId_' + (Math.floor(Math.random()*100000)+1)
this.init();
},
methods: {
async init() {
vector.getSource().clear();
this.centerVector.getSource().clear();
this.deviceVector.getSource().clear();
this.centerPoint = await this.getCenterPoint();
this.initMap();
await this.loadCustomEvent();
},
async getCenterPoint() {
var centerPoint = [];
await getAction('/tsairport/tsAirport/list').then(res=>{
if(res.success) {
if(!res.result) {
this.$message.warning("请设置机场信息");
return;
}
var airport = res.result.records[0];
var lng = airport.lngradis;
var lat = airport.latradis;
centerPoint = [lng,lat];
} else {
this.$message.error(res.message);
}
})
return centerPoint;
},
//初始化地图
initMap() {
const _self = this
var view = new View({
center: _self.centerPoint,
projection: 'EPSG:4326',
zoom: 14,
minZoom: 14,
maxZoom: 17,
})
var gaodeMapLayer = new TileLayer({
source: new XYZ({
url: _self.GaodeMapLayerUrl,
}),
})
var gaodeMapLayer2 = new TileLayer({
source: new XYZ({
url: _self.GaodeMapLayerUrl2,
}),
})
this.layers = [gaodeMapLayer,gaodeMapLayer2,vector,this.centerVector,this.deviceVector]
this.map = new Map({
layers: _self.layers,
view: view,
target: _self.mapId,
})
gaodeMapLayer2.setVisible(false)
// gaodeMapLayer.setOpacity(0.1)
// gaodeMapLayer2.setTransparent(false)
// gaodeMapLayer2.setBrightness(0.5)
// 添加'postrender'事件监听
this.map.once('postrender', function() {
// 在地图渲染完成后调用回调函数
_self.$emit('afterRender');
});
this.Polygon.on('drawend', function (e) {
const geometry = e.feature.getGeometry()
const corrdinates = geometry.getCoordinates()
// 清除画笔
// _self.map.removeInteraction(_self.Polygon)
_self.corrdinatesCollection.push(corrdinates)
})
const popup = new Overlay({
element: _self.$refs.msgForm.$el, // 图层绑定我们上边的弹窗
autoPan: true,
autoPanAnimation: {
duration: 250,
},
})
popup.setPosition(undefined)
this.map.addOverlay(popup)
this.popup = popup
this.map.on('click', function (ev) {
let curFeature = '';
if (_self.canShowTip) {
let mouse = ev.coordinate // 鼠标点击的坐标位置
curFeature = _self.map.forEachFeatureAtPixel(ev.pixel,function(feature, layer) {
// 检查要素的几何类型是否为点
if (feature.getGeometry().getType() === 'Point') {
return feature;
}
});
//将选中curFeature传到父组件
if(curFeature && curFeature.get('id')) {
_self.$emit('getFeature',curFeature);
}
if(curFeature && curFeature.get('deviceId')) {
_self.$emit('getDeviceFeature',curFeature);
}
this.feature = curFeature;
if (curFeature && !curFeature.get('id')) {
_self.data = '';
_self.data = _self.data ? _self.data : _self.getPopData(curFeature) // 获取坐标点的数据
if(_self.data) {
popup.setPosition(mouse) // 设置弹窗的位置
} else {
popup.setPosition(undefined)
}
} else {
popup.setPosition(undefined) // 如果没有点击坐标点,就隐藏弹窗
}
}
if (_self.editIcon) {
_self.$emit('emitEditIcon',ev);
}
})
this.map.on('moveend', function (e) {
var newZoom = _self.map.getView().getZoom()
_self.deviceVector.setVisible(false)
_self.centerVector.setVisible(false)
vector.setVisible(true)
if (newZoom >= 15) {
_self.centerVector.setVisible(true)
}
if(_self.showDevice) {
if(newZoom >= 14) {
_self.deviceVector.setVisible(true)
}
}
})
},
/**
* 自定义事件
*/
async loadCustomEvent() {
//加载分区中心点名称
this.showZoomCenter();
//加载分区信息
this.showZoom();
//加载设备
if(this.showDevice) {
this.deviceData = await this.getDeviceData();
this.drawDevicePoint(this.deviceData);
this.canShowTip = true;
}
//点击高亮事件
if(this.highLight) {
this.initHighLightEvent()
}
},
async showZoom() {
var data = await this.getZoomData();
for(var key in data) {
if(key == 'nomal') {
this.drawData(data[key],defaultZoomStyleObj[key].fillColor,defaultZoomStyleObj[key].strokeColor,key);
} else if(key == 'notice') {
this.drawData(data[key],defaultZoomStyleObj[key].fillColor,defaultZoomStyleObj[key].strokeColor,key);
} else if(key == 'waiwei') {
this.drawData(data[key],defaultZoomStyleObj[key].fillColor,defaultZoomStyleObj[key].strokeColor,key);
}
}
},
/**
* 获取区域中心点坐标,文本值
*/
showZoomCenter() {
getAction('/tstianjinzoom/tsTianjinZoom/getZoomCenter').then(res=>{
if(res.success) {
this.zoomCenterData = res.result;
this.drawText(res.result);
} else {
this.$message.error(res.message)
}
})
},
/**
* 获取所有区域
*/
async getZoomData() {
var data = ''
await getAction('/tstianjinzoom/tsTianjinZoom/getZoomData').then(res=>{
if(res.success) {
data = res.result;
this.zoomData = data;
} else {
this.$message.error(res.message)
}
})
return data;
},
/**
* 获取设备坐标信息
*/
async getDeviceData() {
var data = ''
await getAction('/device/tsTianjinDevice/getDeviceData').then(res=>{
if(res.success) {
data = res.result;
data.forEach(item=>{
item.icon = window._CONFIG['domianURL'] + item.icon
})
} else {
this.$message.error(res.message)
}
})
return data;
},
/**
* 弹窗
*/
showFeaturePop(data,feature) {
if(data) {
this.data = data
this.popup.setPosition(feature.getGeometry().getCoordinates())
} else {
this.popup.setPosition(undefined)
}
},
/**
* 点击多边形高亮事件
*/
initHighLightEvent() {
const that = this;
that.map.on('singleclick', function (e) {
that.map.forEachFeatureAtPixel(e.pixel, function (f) {
var geometryType = f.getGeometry().getType();
if(geometryType === 'Point') {
return
}
const selIndex = that.selectedFeatures.indexOf(f);
if (selIndex < 0) {
that.selectedFeatures.push(f);
f.setStyle(highLightStyle);
} else {
that.selectedFeatures.splice(selIndex, 1);
var zoomType = f.get('type');
var obj = defaultZoomStyleObj[zoomType];
if(obj) {
var lineStyle = new Style({
fill: new Fill({
color: obj.fillColor,
}),
stroke: new Stroke({
color: obj.strokeColor,
width: '1',
})
})
f.setStyle(lineStyle);
} else {
f.setStyle(undefined);
}
}
});
});
},
/**
* 拼接弹窗内容
*/
getPopData(feature) {
if(this.showDevice) {
const coordinates = feature.getGeometry().getCoordinates();
var obj = {};
for(var key in this.deviceData) {
var item = this.deviceData[key];
if(item.x==coordinates[0] || item.y==coordinates[1]) {
obj = item;
break;
}
}
if(obj) {
let content = '';
if(!obj.hasOwnProperty('title')) {
return null;
}
if(obj.controlLing) {
content = `<div>
<p>设备名称:${obj.title}</p>
<p>编号:${obj.bids}</p>
<p>设备位置:${obj.zoomname}</p>
<p>管控范围:${obj.radius}m</p>
<p>设备状态:${obj.state}</p>
<p>投运时间:${obj.bstime}</p>
<p>环境温度:0℃</p>
<p>电瓶电压:0V</p>
<p>煤气罐压力值:0MPa</p>
<p>下次工作倒计时:0s</p>
</div>`
} else {
content = `<div>
<p>设备名称:${obj.title}</p>
<p>编号:${obj.bids}</p>
<p>设备位置:${obj.zoomname}</p>
<p>管控范围:${obj.radius}m</p>
<p>设备状态:${obj.state}</p>
<p>投运时间:${obj.bstime}</p>
</div>`;
}
return content;
}
}
},
drawPositionLine(mouse) {
var coordinate = mouse;
var pointStyle = new Style({
image: new Circle({
radius: 10, // 设置点的半径
fill: new Fill({
color: 'rgba(255, 0, 0, 0.5)', // 设置点的填充颜色
}),
stroke: new Stroke({
color: 'red', // 设置点的边框颜色
width: 1, // 设置点的边框宽度
}),
}),
});
var pointFeature = new Feature({
geometry: new Point(coordinate)
});
pointFeature.setStyle(pointStyle)
this.getLayerByName('pointPosition').getSource().addFeature(pointFeature); // 添加点要素到图层
this.corrdinatesCollection.push(coordinate); // 将坐标添加到存储点坐标的数组
if (this.corrdinatesCollection.length >= 2) {
var lineFeature = new Feature({
geometry: new LineString(this.corrdinatesCollection)
});
// 设置样式
var lineStyle = new Style({
stroke: new Stroke({
color: 'red',
width: 2
})
});
lineFeature.setStyle(lineStyle);
this.getLayerByName('pointPosition').getSource().addFeature(lineFeature); // 添加连线要素到图层
}
},
beginDrawZoom() {
this.corrdinatesCollection = [];
this.removeLayerByName('addZoom');
this.createVectorLayer('addZoom');
this.curPolygon = new Draw({
source: this.getLayerByName('addZoom').getSource(),
type: 'Polygon',
});
var feature = new Feature({
type: 'Polygon',
geometry: this.curPolygon,
})
const that = this;
this.curPolygon.on('drawend', function (e) {
const geometry = e.feature.getGeometry()
const corrdinates = geometry.getCoordinates()
that.corrdinatesCollection= corrdinates
that.map.removeInteraction(that.curPolygon)
})
this.map.addInteraction(this.curPolygon);
},
endDrawZoom() {
this.map.removeInteraction(this.curPolygon)
},
clearCurZoom() {
if(!this.curPolygon) {
return;
}
var feature = new Feature({
type: 'Polygon',
geometry: this.curPolygon,
})
this.corrdinatesCollection = []
this.curZoomCenter = []
this.getLayerByName('addZoom').getSource().clear()
},
clearLayerByName(name) {
this.corrdinatesCollection = []
this.data = ''
this.$refs.msgForm.closeClick();
this.getLayerByName(name).getSource().clear()
},
beginDrawCenterIcon() {
this.editIcon = true;
},
endDrawCenterIcon() {
this.editIcon = false;
},
//手动缩放
setScale(type) {
let view = this.map.getView()
let zoom = view.getZoom()
let scale = type === 'max' ? zoom + 1 : zoom - 1
view.setZoom(scale)
},
beginDraw() {
this.map.addInteraction(this.Polygon)
this.canShowTip = false
},
endDraw() {
this.map.removeInteraction(this.Polygon)
this.canShowTip = true
},
beginDrawCustomIcon() {
this.editIcon = true
this.canShowTip = false
},
endDrawCustomIcon() {
this.editIcon = false
this.canShowTip = true
},
clearSelectDraw() {
if (this.feature != null) {
vector.getSource().removeFeature(this.feature)
}
this.feature = null
this.popup.setPosition(undefined)
},
clearAllDraw() {
vector.getSource().clear()
},
drawData(corrdinatesCollection,fillColor,strokeColor,key) {
var arr = []
corrdinatesCollection.forEach((ele) => {
arr.push(this.drawSingle(ele,fillColor,strokeColor,'',key))
})
vector.getSource().addFeatures(arr)
},
/**
* 自定义画区域
*/
drawAssignLayerZoom(layerName,featureProp,data,fillColor,strokeColor,strokeWidth) {
var arr = []
data.forEach((ele) => {
var lineFeature = this.drawSingle(ele,fillColor,strokeColor,strokeWidth);
lineFeature.set('prop',featureProp);
arr.push(lineFeature);
});
this.getLayerByName(layerName).getSource().addFeatures(arr);
},
drawSingle(data,fillColor,strokeColor,strokeWidth,key) {
var fillColor = fillColor ? fillColor : 'rgba(1, 210, 241, 0.2)';
var strokeColor = strokeColor ? strokeColor : 'rgba(255, 0, 0)';
var strokeWidth = strokeWidth ? strokeWidth : 1;
//下边来添加一线feature
var feature = new Feature({
type: 'Polygon',
geometry: new Polygon(
data // 线的坐标
),
})
let lineStyle = {}
if(fillColor) {
lineStyle = new Style({
fill: new Fill({
color: fillColor,
}),
stroke: new Stroke({
color: strokeColor,
width: strokeWidth,
}),
})
} else {
lineStyle = new Style({
stroke: new Stroke({
color: strokeColor,
width: strokeWidth,
}),
})
}
// 添加线的样式
if(key) {
feature.set('type',key);
}
feature.setStyle(lineStyle);
return feature
},
drawDevicePoint(wrnameData) {
if(!wrnameData) {
return
}
wrnameData.forEach(item=>{
if(item.old == 1) {
var arr = this.wgs84togcj02(item.lng,item.lat)
item.x = arr[0];
item.y = arr[1];
} else {
item.x = item.lng;
item.y = item.lat;
}
})
wrnameData.forEach((item, index) => {
var feature = new Feature({
geometry: new Point([Number(item.x), Number(item.y)]),
})
let style = new Style({
image: new Icon({
scale: 0.1,
src: item.icon,
anchor: [0.48, 0.52],
}),
})
var styles= [style]
if(item.radius) {
const circleStyle = new Style({
image: new Circle({
radius: item.radius,
stroke: new Stroke({
color: '#E96058',
width: 1,
}),
fill: new Fill({
color: 'rgba(198, 54, 48, 0.3)',
})
}),
});
styles.unshift(circleStyle)
}
feature.set('deviceId',item.id);
feature.setStyle(styles)
this.deviceVector.getSource().addFeature(feature)
})
},
/**
* 在特定图层画点
*/
drawAssignLayerPoint(layerName,wrnameData,icon,scale) {
var icon = icon ? icon : houseIcon;
wrnameData.forEach((item, index) => {
var feature = new Feature({
geometry: new Point([Number(item.x), Number(item.y)]),
})
let style = new Style({
image: new Icon({
scale: scale ? scale:0.15,
src: icon,
anchor: [0.48, 0.52],
}),
})
feature.setStyle(style)
if(item.id) {
feature.set("id",item.id);
}
this.getLayerByName(layerName).getSource().addFeature(feature)
})
},
/**
* layerName
* data [{survey_id:63,lat:'',lng:'',old:1}]
*/
drawAssignLayerSurveyMark(layerName,data) {
const that = this;
data.forEach(item=>{
var result = [];
var obj = {};
if(item.old == 1) {
var newArr = that.wgs84togcj02(Number(item.lng),Number(item.lat));
obj.x = newArr[0];
obj.y = newArr[1];
} else {
obj.x = item.lng;
obj.y = item.lat;
}
obj.id = item.id;
result.push(obj);
that.drawAssignLayerPoint(layerName,result,that.findSurveyIcon(item.survey_id),1.2)
})
},
findSurveyIcon(surveyId) {
var icon = ''
if(surveyId == 63) {
icon = icon63;
} else if(surveyId == 64) {
icon = icon64;
} else if(surveyId == 65) {
icon = icon65;
} else if(surveyId == 66) {
icon = icon66;
} else if(surveyId == 67) {
icon = icon67;
} else if(surveyId == 68) {
icon = icon68;
} else {
icon = houseIcon;
}
return icon;
},
/**
* 创建带名称图层
*/
createVectorLayer(name) {
name = name ? name : Math.random()
const newLayer = new VectorLayer({
source: new VectorSource(),
style: {
'fill-color': 'rgba(255, 255, 255, 0.2)',
'stroke-color': '#ffcc33',
'stroke-width': 2,
'circle-radius': 7,
'circle-fill-color': '#ffcc33',
}
})
newLayer.set('name', name);
this.map.addLayer(newLayer);
return newLayer;
},
drawAssignLineArrow(layerName,data) {
if(data.length ==0) {
return ;
}
var coordinates = this.formateLineArrowData(data);
// 创建轨迹线的要素
// 创建轨迹线的样式
// 将轨迹线的要素和样式添加到矢量图层
var layer = this.getLayerByName(layerName);
const styleFunction = function (feature) {
const geometry = feature.getGeometry();
const styles = [
// linestring
new Style({
stroke: new Stroke({
color: 'red',
width: 2,
}),
}),
];
geometry.forEachSegment(function (start, end) {
const dx = end[0] - start[0];
const dy = end[1] - start[1];
const rotation = Math.atan2(dy, dx);
// arrows
styles.push(
new Style({
geometry: new Point(end),
image: new Icon({
src: LineArrowIcon,
scale: 0.08,
anchor: [0.48, 0.52],
rotateWithView: true,
rotation: -rotation,
}),
})
);
});
return styles;
};
var pointStyle = new Style({
image: new Circle({
radius: 10, // 设置点的半径
fill: new Fill({
color: 'rgba(255, 0, 0, 0.5)', // 设置点的填充颜色
}),
stroke: new Stroke({
color: 'red', // 设置点的边框颜色
width: 1, // 设置点的边框宽度
}),
}),
});
var lineFeatures = [];
var pointFeatures = [];
coordinates.forEach(item=>{
if(item.length != 1) {
var lineStringFeature = new Feature({
geometry: new LineString(item),
});
lineStringFeature.setStyle(styleFunction);
lineFeatures.push(lineStringFeature);
} else {
var pointFeature = new Feature({
geometry: new Point([Number(item[0][0]), Number(item[0][1])])
});
pointFeature.setStyle(pointStyle)
pointFeatures.push(pointFeature);
}
});
layer.getSource().addFeatures(lineFeatures);
layer.getSource().addFeatures(pointFeatures);
},
/**
* 指定图层画热力图
* heatData [{lng:117,lat:39,old:1}]
*/
drawAssignHeat(layerName,data) {
if(data.length ==0) {
return ;
}
var heatData = this.formateHeatData(data)
// 新生成图层源,用于存放热力图图层
let source = this.getLayerByName(layerName).getSource()
heatData.forEach((item) => {
// 遍历热力图数据,生成热力图feature
const feature = new Feature({
geometry: new Point([Number(item.lng), Number(item.lat)]),
// weight: item.weight,
})
source.addFeature(feature)
})
this.heatLayer = new HeatmapLayer({
//新生成热力图图层,存放热力图feature
// 矢量数据源
source,
blur: 15, // 模糊尺寸
radius: 25, // 热点半径
// weight(feature) {
// const weight = feature.get('weight') //获取feature的weight参数值,此处weight不可变更为其他参数,否则失效(暂时不明原因);
// const magnitude = weight / 1
// return magnitude
// },
})
this.map.addLayer(this.heatLayer) // 将热力图添加在地图上
},
/**
* 获取指定图层
*/
getLayerByName(layerName) {
let targetLayer = null;
var layers = this.map.getLayers();
layers.forEach((layer) => {
if (layer.get('name') === layerName) {
targetLayer = layer;
}
});
if(!targetLayer) {
return this.createVectorLayer(layerName);
}
return targetLayer;
},
/**
* 删除指定图层
*/
removeLayerByName(layerName) {
const layers = this.map.getLayers().getArray();
const layerToRemove = layers.find(layer => layer.get('name') === layerName);
if (layerToRemove) {
this.map.removeLayer(layerToRemove);
}
},
/**
* 移除图层点坐标信息
*/
removePoint(layerName) {
// 获取所有要素
var layer = this.getLayerByName(layerName);
if(!layer) {
return;
}
const features = layer.getSource().getFeatures();
// 遍历要素并删除点要素
for (let i = features.length - 1; i >= 0; i--) {
const feature = features[i];
if (feature.getGeometry() instanceof Point) {
layer.getSource().removeFeature(feature);
}
}
},
/**
* 判断点是否在多边形内
*/
pointInPolygon(lon, lat, arr) {
const coordinate = [lon, lat];
const polygonFeature = new Feature(arr instanceof Polygon ? arr: new Polygon(arr));
const polygon = polygonFeature.getGeometry();
return polygon.intersectsCoordinate(coordinate);
},
/**
* 计算features面积
*/
calcSelectFeaturesArea(features) {
var sum = 0;
features.forEach(feature=>{
var geometry = feature.getGeometry();
var lnglats = []
geometry.getCoordinates().forEach(square=> {
square.forEach(arr=>{
var item = {lng:arr[0],lat:arr[1]};
lnglats.push(item);
})
var area = this.calculatePolygonArea(lnglats);
sum += area;
});
})
return sum;
},
/**
* 计算面积
* latLngs : [{lng:0,lat:0}]
*/
calculatePolygonArea(latLngs) {
var pointsCount = latLngs.length,
area = 0.0,
d2r = Math.PI / 180,
p1, p2;
if (pointsCount > 2) {
for (var i = 0; i < pointsCount; i++) {
p1 = latLngs[i];
p2 = latLngs[(i + 1) % pointsCount];
area += ((p2.lng - p1.lng) * d2r) *
(2 + Math.sin(p1.lat * d2r) + Math.sin(p2.lat * d2r));
}
area = area * 6378137.0 * 6378137.0 / 2.0;
}
return Math.abs(area);
},
notLoadTitle() {
this.layers[2].setVisible(false)
},
loadTitle() {
this.layers[2].setVisible(true)
},
showFlashPoint() {
var coordinates = [
{
x: '117.34937568735268',
y: '39.13585085286323',
},
{
x: '117.35295925824774',
y: '39.136053936072976',
},
]
this.addDynamicPoints(coordinates)
},
addDynamicPoints(coordinates) {
// 设置图层
let pointLayer = new VectorLayer({
source: new VectorSource(),
})
// 添加图层
this.map.addLayer(pointLayer)
// 循环添加feature
let pointFeature = []
for (let i = 0; i < coordinates.length; i++) {
// 创建feature,一个feature就是一个点坐标信息
const feature = new Feature({
//geometry: new Point(fromLonLat([coordinates[i].x, coordinates[i].y])),
geometry: new Point([Number(coordinates[i].x), Number(coordinates[i].y)]),
})
pointFeature.push(feature)
}
//把要素集合添加到图层
pointLayer.getSource().addFeatures(pointFeature)
// 关键的地方在此:监听postrender事件,在里面重新设置circle的样式
let radius = 0
pointLayer.on('postrender', (evt) => {
if (radius >= 20) radius = 0
var opacity = (20 - radius) * (1 / 20) //不透明度
var pointStyle = new Style({
image: new Circle({
radius: radius,
stroke: new Stroke({
color: 'rgba(255,0,0' + opacity + ')',
width: 3 - radius / 10, //设置宽度
}),
}),
})
// 获取矢量要素上下文
let vectorContext = getVectorContext(evt)
vectorContext.setStyle(pointStyle)
pointFeature.forEach((feature) => {
vectorContext.drawGeometry(feature.getGeometry())
})
radius = radius + 0.3 //调整闪烁速度
//请求地图渲染(在下一个动画帧处)
this.map.render()
})
},
heatMap() {
var coordinates = [
{
x: '117.34937568735268',
y: '39.13585085286323',
weight: 1319,
},
{
x: '117.35295925824774',
y: '39.136053936072976',
weight: 519,
},
]
this.addHeatMap(coordinates)
},
addHeatMap(heatData) {
let source = new VectorSource() // 新生成图层源,用于存放热力图图层
heatData.forEach((item) => {
// 遍历热力图数据,生成热力图feature
const feature = new Feature({
geometry: new Point([Number(item.x), Number(item.y)]),
weight: item.weight,
})
source.addFeature(feature)
})
this.heatLayer = new HeatmapLayer({
//新生成热力图图层,存放热力图feature
// 矢量数据源
source,
blur: 10, // 模糊尺寸
radius: 10, // 热点半径
weight(feature) {
const weight = feature.get('weight') //获取feature的weight参数值,此处weight不可变更为其他参数,否则失效(暂时不明原因);
const magnitude = weight / 1
return magnitude
},
})
this.map.addLayer(this.heatLayer) // 将热力图添加在地图上
},
loadTj() {
this.map.getView().setCenter([117.36, 39.13])
this.map.getView().setZoom(14)
},
loadHz() {
this.map.getView().setCenter([120.43, 30.23])
this.map.getView().setZoom(14)
},
/**
* 区域中心点
*/
drawText(coordinates) {
const that = this
coordinates.forEach((item, index) => {
var point = new Point([Number(item.x), Number(item.y)])
var feature = new Feature({
geometry: point,
})
const labelStyle = new Style({
text: new Text({
font: '13px Calibri,sans-serif',
fill: new Fill({
color: '#000',
}),
stroke: new Stroke({
color: '#fff',
width: 2,
}),
text: item.text,
}),
})
feature.setStyle(labelStyle)
this.centerVector.getSource().addFeature(feature)
})
},
/**
* 坐标转化
* [{lng:117,lat:39,old:1}]
*/
formateHeatData(data) {
var result = [];
for(var key in data) {
var flag = data[key].old;
if(flag == 1) {
var arr = this.wgs84togcj02(data[key].lng,data[key].lat);
result.push({lng:arr[0],lat:arr[1]});
} else {
result.push(data[key]);
}
}
return result;
},
/**
* 轨迹数据 [{pid:"",val:[{lat:1,lng:1,old:1}]}]
*/
formateLineArrowData(data) {
var result = [];
data.forEach(item=>{
var line = [];
var arr = item.val;
var after = this.formateHeatData(arr);
after.forEach(af=>{
line.push([af.lng,af.lat]);
})
result.push(line);
})
return result;
},
// 创建箭头样式函数
createArrowStyle (feature, resolution, arrowLength) {
var styles = [];
if (feature.getGeometry().getType() === 'LineString') {
var coordinates = feature.getGeometry().getCoordinates();
var length = coordinates.length;
if (length > 1) {
var lastCoordinate = coordinates[length - 2];
var secondLastCoordinate = coordinates[length - 1];
var dx = secondLastCoordinate[0] - lastCoordinate[0];
var dy = secondLastCoordinate[1] - lastCoordinate[1];
var rotation = Math.atan2(dy, dx);
var arrowStyle = new Style({
geometry: new Point(secondLastCoordinate),
image: new Icon({
src: LineArrowIcon, // 替换为你自己的箭头图片路径
scale: arrowLength / arrowStyle.getImage().getIconSize()[1],
rotation: -rotation,
rotateWithView: true,
anchor: [0.75, 0.5],
}),
});
styles.push(arrowStyle);
}
}
return styles;
},
/**
* WGS84转GCj02
* @param lng
* @param lat
* @returns {*[]}
*/
wgs84togcj02(lng, lat) {
var dlat = this.transformlat(lng - 105.0, lat - 35.0)
var dlng = this.transformlng(lng - 105.0, lat - 35.0)
var radlat = (lat / 180.0) * PI
var magic = Math.sin(radlat)
magic = 1 - ee * magic * magic
var sqrtmagic = Math.sqrt(magic)
dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI)
dlng = (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI)
var mglat = lat + dlat
var mglng = lng + dlng
return [mglng, mglat]
},
/**
* GCJ02 转换为 WGS84
* @param lng
* @param lat
* @returns {*[]}
*/
gcj02towgs84(lng, lat) {
var dlat = this.transformlat(lng - 105.0, lat - 35.0)
var dlng = this.transformlng(lng - 105.0, lat - 35.0)
var radlat = (lat / 180.0) * PI
var magic = Math.sin(radlat)
magic = 1 - ee * magic * magic
var sqrtmagic = Math.sqrt(magic)
dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI)
dlng = (dlng * 180.0) / ((a / sqrtmagic) * Math.cos(radlat) * PI)
var mglat = lat + dlat
var mglng = lng + dlng
return [lng * 2 - mglng, lat * 2 - mglat]
},
transformlat(lng, lat) {
var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng))
ret += ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0) / 3.0
ret += ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) * 2.0) / 3.0
ret += ((160.0 * Math.sin((lat / 12.0) * PI) + 320 * Math.sin((lat * PI) / 30.0)) * 2.0) / 3.0
return ret
},
transformlng(lng, lat) {
var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng))
ret += ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0) / 3.0
ret += ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * 2.0) / 3.0
ret += ((150.0 * Math.sin((lng / 12.0) * PI) + 300.0 * Math.sin((lng / 30.0) * PI)) * 2.0) / 3.0
return ret
},
changeshow() {
this.popup.setPosition(undefined)
},
drawAreaAndText() {
var points1 = [
{
lat: '39.14445877075195',
lng: '117.33722448348999',
},
{
lat: '39.145681858062744',
lng: '117.33526110649109',
},
{
lat: '39.14422273635864',
lng: '117.33128070831299',
},
{
lat: '39.13998484611511',
lng: '117.3338770866394',
},
{
lat: '39.14174437522888',
lng: '117.3388123512268',
},
]
// var points1 = [
// {
// "lat": "39.124460220336914",
// "lng": "117.35288858413696"
// },
// {
// "lat": "39.122958183288574",
// "lng": "117.34947681427002"
// },
// {
// "lat": "39.11785125732422",
// "lng": "117.35222339630127"
// },
// {
// "lat": "39.11924600601196",
// "lng": "117.35572099685669"
// }
// ]
vector.getSource().clear()
var arr = []
var newArr = []
points1.forEach((item, index) => {
newArr.push(this.wgs84togcj02(Number(item.lng), Number(item.lat)))
})
arr.push(newArr)
this.corrdinatesCollection = []
this.corrdinatesCollection.push(arr)
// alert(this.corrdinatesCollection)
}
},
}
</script>
<style media="screen" lang="less" scoped="true">
.map {
width: 100%;
margin-bottom: 10px;
}
.demo01 {
button {
margin: 0px 5px;
}
}
</style>