| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513 |
- import Map from 'ol/Map.js';
- import View from 'ol/View.js';
- import {
- defaults as defaultControls
- } from 'ol/control.js';
- // 工具类
- import {
- getWidth,
- getTopLeft
- } from 'ol/extent.js';
- import {
- get as getProjection
- } from 'ol/proj.js';
- import GeoJSON from 'ol/format/GeoJSON';
- import WMTSTileGrid from 'ol/tilegrid/WMTS.js';
- // layer->source->feature->style
- // layer
- import {
- Vector as VectorLayer,
- Tile as TileLayer
- } from 'ol/layer';
- // source
- import {
- WMTS
- } from 'ol/source';
- import VectorSource from 'ol/source/Vector';
- // import {
- // TileSuperMapRest
- // } from '@supermap/iclient-ol';
- // feature
- import Feature from 'ol/Feature';
- import {
- Point,
- Polygon,
- MultiPolygon,
- LineString
- } from 'ol/geom';
- // style
- import {
- Icon,
- Style,
- Text,
- Fill,
- Stroke
- } from 'ol/style';
- // 弹窗
- import Overlay from 'ol/Overlay';
- // 选择
- import {
- Select
- } from 'ol/interaction';
- export default class olMapClass {
- constructor() {
- this.popUp = [] //弹窗
- this.mapLayers = {} //地图图层
- this.layerSelect = {} //图层选择对象
- this.center = [] //中心点
- this.zoom = 13
- }
- /**
- * @description 初始化地图
- * @param {String} domId 地图容器
- * @param {Array<Number,Number>} center 中心点经纬度数组
- */
- initOlMap(domId, center, zoom) {
- this.center = center
- this.zoom = zoom
- window.olMap = new Map({
- target: domId,
- view: new View({
- projection: 'EPSG:4326',
- center: center,
- zoom: zoom,
- maxZoom: 22,
- minZoom: 1
- }),
- controls: defaultControls({
- zoom: false,
- rotate: false,
- attribution: false
- })
- });
- }
- /**
- * @description 回到原点
- */
- resetMap() {
- window.olMap.getView().setCenter(this.center)
- window.olMap.getView().setZoom(this.zoom)
- }
- /**
- * @description 销毁地图
- */
- destoryOlMap() {
- window.olMap && window.olMap.dispose();
- window.olMap = null;
- }
- /**
- * @description 创建地图监听事件
- * @param {String} type 监听事件类型
- * @param {Function} callBack 执行函数
- */
- initOlMapEvent(type, callBack) {
- window.olMap.on(type, (event) => {
- callBack(event)
- });
- }
- /**
- * @description 注销地图事件, handler必须是创建地图事件时的执行函数
- * @param {String} type 监听事件类型
- * @param {Function} handler 执行函数
- */
- destoryOlMapEvent(type, handler) {
- window.olMap.un(type, handler)
- }
- /**
- * @description 添加图层选择事件
- * @param {Array} layers 需要选择的图层
- * @param {String} id 创建的选择器id
- * @param {Function} getOption 生成marker配置的函数
- * @param {Object} iconOption 图标的配置
- * @param {Object} textOption 文字的配置
- * @param {Function} callBack 执行函数
- */
- addLayerSelect(layers, id, getOption, callBack, falied) {
- let select = new Select({
- layers: layers,
- style: (feature) => {
- let options = getOption(feature)
- feature.setStyle(
- new Style({
- image: options.icon ? new Icon(options.icon) : null,
- text: options.text ? new Text(options.text) : null
- })
- )
- }
- })
- this.layerSelect[id] = select
- window.olMap.addInteraction(select)
- // 选择事件
- select.on('select', (evt) => {
- // 没选中则自动清除已选的feature
- if (evt.selected.length === 0) {
- select.getFeatures().clear()
- if (falied) falied()
- return
- }
- // 选中后执行后续操作
- callBack(evt)
- })
- }
- /**
- * @description 添加feature到选择器
- * @param {String} selectId 选择器id
- * @param {Object} feature 要选择的feature
- */
- _addFeatureToSelect(selectId, feature) {
- if (this.layerSelect[selectId]) {
- this.layerSelect[selectId].getFeatures().push(feature)
- }
- }
- /**
- * @description 从图层中查找对应的feature并添加到选择器
- * @param {String} layerTypeName 图层大类名称
- * @param {String} layerName 图层名称
- * @param {String} featureId 图层中feature的内置id
- * @param {String} selectId 选择器id
- */
- addFeatureToSelectFromLayer(layerTypeName, layerName, featureId, selectId) {
- if (!this.mapLayers[layerTypeName]) {
- return
- }
- if (!this.mapLayers[layerTypeName][layerName]) {
- return
- }
- let layer = this.mapLayers[layerTypeName][layerName]
- let features = layer.getSource().getFeatures()
- features.forEach(feature => {
- if (feature.values_.id === featureId) {
- this._addFeatureToSelect(selectId, feature)
- }
- })
- }
- /**
- * @description 添加地图图层(天地图、超图)
- * @param {String} layerTypeName 图层大类名称
- * @param {String} layerName 图层名称, 用作控制显示隐藏
- * @param {String} type 图层类型, 用来判断添加方法 tdt:天地图, super:超图
- * @param {String} url 地图url
- * @param {Boolean} show 是否显示
- */
- addMapLayers(layerTypeName, layerName, type, url, show) {
- if (!url) {
- return
- }
- let layer = null
- if (type === 'tdt') {
- layer = this._addWmtsLayer(url)
- }
- if (type === 'super') {
- // layer = this._addSuperMapLayer(url)
- }
- layer.setVisible(show)
- // 第一次出现图层大类
- if (!this.mapLayers[layerTypeName]) {
- this.mapLayers[layerTypeName] = {}
- this.mapLayers[layerTypeName][layerName] = layer
- } else {
- this.mapLayers[layerTypeName][layerName] = layer
- }
- window.olMap.addLayer(layer)
- }
- /**
- * @description 添加marker、高亮图层等
- * @param {String} layerTypeName 图层大类名称
- * @param {String} layerName 图层名称, 用作控制显示隐藏
- * @param {Boolean} show 是否显示
- * @param {Array<any>} dataList 用于创建图层的原始数据
- * @param {Boolean} ifSource 是否需要添加source
- * @param {Object} iconOption 图标的配置
- * @param {Object} textOption 文字的配置
- */
- addVectorLayers(layerTypeName, layerName, show, dataList, ifSource, iconOption, textOption) {
- let vectorSource = new VectorSource({});
- // 需要source才循环添加
- if (ifSource) {
- dataList.map((marker, index) => {
- let iconFeature = new Feature({
- geometry: new Point([marker.longitude, marker.latitude]),
- name: marker.name + '-' + index,
- id: marker.id,
- population: 4000,
- rainfall: 500,
- position: [marker.longitude, marker.latitude],
- ...marker
- });
- let iconStyle = new Style({
- image: iconOption ? new Icon(iconOption) : null,
- text: textOption ? new Text(textOption) : null
- });
- iconFeature.setStyle(iconStyle);
- vectorSource.addFeature(iconFeature)
- })
- }
- let layer = new VectorLayer({
- source: vectorSource
- });
- layer.setVisible(show)
- // 第一次出现图层大类
- if (!this.mapLayers[layerTypeName]) {
- this.mapLayers[layerTypeName] = {}
- this.mapLayers[layerTypeName][layerName] = layer
- } else {
- this.mapLayers[layerTypeName][layerName] = layer
- }
- window.olMap.addLayer(layer)
- }
- /**
- * @description 更新图层的显示属性或设置geometry
- * @param {String} layerTypeName 图层大类名称
- * @param {String} layerName 图层名称
- * @param {Boolean} show 是否显示
- * @param {String} updateType 更新类型,feature:更新feature内的geometry,source:更新source
- * @param {Object} geometry {type:类型,coordinates:点位数组}
- */
- updateLayer(layerTypeName, layerName, show, updateType = 'feature', geometry) {
- if (!this.mapLayers[layerTypeName]) {
- return
- }
- if (!this.mapLayers[layerTypeName][layerName]) {
- return
- }
- let layer = this.mapLayers[layerTypeName][layerName]
- // 是否设置显示隐藏属性
- if (typeof show === 'boolean') {
- layer.setVisible(show)
- }
- if (geometry) {
- // 更新feature内的geometry
- if (updateType === 'feature') {
- let originFeatures = layer.getSource().getFeatures()
- if (originFeatures.length) {
- originFeatures.forEach(feature => {
- feature.setGeometry(this._getFeatureGeometry(geometry))
- })
- } else {
- let newGeometry = this._getFeatureGeometry(geometry)
- let newFeature = new Feature({
- geometry: newGeometry
- })
- let style = new Style({
- stroke: new Stroke({
- color: '#ff8c00',
- width: 5,
- lineCap: 'round',
- lineJoin: 'round'
- })
- })
- newFeature.setStyle(style)
- layer.getSource().addFeature(newFeature);
- }
- }
- // 更新source
- if (updateType === 'source') {
- layer.getSource().clear();
- let newGeometry = this._getFeatureGeometry(geometry)
- let newFeature = new Feature({
- geometry: newGeometry
- })
- let style = new Style({
- fill: new Fill({
- color: '#ff0000'
- }),
- stroke: new Stroke({
- color: '#ff0000',
- width: 3
- })
- })
- newFeature.setStyle(style)
- layer.getSource().addFeature(newFeature);
- }
- }
- }
- /**
- * @description 清除图层source
- * @param {String} layerTypeName 图层大类名称
- * @param {String} layerName 图层名称
- */
- clearLayerSource(layerTypeName, layerName) {
- if (!this.mapLayers[layerTypeName]) {
- return
- }
- if (!this.mapLayers[layerTypeName][layerName]) {
- return
- }
- let layer = this.mapLayers[layerTypeName][layerName]
- layer.getSource().clear();
- }
- /**
- * @description 更新图层的显示属性或设置geometry
- * @param {String} layerTypeName 图层大类名称
- * @param {String} layerName 图层名称
- */
- getLayer(layerTypeName, layerName) {
- if (!this.mapLayers[layerTypeName]) {
- return
- }
- let resLayerList = []
- if (!layerName) {
- for (let key in this.mapLayers[layerTypeName]) {
- resLayerList.push(this.mapLayers[layerTypeName][key])
- }
- } else {
- resLayerList = [this.mapLayers[layerTypeName][layerName]]
- }
- return resLayerList
- }
- /**
- * @description 删除图层
- * @param {String} layerTypeName 图层大类名称
- * @param {String} layerName 图层名称
- */
- removeLayer(layerTypeName) {
- if (!this.mapLayers[layerTypeName]) {
- return
- }
- for (let key in this.mapLayers[layerTypeName]) {
- let layer = this.mapLayers[layerTypeName][key]
- window.olMap.removeLayer(layer)
- }
- this.mapLayers[layerTypeName] = {}
- }
- /**
- * @description 内部方法, 用于创建wmts图层, 添加天地图底图
- * @param {String} url 地图url
- * @return {TileLayer} TileLayer 返回图层
- */
- _addWmtsLayer(url) {
- if (!url) return null
- let projection = getProjection('EPSG:4326')
- let extent = projection.getExtent()
- let width = getWidth(extent)
- let resolutions = [],
- matrixIds = []
- for (let z = 1; z < 19; z++) {
- resolutions[z] = width / (256 * Math.pow(2, z))
- matrixIds[z] = z
- }
- let tileGrid = new WMTSTileGrid({
- origin: getTopLeft(extent),
- resolutions,
- matrixIds
- })
- // 匹配坐标系、图层类型
- let type = url.match(new RegExp(/\/(.{3})_(c|w)\//))
- return new TileLayer({
- source: new WMTS({
- crossOrigin: 'anonymous',
- url: url,
- layer: type[1],
- matrixSet: type[2],
- format: 'tiles',
- style: 'default',
- wrapX: true,
- projection: projection,
- tileGrid
- })
- })
- }
- /**
- * @description 内部方法,根据geometry类型返回对应的feature
- * @param {Object} geometry 原始geometry数据{type, coordinates}
- */
- _getFeatureGeometry(geometry) {
- if (!geometry.type) {
- return
- }
- let featureGeometry;
- if (geometry.type === 'Point') {
- featureGeometry = new Point(geometry.coordinates)
- }
- if (geometry.type === 'Polygon') {
- featureGeometry = new Polygon(geometry.coordinates)
- }
- if (geometry.type === 'MultiPolygon') {
- featureGeometry = new MultiPolygon(geometry.coordinates)
- }
- if (geometry.type === 'LineString') {
- featureGeometry = new LineString(geometry.coordinates)
- }
- return featureGeometry;
- }
- /**
- * @description 添加popUp弹窗
- * @param {String} id 弹窗的id
- * @param {String} domId 弹窗的domId
- * @param {Boolean} show 初始化弹窗时是否显示
- * @param {Array<Number,Number>} position 要添加弹窗图的坐标数组
- */
- addPopUp(id, domId, show, position) {
- let popup = new Overlay({
- element: document.getElementById(domId),
- // 当前窗口可见
- autoPan: true,
- stopEvent: true,
- autoPanAnimation: {
- duration: 250
- }
- })
- window.olMap.addOverlay(popup)
- if (position && position instanceof Array) {
- show ? popup.setPosition(position) : popup.setPosition(undefined)
- } else {
- popup.setPosition(undefined)
- }
- this.popUp.push({
- popId: id,
- popObj: popup
- })
- }
- /**
- * @description 更新弹窗位置或显示隐藏
- * @param {String} id 弹窗的id
- * @param {Boolean} show 是否显示
- * @param {Array<Number,Number>} position 要添加弹窗图的坐标数组
- */
- updatePopUp(id, show, position) {
- if (!this.popUp.length) {
- return
- }
- let popup = this.popUp.find(pop => pop.popId === id)?.popObj
- if (!popup) {
- return
- }
- // 是否显示弹窗
- if (position && position instanceof Array) {
- show ? popup.setPosition(position) : popup.setPosition(undefined)
- } else {
- popup.setPosition(undefined)
- }
- }
- /**
- * @description 移除弹窗, 多个则传入弹窗id数组, 该方法会删除弹窗dom
- * @description 如果不想删除弹窗dom, 请使用updatePopUp()
- * @param {Array<String> & String} id 弹窗的id
- */
- removePopUp(id) {
- this.popUp.forEach(pop => {
- if (id && id instanceof Array) {
- id.indexOf(pop.popId) > -1 && window.olMap.removeOverlay(pop.popObj)
- }
- if (id && typeof id === 'string') {
- id === pop.popId && window.olMap.removeOverlay(pop.popObj)
- }
- })
- }
- /**
- * @description 移除所有弹窗, delDom会删除弹窗dom
- * @param {Boolean} delDom 是否移除dom
- */
- removeAllPopUp(delDom) {
- if (delDom) {
- window.olMap.getOverlays().clear()
- } else {
- this.popUp.forEach(pop => {
- pop.popObj.setPosition(undefined)
- })
- }
- }
- }
|