| 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> |
| | | </template> |
| | | |
| | | <script> |
| | | // import OLCesium from "ol-cesium" |
| | | import "ol/ol.css" |
| | | import OlView from "ol/View.js" |
| | | import { |
| | | // eslint-disable-next-line no-unused-vars |
| | | defaults as OlControlDefaults, |
| | | defaults, |
| | | // 全屏控件 |
| | | FullScreen, |
| | | // 比例尺控件 |
| | | ScaleLine, |
| | | // 缩放滚动条控件 |
| | | // eslint-disable-next-line no-unused-vars |
| | | ZoomSlider, |
| | | // 鼠标位置控件 |
| | | // eslint-disable-next-line no-unused-vars |
| | | MousePosition, |
| | | // -地图属性控件 |
| | | Attribution, |
| | | // 鹰眼控件 |
| | | // eslint-disable-next-line no-unused-vars |
| | | OverviewMap, |
| | | // 缩放到范围控件 |
| | | // eslint-disable-next-line no-unused-vars |
| | | ZoomToExtent, |
| | | Rotate, |
| | | } from "ol/control.js" |
| | | import OlSourceOSM from "ol/source/OSM.js" |
| | | import OlLayerTile from "ol/layer/Tile.js" |
| | | |
| | | import { Image as ImageLayer } from 'ol/layer' |
| | | import ImageStatic from 'ol/source/ImageStatic.js' |
| | | |
| | | import OlLayerVectorTile from "ol/layer/VectorTile.js" |
| | | import OlMap from "ol/Map.js" |
| | | import OlProjection from "ol/proj/Projection.js" |
| | | import OlMVT from "ol/format/MVT.js" |
| | | import OlUnits from "ol/proj/Units.js" |
| | | import OlFeature from "ol/Feature" |
| | | |
| | | import { get as projGet } from "ol/proj.js" |
| | | // c |
| | | |
| | | 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 TileArcGISRest from "ol/source/TileArcGISRest" |
| | | import TilegridTileGrid from "ol/tilegrid/TileGrid" |
| | | |
| | | import GeoJSON from "ol/format/GeoJSON" |
| | | |
| | | import Feature from 'ol/Feature.js' |
| | | import Point from 'ol/geom/Point.js' |
| | | import { Icon, Style, Fill, Text, Stroke, Circle } from 'ol/style.js' |
| | | |
| | | |
| | | let mapView = null |
| | | let layersObjcect = {} |
| | | |
| | | let baseMapLayer = { |
| | | yx: [], |
| | | sl: [] |
| | | } |
| | | let options, |
| | | epsgcode, |
| | | isMvt = false |
| | | |
| | | let isMapResource = true |
| | | export default { |
| | | name: 'OlMapBox', |
| | | |
| | | props: { |
| | | mapType: { |
| | | type: String, |
| | | default: 'sl' |
| | | }, |
| | | |
| | | mapContrast: { |
| | | type: String, |
| | | default: 'custom' |
| | | } |
| | | }, |
| | | |
| | | data () { |
| | | return { |
| | | publicPath: process.env.BASE_URL, |
| | | } |
| | | }, |
| | | |
| | | |
| | | mounted () { |
| | | const that = this |
| | | |
| | | this.$nextTick(() => { |
| | | mapView = new OlMap({ |
| | | target: 'OlMapBoxElement', |
| | | layers: [], |
| | | view: new OlView({ |
| | | // 初始化中心点坐标,经纬度一会自己换一下 |
| | | center: [113, 24], |
| | | zoom: 18, |
| | | projection: "EPSG:4326" |
| | | }), |
| | | }) |
| | | |
| | | mapView.on("singleclick", function (event) { |
| | | mapView.forEachFeatureAtPixel( |
| | | event.pixel, |
| | | (feature) => { |
| | | feature.dispatchEvent && feature.dispatchEvent({ type: 'click', event: event }) |
| | | } |
| | | ) |
| | | }) |
| | | |
| | | that.baseInitLayer(that.mapType) |
| | | |
| | | |
| | | this.mapAddClusterLayer( |
| | | 'livePersonLocationLayer', |
| | | '/public/img/map/location', |
| | | [{lng: 113, lat: 24}, {lng: 115, lat:24 }], |
| | | (e) => { }, |
| | | ) |
| | | }) |
| | | }, |
| | | |
| | | methods: { |
| | | /** |
| | | * @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 || [160, 221], |
| | | 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 }) |
| | | }) |
| | | } |
| | | |
| | | iconFeature.setStyle(new Style(styleOptions)) |
| | | |
| | | iconFeature.on('click', (e) => { |
| | | if (params.event) { |
| | | params.event(e.target.values_.attributes.attr) |
| | | } |
| | | }) |
| | | |
| | | 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]) { |
| | | if (type == 'cluster') { |
| | | let source = new VectorSource() |
| | | |
| | | positionData.forEach(item => { |
| | | source.addFeature(that.getCurItemFeature({ |
| | | item, |
| | | lng: item.lng, |
| | | lat: item.lat, |
| | | url: imgUrl, |
| | | event: incident |
| | | })) |
| | | }) |
| | | |
| | | let layer = new Cluster({ |
| | | source: source, |
| | | distance: 100 |
| | | }) |
| | | |
| | | layersObjcect[layerName] = new VectorLayer({ |
| | | source: layer, |
| | | zIndex: 24, |
| | | style: (feature, resolution) => { |
| | | let size = feature.get('features').length |
| | | |
| | | let radius = 10 |
| | | |
| | | if (size > 900) { |
| | | radius = 19 |
| | | } else if (size > 600) { |
| | | radius = 16 |
| | | } else if (size > 400) { |
| | | radius = 13 |
| | | } |
| | | |
| | | let style = new Style({ |
| | | image: new Circle({ |
| | | radius: radius, |
| | | stroke: new Stroke({ |
| | | color: 'blue', |
| | | width: 1 |
| | | }), |
| | | fill: new Fill({ |
| | | color: 'blue' |
| | | }) |
| | | }), |
| | | text: new Text({ |
| | | text: size.toString(), |
| | | fill: new Fill({ |
| | | color: 'white' |
| | | }) |
| | | }) |
| | | }) |
| | | |
| | | return style |
| | | } |
| | | }) |
| | | |
| | | mapView.addLayer(layersObjcect[layerName]) |
| | | |
| | | return |
| | | } else { |
| | | 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.lng, |
| | | lat: item.lat, |
| | | url: imgUrl, |
| | | event: incident |
| | | })) |
| | | }) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang='scss' scope> |
| | | |
| | | .w100 { |
| | | width: 100%; |
| | | } |
| | | |
| | | .h100 { |
| | | height: 100%; |
| | | } |
| | | </style> |