<template> <div class="mapPage"> <div id="cesiumContainer"></div> </div> </template> <script> import { reactive, toRefs, onBeforeMount, onMounted, nextTick, onBeforeUnmount } from 'vue'; import bus from '@/bus'; import axios from 'axios'; import buildingGeojson from '@/assets/yanAnBuilding.json'; import yanAnRoad from '@/assets/yanAnRoad.json'; import yanAnWater from '@/assets/yanAnWater.json'; import building_icon from '@/assets/newImgs/building_icon.png'; import building_wall from '@/assets/newImgs/building_wall.png'; import building_wall1 from '@/assets/newImgs/g_1_w_8.png'; import yanAn_ShequArea from '@/assets/yanAn_ShequArea.json'; import yanAn_ShequArea_label from '@/assets/yanAn_ShequArea_label.json'; export default { components: {}, props: { initJson: { type: String, default: () => '/static/libs/mapbox/style/floodOneMap.json', }, loadCallback: { type: Function, default: () => function () {}, }, }, setup(props, event) { const allData = reactive({ layerIds: [], }); let geojson = { point: { type: 'FeatureCollection', features: [] }, polygon: { type: 'FeatureCollection', features: [] }, linestring: { type: 'FeatureCollection', features: [] }, }; let map = null; let config = null; let highlightLayers = { highlight_point: 1, highlight_polygon: 1, highlight_linestring: 1, }; const initeMap = async () => { config = (await axios.get(props.initJson)).data; const { basemap } = config.params; const { style, localStyle } = config.params.init; let styleJson = ( await axios.get( localStyle ? localStyle : (style.includes('http') ? '' : location.origin + basemap) + config.params.init.style ) ).data; styleJson.glyphs = styleJson.glyphs.includes('http') ? styleJson.glyphs : location.origin + styleJson.glyphs; styleJson.sprite = styleJson.sprite.includes('http') ? styleJson.sprite : location.origin + styleJson.sprite; window.newfiberMapbox = new mapboxL7.Scene({ id: 'cesiumContainer', map: new mapboxL7.Mapbox({ style: styleJson, // style: localStyle?localStyle:(style.includes('http')?'':location.origin + config.params.basemap) + config.params.init.style, center: config.params.init.center, zoom: config.params.init.zoom, }), }); map = newfiberMapbox.map; map.ogcLayers = []; map.setMaxZoom(18); newfiberMapbox.unLoadLayers = []; map.on('load', async () => { const mouseLocation = new mapboxL7.MouseLocation({ transform: position => { return position; }, }); newfiberMapbox.addControl(mouseLocation); let { sprites, l7 } = config.params; (sprites || []).forEach(url => map.style._loadSprite(url.includes('http') ? url : window.location.origin.split('#')[0] + url) ); ((l7 || []).images || []).forEach(item => newfiberMapbox.addImage( item.name, item.url.includes('http') ? item.url : window.location.origin.split('#')[0] + item.url ) ); addYanAnBuilding(); addYanAnRiverFlow(); // addYanAnRoad(); await getGeoJSON(); await loadData(); props.loadCallback && props.loadCallback(); // getLayerIdByClick(); newfiberMapbox.getLayers().filter(i => highlightLayers[i.newfiberId] && (highlightLayers[i.newfiberId] = i)); let timeout = setTimeout(() => { let { pitch, center } = config.params.init; pitch && newfiberMapbox.map.setPitch(pitch); center && newfiberMapbox.map.setCenter(center); (config.orders || []).forEach(item => setLayerOrder(...item)); clearTimeout(timeout); }, 1000); // three(); // getLayerIdByClick(); }); let layerIds = (config.mapbox || []).map(i => i.id); map.on('click', e => { Object.values(highlightLayers).forEach(layer => { if (layer.setData) layer.setData({ type: 'FeatureCollection', features: [] }); }); const feature = ( map.queryRenderedFeatures([ [e.point.x - 10 / 2, e.point.y - 10 / 2], [e.point.x + 10 / 2, e.point.y + 10 / 2], ]) || [] ).filter(i => layerIds.includes(i.layer.id))[0]; setHighlight(feature); event.emit('map-click', Object.values(e.lngLat), (feature || {}).properties, ((feature || {}).layer || {}).id); }); async function getGeoJSON() { config.geojsonMvts = {}; let url = config.mapbox .filter(i => i.mType == 'geojsonMvt') .map(item => { let { mType, columns, geom_column, id, key } = item; let sourceID = geom_column ? key + '_' + (geom_column || '') : key; let params = []; if (columns) params.push(`columns=${columns}`); if (geom_column) params.push(`geom_column=${geom_column}`); return config.params.mvt + `/v1/geojson/${key}?` + params.join('&'); }); url = Array.from(new Set(url)); let fetchs = url.map(url => axios.get(url)); let results = await Promise.all(fetchs); url.forEach((url, index) => (config.geojsonMvts[url] = results[index].data)); } }; const loadData = async () => { let { mapbox, l7, ogc } = config; if (mapbox) initMapBoxLayer(); if (l7) l7.forEach(item => { let { id, columns, filter } = item; let params = []; if (columns) params.push(`columns=${columns}`); if (filter) params.push(`filter=${filter}`); id ? axios .get(config.params.mvt + `/v1/geojson/${id}?` + params.join('&')) .then(({ data: geojson }) => initMapBoxL7Class(item, geojson)) : initMapBoxL7Class(item, geojson[item.key] || turf.featureCollection([])); }); if (ogc) ogc.forEach(item => { let { id, type, params, methods } = item; Object.keys(params).forEach( i => (params[i] = typeof params[i] == 'string' ? (params[i].includes('||') ? eval(params[i]) : params[i]) : params[i]) ); let layer = new mapboxgl1[type](params); layer.newfiberId = id; methods.forEach(method => { let ms = method.params.map(i => (typeof i == 'string' ? (i.includes('||') ? eval(i) : i) : i)); layer[method.name](...ms); }); map.ogcLayers.push(layer); }); function initMapBoxL7Class({ type, params, methods, id, show, key }, geojson) { let layer = new mapboxL7[type](params).source(geojson); methods.forEach(method => { let ms = method.params.map(i => (typeof i == 'string' ? (i.includes('||') ? eval(i) : i) : i)); layer[method.name](...ms); }); layer.newfiberId = key; if (!show) return newfiberMapbox.unLoadLayers.push(layer); newfiberMapbox.addLayer(layer); allData.layerIds.push(key); } function initMapBoxLayer() { mapbox.forEach(item => { let { mType, columns, geom_column, id, key } = item; let sourceID = geom_column ? key + '_' + (geom_column || '') : key; let params = []; if (columns) params.push(`columns=${columns}`); if (geom_column) params.push(`geom_column=${geom_column}`); if (!!!map.getSource(sourceID)) { let flag = mType == 'geojson'; if (id == 'yanAn_ShequArea' || id == 'yanAn_ShequArea_line') { map.addSource(sourceID, { type: 'geojson', data: yanAn_ShequArea, }); } else if (id == 'yanAn_ShequArea_label') { map.addSource(sourceID, { type: 'geojson', data: yanAn_ShequArea_label, }); } else { flag ? map.addSource(sourceID, { type: mType, data: geojson[key] }) : map.addSource(sourceID, { ...(mType == 'mvt' ? { type: 'vector', tiles: [config.params.mvt + `/v1/${mType}/${key}/{z}/{x}/{y}?` + params.join('&')], tileSize: 512, scheme: 'xyz', maxzoom: 14, minzoom: 1, } : { type: 'geojson', data: config.geojsonMvts[config.params.mvt + `/v1/geojson/${key}?` + params.join('&')], }), }); } } map.addLayer({ ...item, source: sourceID }); map.moveLayer(id, undefined); allData.layerIds.push(id); }); } }; const setLayerVisible = ({ layername, isCheck, values = [] }) => { if (!!!layername) return; if (((config || {}).filter || [])[layername]) { config.filter[layername].layerName.forEach((name, index) => { let layer = newfiberMapbox.getLayers().filter(i => i.newfiberId == name)[0]; let fValues = config.filter[layername].filter[index]; if (layer) { let geojson = layer.getSource().originData; geojson.features.forEach(i => fValues.includes(i.properties.type) && (i.properties.visible = isCheck)); layer.setData(geojson); } if (map.getLayer(name)) { fValues = fValues.filter(Boolean); let filter = map.getFilter(name); if (!fValues.length) fValues = values; if (filter[0] == 'in') { isCheck ? filter.push(...fValues) : (filter = filter.filter(i => !fValues.includes(i))); } else { let _filter = filter[filter.length - 1][filter[filter.length - 1].length - 1][ filter[filter.length - 1][filter[filter.length - 1].length - 1].length - 1 ]; isCheck ? filter[filter.length - 1][filter[filter.length - 1].length - 1][ filter[filter.length - 1][filter[filter.length - 1].length - 1].length - 1 ].push(...fValues) : (filter[filter.length - 1][filter[filter.length - 1].length - 1][ filter[filter.length - 1][filter[filter.length - 1].length - 1].length - 1 ] = _filter.filter(i => !fValues.includes(i))); } map.setFilter(name, filter); } }); return config.filter[layername].easeTo && isCheck && map.easeTo(config.filter[layername].easeTo); } let features = Object.values(geojson) .map(i => i.features) .flat(Infinity) .filter(i => i.properties.type == layername); if (features.length) { let types = Array.from(new Set(features.map(i => i.geometry.type.toLocaleLowerCase()))); types.forEach(type1 => { let filter = map.getFilter(type1); if (filter[0] == 'in') { isCheck ? filter.push(layername) : (filter = filter.filter(i => i != layername)); } else { let _filter = filter[filter.length - 1][filter[filter.length - 1].length - 1][ filter[filter.length - 1][filter[filter.length - 1].length - 1].length - 1 ]; isCheck ? filter[filter.length - 1][filter[filter.length - 1].length - 1][ filter[filter.length - 1][filter[filter.length - 1].length - 1].length - 1 ].push(layername) : (filter[filter.length - 1][filter[filter.length - 1].length - 1][ filter[filter.length - 1][filter[filter.length - 1].length - 1].length - 1 ] = _filter.filter(i => i != layername)); } map.setFilter(type1, filter); }); } let layer = newfiberMapbox.getLayers().filter(i => i.newfiberId == layername)[0]; if (!!!layer) { layer = newfiberMapbox.unLoadLayers.filter(i => i.newfiberId == layername)[0]; isCheck && layer && newfiberMapbox.addLayer(layer); } layer && layer[['hide', 'show'][Number(isCheck)]](); layer = map.getLayer(layername); layer && map.setLayoutProperty(layername, 'visibility', isCheck ? 'visible' : 'none'); layer = map.getLayer(layername + '_text'); layer && map.setLayoutProperty(layername + '_text', 'visibility', isCheck ? 'visible' : 'none'); layer = map.ogcLayers.filter(i => i.id == layername)[0]; layer && (layer.map ? layer[isCheck ? 'show' : 'hide']() : layer.addTo(map)); }; const getGeojsonByType = ({ type, callback }) => { let geojs = turf.featureCollection( Object.values(geojson) .map(i => i.features) .flat(Infinity) .filter(i => i.properties.type == type) ); callback && callback(geojs); }; const removeLayers = ids => { let { getLayers, removeAllLayer, removeLayer: removeLayerL7 } = newfiberMapbox; let { getLayer, removeLayer } = map; if (!!!ids) { allData.layerIds.forEach(id => getLayer(id) && removeLayer(id)); return removeAllLayer(); } ids.forEach(id => { getLayer(id) && removeLayer(id); getLayers().forEach(layer => layer.newfiberId == id && removeLayerL7(layer)); }); }; const removeMapDatas = types => { !!!types ? Object.keys(geojson).forEach(key => (geojson[key].features.length = 0)) : Object.keys(geojson).forEach( key => (geojson[key].features = geojson[key].features.filter(feature => !types.includes(feature.properties.type))) ); return refreshGeoJSON(); }; const setLegendData = list => { list.forEach(i => { let points = []; if (!i.data) return; i.data.features.forEach(a => { if (!!!a || !!!a.properties) return; (a.properties.minzoom = a.properties.minzoom || 0), (a.properties.color = a.properties.color || 'rgba(0,0,0,1)'), (a.properties.type = a.properties.type || i.layername); a.properties.name = a.properties.name || a.properties.Name || a.properties.stName || a.properties.pointNumber || a.properties.sewageName || a.properties.sectionName || a.properties.pumpName; if (a.properties.name && !turf.getType(a).toLocaleLowerCase().includes('point')) { let center = turf.pointOnFeature(a); center.properties = { ...a.properties, minzoom: 10 }; center.properties.geometry = Terraformer.WKT.convert(center.geometry); points.push(center); } }); i.data.features = i.data.features.concat(points); }); let types = {}; list .map(i => i.data && i.data.features) .filter(Boolean) .flat(Infinity) .forEach(feature => { if (!!!feature || !!!feature.properties) return; feature.properties.geometry = Terraformer.WKT.convert(feature.geometry); let type = feature.geometry.type.toLocaleLowerCase(); let flag = type.includes('multi'); type = type.replaceAll('multi', ''); let features = null; if (flag) features = turf.flatten(feature).features; !!!types[type] && (types[type] = []); types[type].push(...(features ? features : [feature])); }); Object.keys(types).forEach(key => geojson[key].features.push(...types[key])); refreshGeoJSON(); }; const refreshGeoJSON = () => { Object.keys(geojson).forEach(key => map.getSource(key) && map.getSource(key).setData(geojson[key])); map.triggerRepaint(); }; const setGeoJSON = ({ json, key }) => { let layer = newfiberMapbox.getLayers().filter(i => i.newfiberId == key)[0]; console.log('layer----', layer); if (!!!layer) { layer = newfiberMapbox.unLoadLayers.filter(i => i.newfiberId == key)[0]; layer && layer.setData(json); layer && newfiberMapbox.addLayer(layer); } if (layer) return layer.setData(json); setLegendData([{ data: json, layername: key, type: 'point' }]); }; const beansToMap = ({ beans, fields = { geometry: 'geometry', lng: 'lng', lat: 'lat', name: 'name' }, type, isConvert }) => { let geojson = turf.featureCollection( beans .filter(i => i[fields.geometry] || (Boolean(Number(i[fields.lng])) && Boolean(Number(i[fields.lat])))) .map(i => { let feature = null; if (i[fields.geometry]) feature = turf.feature(Terraformer.WKT.parse(i[fields.geometry]), { ...i, name: i[fields.name], }); if (i[fields.lng]) feature = turf.point([i[fields.lng], i[fields.lat]].map(Number), { ...i, name: i[fields.name], }); return feature; }) .filter(Boolean) ); isConvert && (geojson = gcoord.transform(geojson, gcoord.AMap, gcoord.WGS84)); setGeoJSON({ json: geojson, key: type }); }; const setHighlight = (features = {}) => { let array = {}; features = features.forEach ? features : [features]; Object.values(highlightLayers).forEach( layer => layer.setData && layer.setData({ type: 'FeatureCollection', features: [] }) ); features.forEach(feature => { if (!!!feature || !Boolean(Object.keys(feature).length) || !feature.properties.geometry) return; let geometry = Terraformer.WKT.parse(feature.properties.geometry); let geoFeature = turf.feature(geometry, feature.properties); let type = geometry.type.toLocaleLowerCase().replaceAll('multi', ''); let key = Object.keys(highlightLayers).filter(key => key.lastIndexOf(type) > -1)[0]; if (!array[key]) array[key] = []; array[key].push(geoFeature); }); Object.keys(array).forEach( key => highlightLayers[key] && highlightLayers[key].setData({ type: 'FeatureCollection', features: array[key], }) ); }; const setLayerOrder = (sourceLayer, targetLayer) => { map.moveLayer(sourceLayer, targetLayer); }; const getLayerIdByClick = () => { map.getStyle().layers.forEach(i => map.on('click', i.id, (a, b, c, d) => { console.log('layer-id', a.features[0].layer.id); }) ); }; const updateStyle = styleJson => { styleJson.glyphs = styleJson.glyphs.includes('http') ? styleJson.glyphs : location.origin + styleJson.glyphs; styleJson.sprite = styleJson.sprite.includes('http') ? styleJson.sprite : location.origin + styleJson.sprite; const currentStyle = map.getStyle(); styleJson.sources = Object.assign({}, currentStyle.sources, styleJson.sources); let labelIndex = styleJson.layers.findIndex(el => { return el.id == 'waterway-label'; }); if (labelIndex === -1) { labelIndex = styleJson.layers.length; } const appLayers = currentStyle.layers.filter(el => { return el.source && el.source != 'mapbox://mapbox.satellite' && el.source != 'mapbox' && el.source != 'composite'; }); styleJson.layers = [...styleJson.layers.slice(0, labelIndex), ...appLayers, ...styleJson.layers.slice(labelIndex, -1)]; map.setStyle(styleJson); }; //添加延安建筑白膜 const addYanAnBuilding = () => { map.loadImage(building_icon, (error, image) => { if (error) throw error; // Add the image to the map style. map.addImage('buildingLayer', image); map.addSource('buildingSource', { type: 'geojson', data: buildingGeojson, }); map.addLayer({ id: 'buildingLayer-top', type: 'fill-extrusion', source: 'buildingSource', // //绘画功能 paint: { 'fill-extrusion-color': 'rgba(210, 210, 210,1)', 'fill-extrusion-height': ['+', ['get', 'height_3'], 0.1], 'fill-extrusion-base': ['get', 'height_3'], 'fill-extrusion-opacity': 1, }, }); map.addLayer({ id: 'buildingLayer', type: 'fill-extrusion', source: 'buildingSource', // //绘画功能 paint: { 'fill-extrusion-pattern': 'buildingLayer', 'fill-extrusion-color': '#ffffff', 'fill-extrusion-height': ['get', 'height_3'], 'fill-extrusion-base': 0, 'fill-extrusion-opacity': 1, }, }); }); }; //添加延安水系 const addYanAnRiverFlow = () => { let layer = new mapboxL7.LineLayer({ name: 'waterLake', }) .source(yanAnWater) .size(4) .shape('line') .texture('arrow') .color('aqua') .animate({ interval: 2, // 间隔 duration: 3, // 持续时间,延时 trailLength: 3, // 流线长度 }) .style({ opacity: 0.8, lineTexture: true, // 开启线的贴图功能 iconStep: 200, // 设置贴图纹理的间距 borderWidth: 0.4, // 默认文 0,最大有效值为 0.5 borderColor: '#fff', // 默认为 #ccc }); newfiberMapbox.addLayer(layer); }; //添加延安路网 const addYanAnRoad = () => { let layer = new mapboxL7.LineLayer({ name: 'dynamicRoad', }) .source(yanAnRoad) .size(1.3) .shape('line') .color('rgb(184, 184, 184)') .animate({ interval: 1, // 间隔 duration: 1.5, // 持续时间,延时 trailLength: 2, // 流线长度 }) .style({ opacity: 0.6, }); newfiberMapbox.addLayer(layer); }; onMounted(() => { initeMap(); bus.on('beansToMap', beansToMap); bus.on('setLayerVisible', setLayerVisible); bus.on('setLegendData', setLegendData); bus.on('setGeoJSON', setGeoJSON); bus.on('getGeojsonByType', getGeojsonByType); bus.on('removeLayers', removeLayers); bus.on('removeMapDatas', removeMapDatas); bus.on('setHighlight', setHighlight); bus.on('updateStyle', updateStyle); }); onBeforeUnmount(() => { bus.off('beansToMap'); bus.off('setLayerVisible'); bus.off('setLegendData'); bus.off('setGeoJSON'); bus.off('getGeojsonByType'); bus.off('removeMapDatas'); bus.off('setHighlight'); bus.off('updateStyle'); if (newfiberMapbox) { newfiberMapbox.destroy(); newfiberMapbox = null; } }); return { ...toRefs(allData), }; }, }; </script> <style> .mapPage { width: 100%; height: 100%; position: absolute; left: 0px; top: 0px; z-index: 0; background: lavender; } #cesiumContainer { width: 100%; height: 100%; position: absolute; } .l7-control-mouse-location { background: none; } .l7-control-mouse-location { color: #ffffff; } </style>