| New file |
| | |
| | | <!-- |
| | | * @Author: shuishen 1109946754@qq.com |
| | | * @Date: 2023-10-11 16:01:58 |
| | | * @LastEditors: shuishen 1109946754@qq.com |
| | | * @LastEditTime: 2023-11-29 14:17:09 |
| | | * @FilePath: \web\business\src\components\OlMapBox\index.vue |
| | | * @Description: |
| | | * |
| | | * Copyright (c) 2023 by shuishen, All Rights Reserved. |
| | | --> |
| | | <template> |
| | | <div class="w100 h100"> |
| | | <div id="OlMapBoxElement" class="w100 h100"> |
| | | </div> |
| | | <div id="popup" class="ol-popup" v-show="isShowUnitInfoPopover"> |
| | | <a href="#" id="popup-closer" class="ol-popup-closer"></a> |
| | | <div id="popup-content"> |
| | | <p>负责人:{{ unitData.securityLinkman }}</p> |
| | | <p>联系方式:{{ unitData.cell }}</p> |
| | | <p>派遣保安员数:{{ unitData.num }}</p> |
| | | <p>派遣单位行业:{{ unitData.professionName }}</p> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import "ol/ol.css" |
| | | import OlView from "ol/View.js" |
| | | import OlLayerTile from "ol/layer/Tile.js" |
| | | import Overlay from "ol/Overlay.js" |
| | | import OlMap from "ol/Map.js" |
| | | import XYZ from "ol/source/XYZ" |
| | | import Cluster from "ol/source/Cluster" |
| | | import VectorLayer from "ol/layer/Vector" |
| | | import VectorSource from "ol/source/Vector" |
| | | import Feature from 'ol/Feature.js' |
| | | import Point from 'ol/geom/Point.js' |
| | | import { Icon, Style, Fill, Text, Stroke, Circle } from 'ol/style.js' |
| | | import { getAlldata } from "@/api/dispatch/dispatch" |
| | | import { mapGetters } from "vuex" |
| | | import { mapState } from "vuex" |
| | | |
| | | let mapView = null |
| | | let layersObjcect = {} |
| | | |
| | | let baseMapLayer = { |
| | | yx: [], |
| | | sl: [] |
| | | } |
| | | |
| | | let unitInfoPopover = null |
| | | |
| | | export default { |
| | | name: 'OlMapBox', |
| | | |
| | | props: { |
| | | mapType: { |
| | | type: String, |
| | | default: 'sl' |
| | | }, |
| | | |
| | | mapContrast: { |
| | | type: String, |
| | | default: 'custom' |
| | | } |
| | | }, |
| | | |
| | | data () { |
| | | return { |
| | | publicPath: process.env.BASE_URL, |
| | | unitData: {}, |
| | | isShowUnitInfoPopover: false |
| | | } |
| | | }, |
| | | |
| | | computed: { |
| | | ...mapGetters(["permission", "userInfo"]), |
| | | |
| | | ...mapState({ |
| | | userInfo: state => state.user.userInfo |
| | | }) |
| | | }, |
| | | mounted () { |
| | | const that = this |
| | | |
| | | this.$nextTick(() => { |
| | | mapView = new OlMap({ |
| | | target: 'OlMapBoxElement', |
| | | layers: [], |
| | | view: new OlView({ |
| | | // 初始化中心点坐标,经纬度一会自己换一下 |
| | | center: [112.85857823133, 35.496284586473], |
| | | zoom: 18, |
| | | projection: "EPSG:4326" |
| | | }), |
| | | }) |
| | | |
| | | mapView.on("singleclick", function (event) { |
| | | mapView.forEachFeatureAtPixel( |
| | | event.pixel, |
| | | (feature) => { |
| | | feature.dispatchEvent && feature.dispatchEvent({ type: 'click', event: event }) |
| | | } |
| | | ) |
| | | }) |
| | | |
| | | mapView.getView().on('change:resolution', function () { |
| | | // console.log('mapView地图缩放事件') |
| | | }) |
| | | |
| | | that.getAlldata() |
| | | that.baseInitLayer(that.mapType) |
| | | }) |
| | | }, |
| | | |
| | | methods: { |
| | | // 图标点击事件 |
| | | pqfwIconClick (e) { |
| | | this.generateMapPopup(e) |
| | | }, |
| | | |
| | | // 获取派遣服务列表 |
| | | getAlldata () { |
| | | let params = {} |
| | | let roleName = this.userInfo.role_name |
| | | if ( |
| | | roleName == "保安公司管理员" || |
| | | roleName == "保安" || |
| | | roleName == "分公司管理员" |
| | | ) { |
| | | params.deptId = this.userInfo.dept_id |
| | | } else if (roleName == "公安管理员" || roleName == "administrator" || roleName == "民警") { |
| | | params.jurisdiction = this.userInfo.jurisdiction |
| | | } |
| | | getAlldata(params).then(res => { |
| | | this.$nextTick(() => { |
| | | this.mapRemoveLayer(['pqfwLayer']) |
| | | this.mapAddClusterLayer('pqfwLayer', 'img/map/unit.png', res.data.data, this.pqfwIconClick) |
| | | }) |
| | | }) |
| | | }, |
| | | |
| | | /** |
| | | * @description: 底图加载 |
| | | * @param {*} type |
| | | * @return {*} |
| | | */ |
| | | baseInitLayer (type) { |
| | | if (baseMapLayer.yx.length) { |
| | | baseMapLayer.yx.forEach(item => { |
| | | mapView.removeLayer(item) |
| | | }) |
| | | baseMapLayer.yx = [] |
| | | } |
| | | |
| | | if (baseMapLayer.sl.length) { |
| | | baseMapLayer.sl.forEach(item => { |
| | | mapView.removeLayer(item) |
| | | }) |
| | | baseMapLayer.sl = [] |
| | | } |
| | | |
| | | if (type == 'yx') { |
| | | let yxImgW = new OlLayerTile({ |
| | | zIndex: 1, |
| | | title: '影像', |
| | | source: new XYZ({ |
| | | url: 'https://t0.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c', |
| | | }) |
| | | }) |
| | | |
| | | mapView.addLayer(yxImgW) |
| | | |
| | | baseMapLayer.yx.push(yxImgW) |
| | | |
| | | let yxCvaW = new OlLayerTile({ |
| | | zIndex: 2, |
| | | title: '影像标注', |
| | | source: new XYZ({ |
| | | url: 'https://t0.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c', |
| | | }) |
| | | }) |
| | | |
| | | mapView.addLayer(yxCvaW) |
| | | |
| | | baseMapLayer.yx.push(yxCvaW) |
| | | } else if (type == 'sl') { |
| | | let slVecW = new OlLayerTile({ |
| | | zIndex: 2, |
| | | title: '矢量', |
| | | source: new XYZ({ |
| | | url: 'https://t0.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c', |
| | | }) |
| | | }) |
| | | |
| | | mapView.addLayer(slVecW) |
| | | |
| | | baseMapLayer.sl.push(slVecW) |
| | | |
| | | let slCvaW = new OlLayerTile({ |
| | | zIndex: 2, |
| | | title: '矢量标注', |
| | | source: new XYZ({ |
| | | url: 'https://t0.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c', |
| | | }) |
| | | }) |
| | | |
| | | mapView.addLayer(slCvaW) |
| | | |
| | | baseMapLayer.sl.push(slVecW) |
| | | } |
| | | }, |
| | | |
| | | // javascript 转换 |
| | | lonLat2Mercator (lonlat) { |
| | | var mercator = { |
| | | x: 0, |
| | | y: 0 |
| | | } |
| | | var earthRad = 6378137.0 |
| | | mercator.x = lonlat.lng * Math.PI / 180 * earthRad |
| | | var a = lonlat.lat * Math.PI / 180 |
| | | mercator.y = earthRad / 2 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a))) |
| | | return mercator |
| | | }, |
| | | |
| | | // 生成图标图层 |
| | | getCurItemFeature (params) { |
| | | const iconFeature = new Feature({ |
| | | geometry: new Point([Number(params.lng), Number(params.lat)]), |
| | | attributes: params.item |
| | | }) |
| | | |
| | | let styleOptions = { |
| | | cursor: 'pointer', |
| | | } |
| | | |
| | | if (params.url) { |
| | | styleOptions.image = new Icon({ |
| | | scale: params.scale || 1, |
| | | imgSize: params.imgSize || [32, 32], |
| | | src: params.url, |
| | | }) |
| | | } |
| | | |
| | | if (params.text) { |
| | | let textElement = document.createElement('span') |
| | | textElement.innerHTML = params.text |
| | | |
| | | let color = '#0000FF' |
| | | |
| | | styleOptions.text = new Text({ |
| | | // 对齐方式 |
| | | textAlign: 'center', |
| | | // 文本基线 |
| | | textBaseline: 'middle', |
| | | text: textElement.innerHTML, |
| | | font: '14px Arial', |
| | | fill: new Fill({ |
| | | color: 'white' |
| | | }), |
| | | // 填充背景 |
| | | backgroundFill: new Fill({ |
| | | color: color |
| | | }), |
| | | padding: [2, 5, 2, 5], |
| | | stroke: new Stroke({ color: '#00000000', width: 1 }), |
| | | // offsetX: -60, |
| | | offsetY: 30 |
| | | }) |
| | | } |
| | | |
| | | iconFeature.setStyle(new Style(styleOptions)) |
| | | |
| | | iconFeature.on('click', (e) => { |
| | | if (params.event) {//icon事件参数 |
| | | params.event(e.target.values_.attributes)//点击事件触发事件并传参 |
| | | } |
| | | }) |
| | | return iconFeature |
| | | }, |
| | | |
| | | /** |
| | | * 删除图层 |
| | | * @param {*} layerName 图层名称 |
| | | */ |
| | | mapRemoveLayer (layerNames) { |
| | | layerNames.forEach(item => { |
| | | if (layersObjcect[item] && layersObjcect[item] != null) { |
| | | mapView.removeLayer(layersObjcect[item]) |
| | | delete layersObjcect[item] |
| | | } |
| | | |
| | | if (layersObjcect[item + 'ONE'] && layersObjcect[item + 'ONE'] != null) { |
| | | mapView.removeLayer(layersObjcect[item + 'ONE']) |
| | | delete layersObjcect[item + 'ONE'] |
| | | } |
| | | |
| | | if (layersObjcect[item + 'TWO'] && layersObjcect[item + 'TWO'] != null) { |
| | | mapView.removeLayer(layersObjcect[item + 'TWO']) |
| | | delete layersObjcect[item + 'TWO'] |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | // 添加聚合图层的新模式,水库点分布 |
| | | mapAddClusterLayer (layerName, imgUrl, positionData, incident = (e) => { }, type = '') { |
| | | const that = this |
| | | if (!layersObjcect[layerName]) { |
| | | layersObjcect[layerName] = new VectorLayer({ |
| | | // 图标图层 |
| | | zIndex: 24, |
| | | // minZoom: 12, |
| | | source: new VectorSource(), |
| | | }) |
| | | mapView.addLayer(layersObjcect[layerName]) |
| | | } |
| | | |
| | | positionData.forEach(item => { |
| | | layersObjcect[layerName].getSource().addFeature(that.getCurItemFeature({ |
| | | item, |
| | | lng: item.longitude, |
| | | lat: item.latitude, |
| | | text: item.name, |
| | | url: imgUrl, |
| | | event: incident |
| | | })) |
| | | }) |
| | | mapView.getView().animate({ // 只设置需要的属性即可 |
| | | center: [positionData[0].longitude, positionData[0].latitude], // 中心点 |
| | | // zoom: 18, // 缩放级别 |
| | | rotation: undefined, // 缩放完成view视图旋转弧度 |
| | | // duration: 1000 // 缩放持续时间,默认不需要设置 |
| | | }) |
| | | }, |
| | | |
| | | // 生成地图弹窗 |
| | | generateMapPopup (e) { |
| | | const that = this |
| | | this.unitData = e |
| | | this.isShowUnitInfoPopover = true |
| | | var container = document.getElementById('popup') |
| | | var closer = document.getElementById('popup-closer') |
| | | |
| | | // 创建popup |
| | | unitInfoPopover = new Overlay({ |
| | | element: container, |
| | | autoPan: true, |
| | | positioning: 'bottom-center', |
| | | stopEvent: false, |
| | | autoPanAnimation: { |
| | | duration: 250 |
| | | } |
| | | }) |
| | | mapView.addOverlay(unitInfoPopover) |
| | | closer.onclick = function () { |
| | | unitInfoPopover.setPosition(undefined) |
| | | closer.blur() |
| | | return false |
| | | } |
| | | unitInfoPopover.setPosition([e.longitude, e.latitude]) |
| | | }, |
| | | |
| | | |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang='scss' scope> |
| | | .w100 { |
| | | width: 100%; |
| | | } |
| | | |
| | | .h100 { |
| | | height: 100%; |
| | | } |
| | | |
| | | .ol-popup { |
| | | position: absolute; |
| | | background-color: white; |
| | | -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2)); |
| | | filter: drop-shadow(0 1px 4px #FFC125); |
| | | padding: 15px; |
| | | border-radius: 10px; |
| | | border: 1px solid #cccccc; |
| | | bottom: 34px; |
| | | left: -46px; |
| | | min-width: 300px; |
| | | } |
| | | |
| | | .ol-popup:after, |
| | | .ol-popup:before { |
| | | top: 100%; |
| | | border: solid transparent; |
| | | content: " "; |
| | | height: 0; |
| | | width: 0; |
| | | position: absolute; |
| | | pointer-events: none; |
| | | } |
| | | |
| | | .ol-popup:after { |
| | | border-top-color: white; |
| | | border-width: 10px; |
| | | left: 48px; |
| | | margin-left: -10px; |
| | | } |
| | | |
| | | .ol-popup:before { |
| | | border-top-color: #cccccc; |
| | | border-width: 11px; |
| | | left: 48px; |
| | | margin-left: -11px; |
| | | } |
| | | |
| | | .ol-popup-closer { |
| | | text-decoration: none; |
| | | position: absolute; |
| | | top: 2px; |
| | | right: 8px; |
| | | color: red; |
| | | } |
| | | |
| | | .ol-popup-closer:after { |
| | | content: "✖"; |
| | | } |
| | | </style> |