Openlayers组件

引用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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值