<template> <div class="mapPage"> <div id="mapboxContainer"></div> </div> </template> <script> import { reactive, toRefs, onBeforeMount, onMounted, nextTick, onBeforeUnmount } from 'vue'; import bus from '@/bus'; import axios from 'axios'; import xiaoganWater from '@/assets/geojson/xiaoganWater.json'; import xiaoganWaterLabel1 from '@/assets/geojson/xiaoganWaterLabel1.json'; import xiaoganWaterLabel2 from '@/assets/geojson/xiaoganWaterLabel2.json'; import xiaoganWaterLabel3 from '@/assets/geojson/xiaoganWaterLabel3.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_point1: 1, highlight_polygon: 1, highlight_linestring: 1, }; const initeMap = async () => { config = (await axios.get(props.initJson)).data; let { sprites, l7 } = config.params; window.newfiberMapbox = new mapboxL7.Scene({ id: 'mapboxContainer', map: new mapboxL7.Mapbox({ style: config.params.init.style, center: config.params.init.center, zoom: config.params.init.zoom, }), }); newfiberMapbox.map.load = false; map = newfiberMapbox.map; map.ogcLayers = []; newfiberMapbox.unLoadLayers = []; (sprites || []).forEach(url => { map.style._loadSprite(url.includes('http') ? url : window.location.href.split('#')[0] + url); }); ((l7 || []).images || []).forEach(item => newfiberMapbox.addImage(item.name, item.url.includes('http') ? item.url : window.location.href.split('#')[0] + item.url) ); setTimeout(() => { map.on('load', async () => { const mouseLocation = new mapboxL7.MouseLocation({ transform: position => { return [position[0].toFixed(6), position[1].toFixed(6)]; }, }); newfiberMapbox.addControl(mouseLocation); console.log('spritesspritessprites', sprites); !!!map.getSource('xiaoganWater') && map.addSource('xiaoganWater', { type: 'geojson', data: xiaoganWater }); !!!map.getLayer('xiaoganWater') && map.addLayer({ id: 'xiaoganWater', type: 'fill', source: 'xiaoganWater', paint: { 'fill-color': '#0c3b7a', }, }); addWaterLabel(); await loadData(); // map.on('styleimagemissing', e => { // console.log('styleimagemissing', e); // (sprites || []).forEach(url => { // map.style._loadSprite(url.includes('http') ? url : window.location.href.split('#')[0] + url); // }); // let pointLayput = config.mapbox.filter(item => item.id == 'point'); // console.log('pointLayput', pointLayput[0]['layout']['icon-image']); // setTimeout(() => { // map.setLayoutProperty('point', 'icon-image', pointLayput[0]['layout']['icon-image']); // }, 1000); // }); props.loadCallback && props.loadCallback(); // getLayerIdByClick(); (config.orders || []).forEach(item => setLayerOrder(...item)); 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); clearTimeout(timeout); }, 2000); newfiberMapbox.map.load = true; }); }, 200); 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]; if (feature) event.emit('map-click', Object.values(e.lngLat), feature.properties); setHighlight(feature); }); }; const loadData = async () => { let { mapbox, l7, ogc } = config; if (mapbox) //用mapbox添加水系 //axios.get(config.params.mvt + `/v1/geojson/hubei_xiaogan_water1`).then(({ data: geojson }) => { // }); mapbox.forEach(item => { let { mType, columns } = item; let params = ''; if (columns) params = `?columns=${columns}`; if (!!!map.getSource(item.id)) { let flag = mType == 'geojson'; flag ? map.addSource(item.id, { type: mType, data: geojson[item.id], }) : map.addSource(item.id, { type: 'vector', tiles: [config.params.mvt + `/v1/${mType}/${item.key}/{z}/{x}/{y}` + params], tileSize: 512, scheme: 'xyz', maxzoom: 14, minzoom: 1, }); } map.addLayer({ ...item, source: item.id }); map.moveLayer(item.id, undefined); allData.layerIds.push(item.id); }); if (l7) { if (!!!l7.length) return; l7.forEach(item => { let { id, columns, filter } = item; let params = ''; if (columns) params += `columns=${columns}&`; if (filter) params += `filter=${filter}&`; id ? axios.get(config.params.mvt + `/v1/geojson/${id}?` + params).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); } }; const setLayerVisible = ({ layername, isCheck }) => { if (!!!window.newfiberMapbox) return; if (((config || {}).filter || {})[layername]) { config.filter[layername].layerName.forEach((name, index) => { let filter = map.getFilter(name); let fValues = config.filter[layername].filter[index]; isCheck ? filter.push(...fValues) : (filter = 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) return; isCheck ? filter.push(layername) : (filter = 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, '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 => i.data && i.data.features.forEach(a => { if (!!!a || !!!a.properties) return; a.properties.type = a.properties.type || i.layername; a.properties.name = a.properties.name || a.properties.Name || a.properties.stName || a.properties.roadName || a.properties.sewageName || a.properties.sectionName || a.properties.pumpName || a.properties.projectName; }) ); 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])); }; const setGeoJSON = ({ json, key }) => { // geojson[key] = json; let layer = newfiberMapbox.getLayers().filter(i => i.newfiberId == key)[0]; if (!!!layer) { layer = newfiberMapbox.unLoadLayers.filter(i => i.newfiberId == key)[0]; layer && newfiberMapbox.addLayer(layer); } if (layer) layer.setData(json); setLegendData([{ data: json, layername: key, type: 'point' }]); }; const setLayerOrder = (sourceLayer, targetLayer) => { map.moveLayer(sourceLayer, targetLayer); }; 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 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 addWaterLabel = () => { !!!map.getSource('xiaoganWaterLabel1') && map.addSource('xiaoganWaterLabel1', { type: 'geojson', data: xiaoganWaterLabel1 }); !!!map.getLayer('xiaoganWaterLabel1') && map.addLayer({ id: 'xiaoganWaterLabel1', type: 'symbol', source: 'xiaoganWaterLabel1', layout: { 'text-field': ['get', 'name'], 'text-font': ['KlokanTech Noto Sans Regular'], 'text-transform': 'uppercase', }, paint: { 'text-halo-color': 'rgba(0,0,0,1)', 'text-color': 'rgba(0,167,210,1)', 'icon-opacity': 1, 'text-halo-width': 1, }, }); !!!map.getSource('xiaoganWaterLabel2') && map.addSource('xiaoganWaterLabel2', { type: 'geojson', data: xiaoganWaterLabel2 }); !!!map.getLayer('xiaoganWaterLabel2') && map.addLayer({ id: 'xiaoganWaterLabel2', type: 'symbol', source: 'xiaoganWaterLabel2', layout: { 'symbol-placement': 'line', 'text-field': ['get', 'name'], 'text-font': ['KlokanTech Noto Sans Regular'], 'text-letter-spacing': 0.1, 'text-rotation-alignment': 'map', 'text-size': { base: 1.4, stops: [ [10, 16], [20, 22], ], }, 'text-transform': 'uppercase', }, paint: { 'text-halo-color': 'rgba(0,0,0,1)', 'text-color': 'rgba(0,167,210,1)', 'icon-opacity': 1, 'text-halo-width': 1, }, }); !!!map.getSource('xiaoganWaterLabel3') && map.addSource('xiaoganWaterLabel3', { type: 'geojson', data: xiaoganWaterLabel3 }); !!!map.getLayer('xiaoganWaterLabel3') && map.addLayer({ id: 'xiaoganWaterLabel3', type: 'symbol', source: 'xiaoganWaterLabel3', layout: { 'symbol-placement': 'line', 'text-field': ['get', 'name'], 'text-font': ['KlokanTech Noto Sans Regular'], 'text-letter-spacing': 0.1, 'text-rotation-alignment': 'map', 'text-size': { base: 1.4, stops: [ [10, 16], [20, 22], ], }, 'text-transform': 'uppercase', }, paint: { 'text-halo-color': 'rgba(0,0,0,1)', 'text-color': 'rgba(0,167,210,1)', 'icon-opacity': 1, 'text-halo-width': 1, }, }); }; onMounted(() => { initeMap(); 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); }); onBeforeUnmount(() => { bus.off('setLayerVisible'); bus.off('setLegendData'); bus.off('setGeoJSON'); bus.off('getGeojsonByType'); bus.off('removeMapDatas'); bus.off('setHighlight'); newfiberMapbox.destroy(); newfiberMapbox = null; }); return { ...toRefs(allData), initeMap, }; }, }; </script> <style lang="scss"> .mapPage { width: 100%; height: 100%; position: absolute; left: 0px; top: 0px; z-index: 10; background: lavender; #mapboxContainer { width: 100%; height: 100%; position: absolute; } .l7-control-mouse-location { background: none; } .l7-control-mouse-location { color: #ffffff; } } </style>