You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

161 lines
4.8 KiB

<script setup>
import { onMounted } from 'vue';
import mapbox from 'mapbox-gl';
import config, { mapStyles } from '@/config/map';
import commonRefs from '@/utils/commonRefs';
import mapHelper from '@/core/mapHelper';
import 'mapbox-gl/dist/mapbox-gl.css';
import MultifunctionalBar from '@/layout/components/MultifunctionalBar.vue';
import ZoomBar from '@/layout/components/ZoomBar.vue';
let map;
// 添加一个关键图层
// 添加在所有label层之前,那么不想挡住label层的图层就可以添加到此图层之前
function addKeyLayer() {
if (!map.getLayer('keyLayer')) {
const { layers } = map.getStyle();
// 找到第一个label图层
const { id: layerId } = (layers || []).find(({ id }) => id.endsWith('-label')) || {};
map.addLayer({
id: 'keyLayer',
type: 'background',
layout: {
visibility: 'none',
},
}, layerId || null);
}
}
// 切换语言
function switchMapLanguage() {
[
'country-label',
'state-label',
'settlement-label',
'settlement-subdivision-label',
'road-label',
'poi-label',
'transit-label',
'airport-label',
'waterway-label',
'natural-line-label',
'natural-point-label',
'water-line-label',
'water-point-label',
].forEach((layerId) => {
if (!map) return;
const layer = map.getLayer(layerId);
if (!layer) return;
map.setLayoutProperty(layerId, 'text-field', [
'coalesce',
// 匹配iso_3166_1的值是CN的话,返回'name_zh',否则返回'name_zh-Hans'
['get', ['match', ['get', 'iso_3166_1'], 'CN', 'name_zh', 'name_zh-Hans']],
['get', 'name'],
]);
});
}
// 中国边界
function showChinaBoundary(worldview = 'CN') {
if (map.getLayer('admin-0-boundary-disputed')) {
map.setFilter('admin-0-boundary-disputed', [
'all',
['==', ['get', 'disputed'], 'true'],
['==', ['get', 'admin_level'], 0],
['==', ['get', 'maritime'], 'false'],
['match', ['get', 'worldview'], ['all', worldview], true, false],
]);
}
if (map.getLayer('admin-0-boundary')) {
map.setFilter('admin-0-boundary', [
'all',
['==', ['get', 'admin_level'], 0],
['==', ['get', 'disputed'], 'false'],
['==', ['get', 'maritime'], 'false'],
['match', ['get', 'worldview'], ['all', worldview], true, false],
]);
}
if (map.getLayer('admin-0-boundary-bg')) {
map.setFilter('admin-0-boundary-bg', [
'all',
['==', ['get', 'admin_level'], 0],
['==', ['get', 'maritime'], 'false'],
['match', ['get', 'worldview'], ['all', worldview], true, false],
]);
}
}
function initMap() {
const { accessToken, center, zoom } = config;
mapbox.accessToken = accessToken;
map = new mapbox.Map({
container: 'map',
style: mapStyles.satelliteStreetMap,
center,
zoom,
minZoom: 3,
maxZoom: 23,
dragRotate: false,
// antialias: true,
preserveDrawingBuffer: true,
});
map.on('styledata', () => {
addKeyLayer();
switchMapLanguage();
showChinaBoundary();
});
map.on('style.load', () => {
commonRefs.setRef('map', map);
mapHelper.setMap(map);
});
map.on('load', () => {
});
map.on('error', (e) => {
console.log(e);
});
}
onMounted(() => {
initMap();
});
</script>
<template>
<div :class="s.root" id="map">
<div class="tool-bar">
<ZoomBar class="tool" />
<MultifunctionalBar class="tool" />
</div>
</div>
</template>
<style lang="less" module="s">
.root {
position: absolute;
left: 0;
top: 0;
z-index: 0;
width: 100%;
height: 100%;
background-color: #2f4f4f;
:global {
.tool-bar {
position: absolute;
top: 50%;
right: var(--td-comp-margin-m);
transform: translateY(-50%);
display: grid;
justify-content: center;
gap: var(--td-comp-margin-l);
}
}
}
</style>