import request from 'axios'; // wms 通用参数 const WMS_PARAMS = { SERVICE: 'WMS', VERSION: '1.3.0', REQUEST: 'GetMap', FORMAT: 'image/png', TRANSPARENT: true, srs: 'EPSG:3857', width: 256, height: 256, bbox: 'bboxx', } const WFS_PARAMS = { SERVICE: 'WFS', request: 'GetFeature', typeName: 'typename', VERSION: '1.1.0', outputFormat: 'application/json', bbox: '', } const VECTOR_TYPE = { POINT: 'POINT', LINESTRING: 'LINESTRING', POLYGON: 'POLYGON' } const mapConfig = { 'NAN_PING':{ center: [118.09335687862085, 27.36991075178898] }, 'NAN_PING_':{ center: [118.09335687862085, 27.36991075178898] }, 'WU_HU':{ center: [118.43303301141083,31.350763350582454], } }[import.meta.env.VITE_PROJECT_NAME] export default class NewFiberMapUtils { //地图实例 map = null; //三维场景对象 virtualSpaceObj = null; //搜索对象 search = null; features = []; //相机动画对象 animation = null; //点聚合对象 markerCluster = null; callbacks = { mapClick: undefined, featureClick: undefined } imageLayers = []; canvasLayers = []; timer = null; static defaultParams = { keys: { temporary: 'temporary', primaryKey: 'primary_key' }, url: { icon: 'https://lkimgyt.luokuang.com/1592966522911.png' }, size: { icon: [32, 32] }, flyTo: { duration: 3000, zoom: 15, center: mapConfig.center } } static mapConfig = { adcode: 411600, container: 'map', zoom: 11.6, pitch: 0, bearing: 0, fog: false, antialias: true, // 是否开启抗锯齿 cursor: 'default', center: new LKMap.LngLat(...mapConfig.center), minZoom: 3, maxZoom: 22, isHotspot: false, isHotspotActive: false } static _layers = { terrain: { url: "https://api.luokuang.com/data3d/terrain_png/440100/20220901/{z}/{x}/{y}.png" }, baseMap: [ { id: 'baseMap_vector', name: '矢量图', icon: import.meta.env.VITE_APP_MAP_SRC + 'static/images/ylz/dengjired.png', type: 0, url: import.meta.env.VITE_APP_MAP_SRC + 'static/libs/map/nightblue.json', check: true }, { id: 'baseMap_imagery', name: '影像图', icon: import.meta.env.VITE_APP_MAP_SRC + 'static/images/ylz/dengjigreen.png', type: 1, url: 'https://gac-geo.googlecnapps.cn/maps/vt?lyrs=s&hl=zh-CN&gl=CN&x={x}&y={y}&z={z}&src=app&scale=2' }, ], wms: { }, features: [] } constructor(container, options) { this.initMap(container, options); } initMap(container, options) { let self = this; let config = Object.assign(NewFiberMapUtils.mapConfig, options); config.container = container || config.container; if(import.meta.env.VITE_PROJECT_NAME == 'NAN_PING') config.style = { "version": 8, "sources": {"raster-tiles": {"type": "raster", "tiles": ['http://192.168.1.38:8900/OfflineMap/mapabc/satellite/{z}/{x}/{y}.jpg'], "tileSize": 256}}, // "sources": {"raster-tiles": {"type": "raster", "tiles": ['http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}'], "tileSize": 256}}, "layers": [{"id": "simple-tiles", "type": "raster", "source": "raster-tiles", "minzoom": 0, "maxzoom": 22}] } self.callbacks = { mapClick: options.mapClick, featureClick: options.featureClick } this.map = new LKMap.Map(config.container, config); this.map.on('load', () => { // this.addTerrain(); // this.addControl(); self.updateSky(); self.addBaseMapImagery(); self.mapZoomEndEvt(); //地图点击回调 if (self.callbacks.mapClick) this.mapClick(self.callbacks); self.animation = new LKMap.CameraAnimation({ map: this.map }); /* this.map.plugin(["MarkerClusterer", "AnalysisSearch"], function () { //查询对象 self.search = new LKMap.AnalysisSearch({ size: 10, adcode: NewFiberMapUtils.mapConfig.adcode, regionLimit: true }) //聚合对象 self.markerCluster = new LKMap.MarkerClusterer({ map: self.map }); });*/ if(import.meta.env.VITE_PROJECT_NAME == 'NAN_PING'){ let configs = [ // {id:'tdt_vec',url:'http://t{s}.tianditu.com/DataServer?T=vec_w&X={x}&Y={y}&L={z}&tk=dee46731f7a87187c6507ff35aa9f2ef',params:{subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], minZoom: 1, maxZoom: 19, tileType: 'xyz'}}, {id:'iserver_basemap_vec',url: import.meta.env.VITE_PROJECT_ISERVER_URL+'/iserver/services/map-arcgis-50/wmts100?layer=图层&style=default&tilematrixset=GlobalCRS84Scale_图层&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/png&TileMatrix={z}&TileCol={x}&TileRow={y}',params:{subdomains: [], minZoom: 1, maxZoom: 19, tileType: 'xyz'}}, {id:'iserver_basemap_annotation',url:import.meta.env.VITE_PROJECT_ISERVER_URL+'/iserver/services/map-arcgis-51/wmts100?layer=图层&style=default&tilematrixset=GlobalCRS84Scale_图层&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/png&TileMatrix={z}&TileCol={x}&TileRow={y}',params:{subdomains: [], minZoom: 1, maxZoom: 19, tileType: 'xyz'}}, // {id:'iserver_china_4490',url:'https://iserver.supermap.io/iserver/services/map-china400/rest/maps/China_4490/zxyTileImage.png?z={z}&x={x}&y={y}',params:{subdomains: [], minZoom: 1, maxZoom: 19, tileType: 'xyz'}}, ]; configs.forEach(config => { new WMTSLayer({url:config.url}).addTo(self.map); }) // configs.forEach(config => self.map.addLayer(new customTileLayer(config.id, config.url,config.params))) } self.loadVectorWall(); }); if(!!!(import.meta.env.VITE_PROJECT_NAME == 'NAN_PING')) self.map.setStyle(NewFiberMapUtils._layers.baseMap[0].url); } async loadVectorWall(){ let {data} = await request(import.meta.env.VITE_APP_MAP_SRC + 'static/json/' + import.meta.env.VITE_PROJECT_NAME+'_'+'boundary.json'); let effectLayer = new this.virtualSpaceObj.DynamicEffect({VirtualSpace: this.virtualSpaceObj,}); effectLayer.createTextureWall({ id: 5, url: 'https://lkimgyt.luokuang.com/1655804893047.png', path: turf.getCoords(data.features[0])[0][0], direction: 3, height: 3000, base: 18, isGradient: true, repeatY: 4 }) } searchByKeyWord(keyword, callback) { let self = this; self.search.search(keyword, callback) } featureClick(feature, callback) { feature.on('click', (e) => callback(e)) } mapZoomEndEvt() { let self = this; self.map.on('zoomend', (e) => { markerScopeEvt(); }) function markerScopeEvt() { let zoom = self.map.getZoom(); self.features.filter(i => !!i.getIcon).forEach(i => { let iconScope = i.getIcon().options.scope; let labelScope = ((i.getLabel() || {}).scope) || [0, 25]; i[['hide', 'show'][Number(zoom > iconScope[0] && zoom < iconScope[1])]](); if (!!(i.getLabel())) i.setLabelStyle(Object.assign(i.getLabel().style, { 'opacity': Number(zoom > labelScope[0] && zoom < labelScope[1]) })); }) } } mapClick(callback) { let self = this; this.map.on('click', (e) => { const zoom = self.map.getZoom(); const value = Math.pow(2, 22 - zoom); let { lng, lat } = e.lngLat; let val = 0.0005; let bbox = turf.bbox(turf.buffer(turf.point([lng, lat]), val)); // let bbox = turf.bbox(turf.buffer(turf.point(CoordTransform.gcj02towgs84(lng,lat)),val)); const center = wgs84ToMercator(lng, lat); // const [] // const min = [center.x - value, center.y - value]; // const max = [center.x + value, center.y + value]; let params = Object.assign(WFS_PARAMS, {}); // delete params.bbox; // params.bbox = bbox.join(',') // params.filter = `<Filter xmlns="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"><Intersects><PropertyName>geometrys</PropertyName><gml:Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"><gml:coordinates>${CoordTransform.gcj02towgs84(lng,lat).join(',')}</gml:coordinates></gml:Point></Intersects></Filter>` // params.bbox = `${lng - val},${lat - val},${lng + val},${lat + val}` // params.bbox = [min,max].flat().join(','); bbox.push('EPSG:4326') params.bbox = bbox.join(','); if (!!!(Object.keys(NewFiberMapUtils._layers.wms).length)) return let { linestring, point } = NewFiberMapUtils._layers.wms; let lineStringChecks = linestring.children.filter(i => i.check); let pointChecks = point.children.filter(i => i.check); let urls = []; urls.push(!!lineStringChecks.length && linestring); urls.push(!!pointChecks.length && point); urls = urls.filter(Boolean).map(item => { let url = item.url; params.typeName = item.layers; url = url + '?' + Object.keys(params).map(key => `${key}=${params[key]}`).join('&'); return request({ url: url.toString() }); }); if (!!!urls.length) return Promise.resolve(); Promise.all(urls).then((results) => callback(results)); }) function wgs84ToMercator(lng, lat) { lng = parseFloat(lng); lat = parseFloat(lat); let d = Math.PI / 180, max = 90, sin = Math.sin(lat * d); lat = Math.max(Math.min(max, lat), -max); let x = 6378137 * lng * d; let y = 6378137 * Math.log((1 + sin) / (1 - sin)) / 2; return { x, y }; }; } addBaseMapImagery() { NewFiberMapUtils._layers.baseMap[1].instance = new LKMap.TileLayer({ getTileUrl: NewFiberMapUtils._layers.baseMap[1].url, opacity: 1 }); NewFiberMapUtils._layers.baseMap[1].instance.setMap(this.map); NewFiberMapUtils._layers.baseMap[1].instance.hide(); } wmsLayerChange(cItem, cIndex, item) { console.log(cItem, cIndex, item); console.log(item.url); let self = this; cItem.instance ? cItem.check ? cItem.instance.show() : cItem.instance.hide() : loadWms(); function loadWms() { let bboxKey = WMS_PARAMS.bbox; let url = item.url; let params = Object.assign(WMS_PARAMS, { LAYERS: item.layers, cql_filter: `${item.filterField}='${cItem.id}'` }); url = url + '?' + Object.keys(params).map(key => `${key}=${params[key]}`).join('&'); console.log(url); cItem.instance = new LKMap.TileLayer.WMS({ getTileUrl: (bbox) => url.replaceAll(bboxKey, bbox) }); cItem.instance.setMap(self.map); } } baseMapChange(item) { item.instance ? item.check ? item.instance.show() : item.instance.hide() : NewFiberMapUtils._layers.baseMap[1].instance.hide(); } updateSky() { let self = this; // 实例化三维场景类 self.virtualSpaceObj = new LKMap.VirtualSpace({ map: self.map, /*** * 天空盒类型: * 1. hdr_morning 早上 * 2. hdr_daylight 白天 * 3. hdr_sunset 日落 * 4. hdr_night 晚上 */ skyType: "hdr_daylight", // 设置天空盒类型 }); } addTerrain() { this.map.addTerrain({ url: NewFiberMapUtils._layers.terrain.url, exaggeration: 1, maxDrapeOverZoom: 5, }) this.map.addHillshading({ illuminationAnchor: "map", exaggeration: 0.5, }); } // 添加地图控件 addControl(params) { let self = this; // 缩放控件 this.map.plugin(["ToolBar", "Scale", "ControlBar"], function () { [ new LKMap.ToolBar({ position: 'bottom-right', showZoom: true, liteStyle: true }), new LKMap.Scale({ position: 'bottom-left' }), new LKMap.ControlBar({ position: 'bottom-right' }) ].forEach(control => self.map.addControl(control)) }); } static throttle(fn, delay = 300) { let timer = null return function (...args) { if (timer == null) { timer = setTimeout(() => { fn.call(this, ...args) clearTimeout(timer) timer = null }, delay); } } } addMarkers(lngLats, properties, labelScope = [15, 25], iconScope = [0, 25]) { let self = this; return lngLats.map((lngLat, index) => { let id = properties[index].mapParams.id ?? NewFiberMapUtils.defaultParams.keys.temporary; let icon = properties[index].mapParams.icon ?? NewFiberMapUtils.defaultParams.url.icon; let size = properties[index].mapParams.size ?? NewFiberMapUtils.defaultParams.size.icon; let marker = new LKMap.Marker({ map: self.map, position: new LKMap.LngLat(...lngLat), anchor: 'bottom', extData: properties[index] ?? {}, icon: new LKMap.Icon({ size: new LKMap.Size(...size), image: icon, scope: iconScope, anchor: 'top-center' }), label: { scope: labelScope, content: properties[index].mapParams.name ?? '', direction: 'top', offset: new LKMap.Pixel(0, -5), style: { 'background-color': "rgba(255,255,255,1)", 'padding': '5px 10px', 'border-radius': '4px', 'color': 'black', 'box-shadow': '0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)' } }, }); marker.newfiberId = id; return marker; // this.features.push(marker); }) } addPolygon(lngLats, properties, labelScope = [15, 25], iconScope = [0, 25]) { let self = this; return lngLats.map((lngLat, index) => { let id = properties[index].mapParams.id ?? NewFiberMapUtils.defaultParams.keys.temporary; let color = properties[index].mapParams.color; let polygon = new LKMap.Polygon({ path: lngLat, strokeWeight: 2, strokeOpacity: 0.8, strokeColor: color, fillColor: color, extData: properties[index] }); polygon.newfiberId = id; polygon.setMap(self.map); return polygon; // this.features.push(marker); }) } addPolyline(lngLats, properties) { let self = this; return lngLats.map((lngLat, index) => { let id = properties[index].mapParams.id ?? NewFiberMapUtils.defaultParams.keys.temporary; let color = properties[index].mapParams.color; let polyline = new LKMap.Polyline({ map: self.map, path: lngLat, strokeWeight: 1, showBorder: true, // 是否显示描边 borderWeight: 1, // 描边宽度 borderColor: color, extData: properties[index] }); polyline.newfiberId = id; return polyline; // this.features.push(marker); }) } addGeojson(geoJSON) { let self = this; let features = []; /* let features = geoJSON.features.map(feature => { let type = feature.geometry.type.toLocaleUpperCase(); let coordinates = feature.geometry.coordinates; let properties = feature.properties; let lkFeature = []; if(type.includes(VECTOR_TYPE.POINT)) lkFeature = self.addMarkers(coordinates,[properties]) if(type.includes(VECTOR_TYPE.LINESTRING)) lkFeature = self.addPolyline([coordinates],[properties]) if(type.includes(VECTOR_TYPE.POLYGON)) lkFeature = self.addPolygon([coordinates],[properties]) return lkFeature[0]; }).filter(Boolean);*/ let geojson = new LKMap.GeoJSON({ geoJSON, // GeoJSON对象 getMarker: function (feature, lnglats) {//还可以自定义getMarker和getPolyline features.push(self.addMarkers([lnglats], [feature.properties])); }, getPolygon: (feature, lnglats) => { let polygon = self.addPolygon([lnglats], [feature.properties]); features.push(polygon); }, getPolyline: (feature, lnglats) => { features.push(self.addPolyline([lnglats], [feature.properties])); } }); if (self.callbacks.featureClick) features.flat(Infinity).forEach(i => self.featureClick(i, self.callbacks.featureClick)); self.features = self.features.concat(features).flat(Infinity); } beansToGeojson(beans, fields = { id: 'id', color: 'color', geometry: 'geometry', name: 'name', icon: 'icon_url' }) { return turf.featureCollection(beans.filter(bean => bean[fields.geometry]).map(bean => { let mapParams = { id: bean[fields.id] || NewFiberMapUtils.defaultParams.keys.temporary, color: bean[fields.color] || NewFiberMapUtils.randomRgb(), icon: bean[fields.icon] || NewFiberMapUtils.defaultParams.url.icon, name: bean[fields.name] || '' }; bean = Object.assign({ mapParams }, bean); let feature = turf.feature(Terraformer.WKT.parse(bean[fields.geometry]), bean); gcoord.transform(feature, gcoord.WGS84, gcoord.GCJ02); let point = turf.center(feature.geometry); point.properties = bean; return [feature, point]; }).flat(Infinity)) } flyTo(params, callback) { let defaultFlyParams = NewFiberMapUtils.defaultParams.flyTo; defaultFlyParams = Object.assign(defaultFlyParams, params); this.animation.flyTo(defaultFlyParams, () => callback); } removeByIds(ids = []) { if (!!!ids.length) { this.features.forEach(i => i.remove()); this.features = []; } this.getFeaturesByIds(ids).forEach(i => i.remove()) // return this.getFeaturesByIds(ids).forEach(feature => feature.remove()) } getFeaturesByIds(ids) { return this.features.filter(feature => ids.includes(feature.newfiberId)); } setFeaturesVisibleByIds(ids, visible = true) { this.getFeaturesByIds(ids).forEach(feature => feature[['hide', 'show'][Number(visible)]]()) } setFitViewByFeatures(feature = null, options = null) { // this.map.flyTo(feature); this.map.setFitView(feature, options); } dynamicLine(geojson) { this.runLineLayer = new this.virtualSpaceObj.RunLine({ VirtualSpace: this.virtualSpaceObj }); this.runLineLayer.addLine(geojson.features.map((feature, index) => { let lngLats = turf.coordAll(feature); return { id: index, image: 'https://lkimgyt.luokuang.com/1655260316814.png', height: 0, from: gcoord.transform(lngLats[0], gcoord.WGS1984, gcoord.AMap), to: gcoord.transform(lngLats[1], gcoord.WGS1984, gcoord.AMap), speed: 2, width: 10, } }), e => { console.log('飞线添加完成', e); }) } initImageLayers(urls, bounds) { let self = this; if (!!!self.imageLayers.length) self.imageLayers.forEach(layer => layer.remove()); self.imageLayers.length = 0; self.imageLayers = urls.map(url => { let imageLayer = new LKMap.ImageLayer({ url, bounds: new LKMap.Bounds(...bounds), // 设置图片覆盖的范围 opacity: 1, // 设置图层透明度 }); imageLayer.setMap(self.map); return imageLayer; }); } startPlayImageLayers() { let self = this; let step = 0; const alphaStep = 0.01; let arrTileLayer = self.imageLayers; function changeRadarAlpha(time) { if (step > arrTileLayer.length - 1) { step = 0; arrTileLayer[arrTileLayer.length - 1].setOptions({ opacity: 0 }); // arrTileLayer[arrTileLayer.length - 1].alpha = 0 } const layer1 = arrTileLayer[step] const layer2 = arrTileLayer[step + 1] if (!layer1 || !layer2) return; layer1.setOptions({ opacity: 1 }); layer2.setOptions({ opacity: 0 }); clearInterval(self.timer) self.timer = window.setInterval(function () { let opacity1 = layer1.getOptions().opacity; let opacity2 = layer2.getOptions().opacity; opacity1 -= alphaStep; opacity2 += alphaStep; layer2.setOptions({ opacity: opacity1 }); layer2.setOptions({ opacity: opacity2 }); if (opacity1 < alphaStep) { layer1.alpha = 0; layer2.setOptions({ opacity: 0 }); step++; changeRadarAlpha(time); } }, time * 1000 * alphaStep) } changeRadarAlpha(1) } initCanvasLayer(id, bounds) { if (!!this.canvasLayers.length) this.canvasLayers.forEach(i => i.remove()); this.canvasLayers.length = 0; let canvasLayerObj = new LKMap.CanvasLayer({ canvasId: id, bounds: new LKMap.Bounds(...bounds), }); canvasLayerObj.setMap(this.map); this.canvasLayers.push(canvasLayerObj); } static randomRgb() {//rgb颜色随机 const r = Math.floor(Math.random() * 256); const g = Math.floor(Math.random() * 256); const b = Math.floor(Math.random() * 256); return `rgba(${r},${g},${b},0.5)`; } static loadAllImages(imgUrls) { var _load = function (imgUrl) { //创建img标签 var img = new Image(); img.src = imgUrl; //跨域选项 img.setAttribute("crossOrigin", 'Anonymous'); return new Promise((resolve, reject) => { //文件加载完毕 img.onload = function () { resolve(img); }; }); } var _loadAll = function (imgUrls) { var loadedImageUrls=[]; for(var i=0,len=imgUrls.length;i<len;i++){ loadedImageUrls.push(_load(imgUrls[i])); } return loadedImageUrls; } return Promise.all(_loadAll(imgUrls)) } canvasImageToMap (data){ let images = []; Object.keys(data).forEach(key => { let canvasLayerObj = new LKMap.CanvasLayer({ canvasId: `${key}_canvas`, bounds: new LKMap.Bounds(...(data[key].bounds)), }); canvasLayerObj.setMap(AllData.maps[key].map); images = images.concat(data[key].urls); AllData.maps[key].map.setBounds(new LKMap.Bounds(...(data[key].bounds))); }); let index = 0; NewFiberMapUtils.loadAllImages(images).then(res => { let imagess = _.chunk(res,res.length / 2); let keys = Object.keys(AllData.remouldData); let canvass = keys.map((key,index) => { let canvas = document.getElementById( `${key}_canvas`); canvas.width = data[key].wh[0]; canvas.height = data[key].wh[1]; return canvas; }); let contexts = canvass.map(canvas => canvas.getContext("2d")); if(AllData.interval) clearInterval(AllData.interval); AllData.interval = setInterval(()=>{ index ++; if(index == imagess[0].length) index = 0; contexts.forEach((context,idx) => { let w = canvass[idx].width; let h = canvass[idx].height; canvass[idx].width = w; canvass[idx].height = h; context.drawImage(imagess[idx][index],0,0,data[keys[idx]].wh[0],data[keys[idx]].wh[1]); }) },1000) }) } }