欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Vue、OpenLayers结合天地图实现Gis

程序员文章站 2022-07-02 09:49:01
...

安装依赖:
npm install ol
主要代码:

<template>
  <div class="command-center">
    <div id="mapContainer" class="mapContainer"></div>
    <div class="customDiv">
      <div class="HeadDiv">
          <el-popover
                  placement="bottom"
                  width="500"
                  trigger="manual"
                  :offset="-50"
                  v-model="visibleSearch">
              <div style="max-height: 460px; overflow-y: auto;">
                  <div v-for="(item, index) in poiList" :key="index" @click="selectOne(item)" style="line-height: 24px;cursor: pointer">
                      <el-row>
                          <el-col :span="16">{{item.name}}</el-col>
                          <el-col :span="8">{{item.lng}} {{item.lat}}</el-col>
                      </el-row>
                  </div>
              </div>
              <el-input class="inputAddress" placeholder="请输入地点" v-model="address" slot="reference" clearable>
                  <el-button slot="append" icon="el-icon-search" @click="searchPlace(address)" >查询</el-button>
              </el-input>
          </el-popover>

<!--        <el-select-->
<!--                v-model="address"-->
<!--                :multiple="false"-->
<!--                :reserve-keyword="false"-->
<!--                filterable-->
<!--                remote-->
<!--                placeholder="请输入地点"-->
<!--                :remote-method="searchPlace"-->
<!--                @change="selectOne" clearable-->
<!--                :loading="loading">-->
<!--          <el-option-->
<!--                  v-for="(item, index) in poiList"-->
<!--                  :key="index"-->
<!--                  :label="item.name"-->
<!--                  :value="item">-->
<!--          </el-option>-->
<!--        </el-select>-->
<!--        <el-button type="primary" @click="searchPlace">查询</el-button>-->
      </div>
      <div class="mapType">
        <el-radio v-model="radioMap" label="1" border size="small" @change="radioMapChange">地图(道路)</el-radio>
        <el-radio v-model="radioMap" label="2" border size="small" @change="radioMapChange">地图(卫星)</el-radio>
      </div>
      <div class="optionDiv">
<!--        <el-row class="btn_gis">-->
<!--          <el-button size="small" type="primary" class="el-icon-map-location" @click="addMapClick"></el-button>-->
<!--        </el-row>-->
<!--        <el-row class="btn_gis">-->
<!--          <el-button size="small" type="primary" class="el-icon-coin" @click="getLayers"></el-button>-->
<!--        </el-row>-->
        <el-row class="btn_gis">
            <el-tooltip content="清空" placement="left">
                <el-button size="small" type="primary" class="el-icon-brush" @click="cleanMap"></el-button>
            </el-tooltip>
        </el-row>
<!--        <el-row class="btn_gis">-->
<!--          <el-button size="small" type="primary" class="el-icon-brush" @click="addPopup"></el-button>-->
<!--        </el-row>-->
      </div>
      <div class="InfoListDiv">
          <el-tooltip content="单位装备信息列表" placement="left">
              <el-button v-show="drawerShowBtn" style="position: absolute;top: 60px;right: -5px;" size="small" type="primary" class="el-icon-caret-left" @click="handleOpen"></el-button>
          </el-tooltip>
        <el-drawer
                title="单位装备信息列表"
                :visible.sync="drawer" :size="550" :append-to-body="false"
                direction="rtl" :modal="false" :wrapperClosable="false"
                :before-close="handleClose">
          <el-row>
            <el-row>
              事件类型
                <el-select v-model="currentScenarioType" placeholder="请选择">
                    <el-option
                            v-for="item in scenarioTypes"
                            :key="item.id"
                            :label="item.name"
                            :value="item.code">
                    </el-option>
                </el-select>
            </el-row>
            <el-row>
              <el-tabs v-model="activeOrgType" @tab-click="changeOrgByDistance">
                <el-tab-pane :label="'0~5KM-可增援单位' + orgList5KM.length +'个'" name="first"></el-tab-pane>
                <el-tab-pane :label="'5~10KM-可增援单位' + orgList10KM.length +'个'" name="second"></el-tab-pane>
                <el-tab-pane :label="'10~20KM-可增援单位' + orgList20KM.length +'个'" name="third"></el-tab-pane>
              </el-tabs>
            </el-row>
            <el-row>
              <el-table :data.sync="orgListTable" border stripe style="width: 100%">
              <el-table-column type="index" label="序号" width="50"></el-table-column>
              <el-table-column prop="name" label="单位名称"></el-table-column>
              <el-table-column prop="distance" label="距离" width="80"></el-table-column>
              <el-table-column prop="areaName" label="地址"></el-table-column>
              </el-table>
            </el-row>
          </el-row>
        </el-drawer>
      </div>
    </div>
  </div>
</template>

<script>
import * as Gis from '@/api/modules/gis/gis' // 接口
import $ from 'jquery'
// openLayer
import 'ol/ol.css'
import Map from 'ol/Map'
import View from 'ol/View'
import {Vector as VectorSource, XYZ} from 'ol/source'
import {createStringXY} from 'ol/coordinate'
import {defaults as defaultControls, ScaleLine, ZoomSlider, FullScreen, MousePosition} from 'ol/control'
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer'
import Feature from 'ol/Feature'
import {Point, LineString } from 'ol/geom'
import { Style, Icon, Stroke, Circle as CircleStyle, Fill} from 'ol/style'
import {unByKey} from 'ol/Observable'
import  {easeOut} from 'ol/easing'
import {getVectorContext} from 'ol/render'
import Overlay from 'ol/Overlay'

export default {
    components: {
    },
    data () {
        return {
            CommonUrl: window.gisCommonUrl,
            // 查询
            address: '',
            poiList: [],
            visibleSearch: false,
            loading: false,
            drawer: false,
            drawerShowBtn: false,
            currentAddress: null,
            scenarioTypes: null, // 事件类型
            currentScenarioType: [], // 事件类型
            orgList: [], // 增援单位
            orgList5KM: [],
            orgList10KM: [],
            orgList20KM: [],
            orgListTable: [],
            activeOrgTypeOld: 'first',
            activeOrgType: 'first',
            // gis 地图
            map: null,
            startIcon: require("@/assets/images/start.png"),	//起点图标
            endIcon: require("@/assets/images/end.png"),		//终点图标
            // openLayer
            view: null,
            TileLayerCommon: null, // 普通地图
            TileLayerSatellite: null, // 卫星地图
            TileLayer: null,
            radioMap: '1',
            vectorLayer: null,
            animateSourceLayer: null,
            animateVectorLayer: null,
            iconFeature: null,
            feature: null, // 水波纹
            routerColor: [[18, 109, 4, 0.7], [237, 212, 0, 0.7]], // 轨迹路线颜色
            speed: 8, // 轨迹速度
            animatingRouter: false,
            startTimeRouter: null,
            currentCoordinates: []
        }
    },
    mounted () {
        this.TileLayerCommon =  new TileLayer({
        source: new XYZ({
          name: "地图(道路)",
          url: window.gisCommonUrl, // 地图服务地址或在线地图
        }),
        visible: true
        })
        this.TileLayerSatellite =  new TileLayer({
        source: new XYZ({
          name: "地图(卫星)",
          url: window.gisSatelliteUrl  // 地图服务地址或在线地图
        }),
        visible: false
        })

        this.init()
        this.getScenarioType()

        // 每当触发添加要素的事件时,执行flash()水波纹动画 --- 使用第一种时放开
        // this.addfeatureKey = this.animateSourceLayer.on("addfeature", (e) => {
        //   // this.flash(e.feature)
        //   this.flashOverlay()
        // })
    },
    destroyed() {
        // 水波纹动画 --- 使用第一种时放开
        // unByKey(this.addfeatureKey)
        this.removeMapClick()
    },
    methods: {
        // 初始化地图
        init () {
            this.TileLayer = [this.TileLayerCommon, this.TileLayerSatellite]
            this.map = new Map({
              target: 'mapContainer',
              layers: this.TileLayer,
              view: new View({
                center: [117.276828, 31.77611],
                projection: 'EPSG:4326',
                zoom: 10,
                minZoom: 2,
                controls: defaultControls({ zoom: true }).extend([])
              })
            })

            // 水波纹动画图层
            this.animateSourceLayer = new VectorSource({
              wrapX: false
            })
            this.animateVectorLayer = new VectorLayer({
              name: "点位标注(水波纹动画)",
              source: this.animateSourceLayer
            })
            this.map.addLayer(this.animateVectorLayer)

            // 轨迹图层
            this.routerVectorLayer = new VectorLayer({
                id: '20210526',
                source: '',
                style: new Style({
                    stroke: new Stroke({
                        width: 6,
                        color: this.routerColor[0]
                    })
                })
            })
            this.map.addLayer(this.routerVectorLayer)

            // 添加点位图层
            // this.vectorLayer = new VectorLayer({
            //   name: "点位标注",
            //   source: new VectorSource({
            //     features: [],
            //   }),
            //   zIndex: 100,
            //   visible: true,
            // })
            // this.map.addLayer(this.vectorLayer)

            // 向地图添加 MousePosition
            let mousePositionControl = new MousePosition({
              //坐标格式
              coordinateFormat: createStringXY(6),
              //地图投影坐标系(若未设置则输出为默认投影坐标系下的坐标)
              projection: "EPSG:4326",
              //坐标信息显示样式类名,默认是'ol-mouse-position'custom-mouse-position
              className: "ol-mouse-position",
              //显示鼠标位置信息的目标容器
              target: document.getElementById("mouse-position"),
              //未定义坐标的标记
              undefinedHTML: "&nbsp;"
            })
            this.map.addControl(mousePositionControl)
            // 比例尺
            this.map.addControl(new ScaleLine())
            // 缩放条
            this.map.addControl(new ZoomSlider())
            // 全屏
            this.map.addControl(new FullScreen({
              tipLabel: "全屏"
            }))

            // let bern = fromLonLat([117.276828, 31.77611]);
            // this.flyTo(bern, function () {})
        },
        // 查询目标地
        searchPlace (address) {
            this.loading = true
            let params = {
              'name': address
            }
            Gis.getPoiList(params).then(({data}) => {
              this.poiList = data.data
              this.visibleSearch = true
              this.loading = false
            })
        },
        selectOne (item) {
            this.cleanMap()
            // 切换定位跳转方式动画
            this.flyTo([item.lng, item.lat], function () {})
            // 普通定位
            // this.map.getView().setCenter([item.lng, item.lat])
            // this.map.getView().setZoom(12)
            this.addRandomFeature(item, false)
            this.address = ''
            this.poiList = []
            this.visibleSearch = false

            this.activeOrgType = "first"
            this.activeOrgTypeOld = "first"
            this.currentAddress = JSON.parse(JSON.stringify(item))
            this.getOrgAll(item)
        },
        // 获取增援单位信息列表
        getOrgAll (point) {
            Gis.getOrgAll().then((res) => {
              this.orgList = res.data.data
              console.log(this.orgList)
              this.groupOrg(point)
              this.drawerShowBtn = false
              this.drawer = true
            })
        },
        // 增援单位根据距离分组
        groupOrg(point) {
            this.orgList5KM = []
            this.orgList10KM = []
            this.orgList20KM = []
            this.orgList.forEach((item) => {
              if (item.lat && item.lng) {
                let distance = this.distanceTo(item, point)
                item.distance = distance
                if (distance > 0 && distance <= 5) {
                  this.orgList5KM.push(item)
                  this.addRandomFeature(item, true)
                } else if (distance > 5 && distance <= 10) {
                  this.orgList10KM.push(item)
                } else if (distance > 10 && distance <= 20) {
                  this.orgList20KM.push(item)
                }
              }
            })
            this.orgListTable = this.orgList5KM
            this.addRouterLine()
        },
        // 计算距离 单位KM
        distanceTo (point1, point2) {
            let R = 6371; // km
            let dLon = (point1.lng - point2.lng) * Math.PI/180,
                    lat1 = point1.lat * Math.PI/180,
                    lat2 = point2.lat * Math.PI/180,
                    d = Math.acos(Math.sin(lat1)*Math.sin(lat2) + Math.cos(lat1)*Math.cos(lat2) * Math.cos(dLon)) * R
            return d.toFixed(2)
            // let distance = 0.0;
            // if ((point1.lng != null) && (point1.lat != null) && (point2 != null) && (point2.lng != null) && (point2.lat != null)) {
            //   let dx2 = Math.pow(point1.lng - point2.lng, 2)*1000
            //   let dy2 = Math.pow(point1.lat - point2.lat, 2)*1000
            //   distance = Math.sqrt(dx2 + dy2)
            // }
            // return distance
        },
        // 切换展示不同距离增援单位
        changeOrgByDistance (tab) {
            switch (tab.name) {
              case 'first':
                this.orgListTable = this.orgList5KM;
                this.map.getView()
                this.map.getView().setZoom(14)
                break;
              case 'second':
                this.orgListTable = this.orgList10KM
                this.map.getView().setZoom(13)
                break;
              case 'third':
                this.orgListTable = this.orgList20KM;
                this.map.getView().setZoom(12)
                break;
            }
            if(this.activeOrgTypeOld !== tab.name) {
                this.map.getView().setCenter([this.currentAddress.lng, this.currentAddress.lat])
                this.changeOrgByDistancePoint ()
                this.activeOrgTypeOld = tab.name
                this.addRouterLine()
            }
        },
        // 单位装备信息列表
        handleOpen () {
            this.drawerShowBtn = false
            this.drawer = true
        },
        handleClose() {
            this.drawer = false
            this.drawerShowBtn = true
            // this.$confirm('确认关闭?')
            //         .then( () => {
            //           this.drawer = false
            //         })
            //         .catch( () => {})
        },
        // 获取事件类型
        getScenarioType() {
            Gis.scenarioType().then((res) => {
                this.scenarioTypes = res.data.data
            })
        },
        // 切换定位跳转方式动画
        flyTo (location, done) {
            let duration = 2000
            let zoom = this.map.getView().getZoom()
            let parts = 2
            let called = false
            function callback(complete) {
              --parts;
              if (called) {
                return;
              }
              if (parts === 0 || !complete) {
                called = true;
                done(complete);
              }
            }
            this.map.getView().animate(
                    {
                      center: location,
                      duration: duration,
                    },
                    callback
            )
            this.map.getView().animate(
                    {
                      zoom: zoom - 1,
                      duration: duration / 2,
                    },
                    {
                      zoom: 14,
                      duration: duration / 2,
                    },
                    callback
            )
        },
        // 切换地图
        radioMapChange (val) {
            switch (val) {
              case '1':
                this.TileLayerCommon.setVisible(true)
                this.TileLayerSatellite.setVisible(false)
                this.routerVectorLayer.getStyle().getStroke().setColor(this.routerColor[0])
                break;
              case '2':
                this.TileLayerSatellite.setVisible(true)
                this.TileLayerCommon.setVisible(false)
                this.routerVectorLayer.getStyle().getStroke().setColor(this.routerColor[1])
                break;
            }
            this.addRouterLine()
        },
        // 图层
        getLayers() {
            let layers = this.map.getLayers()
            console.log(layers)
            // this.vectorLayer.setVisible(!this.vectorLayer.getVisible())
        },
        // 移除监听
        removeMapClick() {
            unByKey(this.mapClickKey)
            unByKey(this.animateKey)
        },
        // 地图点击事件 -- 添加点
        addMapClick () {
            this.mapClickKey = this.map.on('singleclick', (e) => {
              // 获取当前点位坐标
              let point = e.coordinate
              // 打点,水纹动画
              this.addRandomFeature(point[0], point[1], true)
              unByKey(this.mapClickKey)
            })
        },
        // 清空地图
        cleanMap () {
            this.animateVectorLayer.getSource().clear()
            this.map.getOverlays().clear()
            this.removeMapClick()
            this.currentAddress = ''
            this.drawer = false
            this.drawerShowBtn = false
            this.routerVectorLayer.setSource(null)
        },
        // 切换展示不同距离增援单位 --- 显示增援地点信息
        changeOrgByDistancePoint() {
            let overlays = this.map.getOverlays().getArray()
            for(let i = 0; i < overlays.length; i++) {
                if(overlays[i].getId() == 'organ' || overlays[i].getId() == 'organPopup') {
                    this.map.removeOverlay(overlays[i])
                    i--
                }
            }
            this.orgListTable.forEach((item) => {
                this.addRandomFeature(item, true)
            })
        },
        // 打点
        addRandomFeature (item, flag) {
            // 点图标
            if(!flag) {
              this.iconFeature = new Feature({
                geometry: new Point([item.lng, item.lat]),
                name: '地点',
                // population: 4000,
                // rainfall: 500,
              })
              let iconStyle = new Style({
                image: new Icon({
                  anchor: [0.5, 1],
                  src: this.startIcon, // 图标
                }),
              })
              this.iconFeature.setStyle(iconStyle)
              this.animateSourceLayer.addFeatures([this.iconFeature])
                // 水波纹动画
                this.flashOverlay(item.lng, item.lat, 'flagOrgan')
            }

            if(flag) {
                // 水波纹动画
                this.flashOverlay(item.lng, item.lat, 'organ')
                // 弹窗
                this.addPopup(item)
            }

            // // 增加可移动点位元素
            // let iconTranslate = new PointerTranslate({
            //   features: new Collection([feature, this.iconFeature])
            // })
            // this.map.addInteraction(iconTranslate)
            // // 为元素增加点击事件
            // unByKey(this.featureClickKey)
            // this.featureClickKey = iconTranslate.on("translateend", () => {
            //   let clickPoint = this.iconFeature.getGeometry().flatCoordinates
            //   // 将点位转成EPSG:4326坐标系
            //   clickPoint = transform(clickPoint, 'EPSG:3857', 'EPSG:4326')
            //   alert(clickPoint)
            // })
        },
        // 水纹动画--第一种
        flash (feature) {
            let duration = 3000
            let start = new Date().getTime()
            //进行地图水波渲染
            let that = this
            that.animateKey = this.TileLayer.on('postrender', function animate(event) {
              let vectorContext = getVectorContext(event)
              let frameState = event.frameState
              let flashGeom = feature.getGeometry().clone()
              let elapsed = frameState.time - start
              let elapsedRatio = elapsed / duration
              let radius = easeOut(elapsedRatio) * 25 + 15
              let opacityFill = easeOut(1 - elapsedRatio) - 0.3
              let opacity = easeOut(1 - elapsedRatio)

              let style = new Style({
                image: new CircleStyle({
                  radius: radius,
                  fill: new Fill({
                    color: 'rgba(255, 0, 0, ' + opacityFill + ')',
                    width: 0.5 + opacity,
                  }),
                  stroke: new Stroke({
                    color: 'rgba(255, 0, 0, ' + opacity + ')',
                    width: 0.5 + opacity,
                  }),
                })
              })
              vectorContext.setStyle(style)
              vectorContext.drawGeometry(flashGeom)
              // 当持续时间超过了duration后,取消绑定的postrender事件
              if (elapsed > duration) {
                unByKey(that.animateKey)
                return;
              }
              that.map.render()
            })
        },
        // 水纹动画--第二种
        flashOverlay (x, y, id) {
            let element = document.createElement("div")
            element.className =(id == "flagOrgan" ? "point_animation_flag" : "point_animation_com")
            let p = document.createElement("p")
            let span = document.createElement("span")
            element.appendChild(p)
            element.appendChild(span)
            let point_overlay = new Overlay({
                id: id,
                element: element,
                positioning: 'center-center',
            })
            point_overlay.setPosition([x, y])
            this.map.addOverlay(point_overlay)
        },
        // 弹窗
        addPopup (item) {
            let element = document.createElement("div")
            element.className = "popup"
            element.innerHTML = "<div class='popupInfoMap'>" +
                    "<div class='el-header'><div class='name'>"+ item.name +"</div><div class='optionBtn' id='detail'>装备详情</div></div>" +
                    "<div class='el-main'>" +
                    "<div class='el-row numDiv'><div class='el-col-6'>20</div><div class='el-col-6'>241</div>" +
                    "<div class='el-col-6'>90</div><div class='el-col-6'>"+ item.distance +"KM</div></div>" +
                    "<div class='el-row typeDiv'><div class='el-col-6'>装备分类</div><div class='el-col-6'>装备总数</div>" +
                    "<div class='el-col-6'>人员</div><div class='el-col-6'>距离</div></div>" +
                    "<div class='el-row'><button class='btn' id='taskSend'>下发任务</button></div>" +
                    // "<div class='el-row'>经纬度:"+ item.lng +","+ item.lat + "</div>" +
                "</div></div>"
            let popup_overlay = new Overlay({
                id: 'organPopup',
                element: element,
                positioning: 'center-center',
            })
            popup_overlay.setPosition([item.lng, item.lat])
            this.map.addOverlay(popup_overlay)
            $('.popup').parent().css('z-index', 9999)

            // 添加点击事件
            $("#taskSend").on("click",()=>{
                this.taskSend(item);
            })
            $("#detail").on("click",()=>{
                this.detail(popup_overlay, item);
            })
        },
        // 发布任务
        taskSend(item) {
            let params = {
                'startPoint': item.lat + "," + item.lng,
                'endPoint': this.currentAddress.lat + "," + this.currentAddress.lng
            }
            Gis.getRouterGis(params).then((res) => {
                this.currentCoordinates = res.data.data.paths[0].points.coordinates
                this.geoMarker = new Feature({
                    type: 'geoMarker',
                    geometry: new Point([item.lng, item.lat]),
                });
                this.animatingRouter = false
                this.startAnimation()
            })

        },
        // 装备详情
        detail(overlay, item) {
            let elementNode = overlay.element.childNodes[0]
            if (elementNode.children.length > 1) {
                elementNode.removeChild(elementNode.children[1])
            }else {
                let params = {
                    'orgId': item.id
                }
                Gis.getEquipStrengthList(params).then((res) => {
                    let equipList = res.data.data
                    let addHtml = document.createElement('div')
                    addHtml.innerHTML = ''
                    let str = "<div id='detailEquip'><table><thead><tr><td>序号</td><td>单位名称</td><td>装备数量</td></tr></thead>"
                    for(let i = 0; i < equipList.length; i++){
                        str += "<tr><td>"+ (i+1) +"</td><td>"+ equipList[i].equipName +"</td><td>" + equipList[i].total + "</td></tr>"
                    }
                    addHtml.innerHTML = (str + "</table></div>")
                    elementNode.appendChild(addHtml)
                })
            }
        },
        // 轨迹路线===============================start
        // 添加静态路线
        addRouterLine() {
            let routeFeatureArr = []
            for(let i = 0; i < this.orgListTable.length; i++) {
                let params = {
                    'startPoint': this.orgListTable[i].lat + "," + this.orgListTable[i].lng,
                    'endPoint': this.currentAddress.lat + "," + this.currentAddress.lng
                }
                Gis.getRouterGis(params).then((res) => {
                    let routeFeature = new Feature({
                        type: "route",
                        geometry: new LineString(res.data.data.paths[0].points.coordinates)
                    })
                    routeFeatureArr.push(routeFeature)
                    if(i === this.orgListTable.length - 1) {
                        this.routerVectorLayer.setSource(new VectorSource({
                            features: routeFeatureArr
                        }))
                    }
                })
            }
        },
        // 轨迹跟踪动效
        moveFeature(event) {
            let vectorContext = getVectorContext(event);
            let frameState = event.frameState;
            if (this.animatingRouter) {
                let elapsedTime = frameState.time - this.startTimeRouter;
                let distance = Math.round(this.speed * elapsedTime/1000)
                if (distance >= this.currentCoordinates.length) {
                    this.geoMarker.getGeometry().setCoordinates(this.currentCoordinates[0]);
                    this.routerVectorLayer.un("postrender", this.moveFeature);
                    return;
                }
                let currentPoint = new Point(this.currentCoordinates[distance])
                let feature = new Feature(currentPoint);
                vectorContext.drawFeature(feature, new Style({
                    image: new CircleStyle({
                        radius: 7,
                        fill: new Fill({color: 'black'}),
                        stroke: new Stroke({
                            color: 'white',
                            width: 6,
                        }),
                    }),
                }));
            }
            this.map.render()
        },
        startAnimation() {
            if (this.animatingRouter) {
                this.geoMarker.getGeometry().setCoordinates(this.currentCoordinates[this.currentCoordinates.length-1]);
                this.routerVectorLayer.un("postrender", this.moveFeature);
            } else {
                this.animatingRouter = true;
                this.startTimeRouter = new Date().getTime();
                this.geoMarker.changed();
                this.routerVectorLayer.on("postrender", this.moveFeature);
                this.map.render()
            }
        }
        // 轨迹=========================end
    }
}
</script>

<style lang="scss" scoped>
  .command-center {
    width: 100%;
    height: 100%;
    .customDiv {
      z-index: 999;
      .HeadDiv {
        position: absolute;
        top: 50px;
        right: 700px;
        width: 600px;
        background: #409eff;
        padding: 10px;
        border-radius: 4px;
        /*.el-select {*/
        /*  width: 80%;*/
        /*}*/
      }
      .mapType {
        position: absolute;
        top: 10px;
        right: 50px;
        .el-radio {
          background: #fff;
          margin-right: 0;
        }
      }
      .optionDiv {
        position: absolute;
        bottom: 50px;
        right: 10px;
        width: 50px;
        .btn_gis {
          margin-bottom: 5px;
        }
      }
      .InfoListDiv {
        /deep/.el-drawer__wrapper {
          margin: 10px;
          top: 50px;
          left: auto;
          width: 550px;
          height: 600px;
          .el-drawer__header {
            /*padding: 10px 10px 0;*/
            font-size: 18px;
            font-weight: 600;
          }
          .el-drawer.rtl {
            background: rgba(255, 255, 255, 0.9);
            height: 600px;
            .orgType {
              cursor: pointer;
            }
            .el-drawer__body {
              padding: 0px 20px;
            }
            .el-table__body-wrapper {
              height: 360px;
              overflow-y: auto;
            }
          }
        }
      }
    }
    /**map*/
    .mapContainer {
      width: 100vw;
      height: 100vh;
      /**openLayer样式**/
        /deep/.ol-control {
            background-color: rgba(255, 255, 255, 0.8);
        }
      /**坐标信息*/
      /deep/.ol-mouse-position {
        bottom: 8px;
        left: 150px;
        top: unset;
        right: unset;
      }
      /**点扩散闪烁样式*/
      /deep/.point_animation_flag{
        background: #ff0000;
        width: 10px;
        height: 10px;
        border: 2px #ff0000 solid;
        border-radius: 50%;
        position: absolute;
        p, span{
          position: absolute;
          top: -25px;
          left: -25px;
          width: 60px;
          height: 60px;
          animation: point_animation_flag 1.5s infinite;
          box-shadow: 0px 0px 1px #ff0000;
          background: rgba(255, 0, 0, 0.25);
          margin: 0px;
          border-radius: 50%;
        }
        span{
          animation-delay: 0.8s;
        }
      }
      @keyframes point_animation_flag{
        10% {
          transform: scale(1);
        }
        100% {
          transform: scale(8);
        }
      }
      /deep/.point_animation_com{
        background: #367ae2;
        width: 10px;
        height: 10px;
        border: 2px #367ae2 solid;
        border-radius: 50%;
        position: absolute;
        p, span{
            position: absolute;
            top: -8px;
            left: -8px;
            width: 20px;
            height: 20px;
            animation: point_animation_com 1.5s infinite;
            box-shadow: 0px 0px 1px #0059e0;
            background: rgba(54, 122, 226, 0.25);
            margin: 0px;
            border-radius: 50%;
        }
        span{
            animation-delay: 0.8s;
        }
    }
      @keyframes point_animation_com{
            10% {
                transform: scale(1);
            }
            100% {
                transform: scale(8);
            }
        }
      /**弹窗样式*/
        /deep/.popup {
        position: absolute;
        background-color: rgba(255, 255, 255, 0.9);
        box-shadow: 0 1px 4px rgba(0,0,0,0.2);
        padding: 15px;
        border-radius: 10px;
        border: 1px solid #409eff;
        bottom: 12px;
        left: -50px;
        width: 335px;
        .el-header {
          color: #409eff;
            .name {
                width: calc(100% - 100px);
                float: left;
            }
            .optionBtn {
                width: 100px;
                float: right;
                text-align: right;
                cursor: pointer;
            }
        }
        .el-main {
          padding: 3px 20px;
          .numDiv {
            font-size: 18px;
            font-weight: 600;
            text-align: center;
          }
          .typeDiv {
            text-align: center;
          }
          .btn {
            background: #fbc500;
            border: 1px solid #fbc500;
            border-radius: 3px;
            cursor: pointer;
            float: right;
          }
        }
        #detailEquip {
            table {
                width: 100%;
                border: 1px solid #66b1ff;
                tbody {
                    color: #888;
                }
            }
        }
      }
      /deep/.popup:after, /deep/.popup:before {
        top: 100%;
        border: solid transparent;
        content: " ";
        height: 0;
        width: 0;
        position: absolute;
        pointer-events: none;
      }
      /deep/.popup:after {
        border-top-color: white;
        border-width: 10px;
        left: 48px;
        margin-left: -10px;
      }
      /deep/.popup:before {
        border-top-color: #cccccc;
        border-width: 11px;
        left: 48px;
        margin-left: -11px;
      }
    }
  }
</style>