Commit 6cdc86e2 authored by daniel's avatar daniel

feat(map): 添加地图搜索功能

parent 09afcc3b
......@@ -30,6 +30,12 @@
<link href="https://api.mapbox.com/mapbox-gl-js/v3.3.0/mapbox-gl.css" rel="stylesheet">
<!-- 添加Mapbox GL JS -->
<script src="https://api.mapbox.com/mapbox-gl-js/v3.3.0/mapbox-gl.js"></script>
<!-- 添加Mapbox GL Geocoder JS -->
<script
src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.1-dev/mapbox-gl-geocoder.min.js"></script>
<link rel="stylesheet"
href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.1-dev/mapbox-gl-geocoder.css"
type="text/css" />
<!-- Favicon-->
<link rel="shortcut icon" href="https://img.geexek.com/files/home/favicon.ico">
<!-- 自定义css -->
......@@ -61,6 +67,12 @@
[v-cloak] {
display: none;
}
/* 下移 50px,右移 10px(可根据需要调整) */
.mapboxgl-ctrl-top-left .mapboxgl-ctrl-geocoder {
margin-top: 90px;
/* margin-left: 10px; */
}
</style>
</head>
......@@ -81,7 +93,7 @@
<script type="text/x-template" id="my-app">
<div style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; margin: 0; padding: 0;">
<div id="map" style="width: 100%; height: 100%;z-index: 0;"></div>
<div class="fixed left-0 top-0 z-10 flex flex-row justify-center items-center p-3">
<div class="fixed left-0 top-0 z-10 flex flex-col justify-center items-start gap-y-2 p-3">
<!-- <input
type="file"
accept=".gpx,.kml"
......@@ -105,6 +117,14 @@
<n-button @click="onBack" type="primary">
返回
</n-button>
<n-switch v-model:value="isSatelliteLayer" @update:value="toggleMapLayer" >
<template #checked>
卫星地图
</template>
<template #unchecked>
普通地图
</template>
</n-switch>
</div>
<div class="fixed right-3 top-0 z-10 p-3 flex flex-col gap-y-1">
<div class="flex flex-row items-center mb-2 w-full gap-x-1 bg-white p-2 rounded-sm">
......@@ -483,68 +503,34 @@
color: "#7367F0"
},
};
// 获取天地图的地址
const getTDTUrls = () => {
const getTDTUrls = (type = 'satellite') => {
const services = Array.from({ length: 7 }, (_, i) => i + 1);
const baseUrl = 'https://t%s.tianditu.gov.cn';
const generateUrls = (path) => {
return services.map((v) => baseUrl.replace('%s', v.toString()) + path);
};
// 天地图卫星影像服务地址
// ===== 普通矢量图层(非卫星) =====
const normalPath = "/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=" + tk;
const TDTNormalUrls = generateUrls(normalPath);
// ===== 卫星图层 =====
const satellitePath = "/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=" + tk;
const TDTSatelliteUrls = generateUrls(satellitePath);
// 获取原始地图数据集合
const dataServerPath = "/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=" + tk;
const TDTDataServerUrls = generateUrls(dataServerPath);
// 天地图注记服务地址
// ===== 注记层(通用) =====
const annotationPath = "/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=" + tk;
const TDTAnnotationUrls = generateUrls(annotationPath);
return {
TDTNormalUrls,
TDTSatelliteUrls,
TDTDataServerUrls,
TDTAnnotationUrls,
};
}
// mapbox的字体
const glyphs = 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf';
// 获取地址
const { TDTDataServerUrls, TDTAnnotationUrls, TDTSatelliteUrls } =
getTDTUrls();
// 构建样式
const defaultStyle = {
version: 8,
sources: {
tianmap: {
type: 'raster',
tiles: TDTSatelliteUrls,
tileSize: 256,
attribution: '天地图影像图',
},
// 添加注记图层的数据源
tianmapAnnotation: {
type: 'raster',
tiles: TDTAnnotationUrls,
tileSize: 256,
attribution: '天地图注记图层',
},
},
layers: [
{
id: 'tianmap-layer',
type: 'raster',
source: 'tianmap',
},
{
id: 'tianmap-annotation-layer',
type: 'raster',
source: 'tianmapAnnotation',
},
],
// 添加 glyphs 属性到地图样式
glyphs,
};
// 获取url参数
const getQueryParams = () => {
......@@ -556,9 +542,10 @@
return params;
}
const urlParams = getQueryParams()
</script>
<script>
const { createApp, defineComponent, ref, onMounted, reactive } = Vue;
const { createApp, defineComponent, ref, onMounted, reactive, computed } = Vue;
const { useMessage, useNotification, dateZhCN, zhCN } = naive
const MyApp = defineComponent({
name: 'MyApp',
......@@ -567,10 +554,75 @@
const loading = ref(false)
const message = useMessage()
const notification = useNotification()
onMounted(() => {
fetchData()
// 是否是卫星地图图层
const isSatelliteLayer = ref(true)
// 获取地址
const { TDTNormalUrls, TDTSatelliteUrls, TDTAnnotationUrls } = getTDTUrls();
// 构建样式
const mapStyle = computed(() => ({
version: 8,
sources: {
tianmap: {
type: 'raster',
tiles: isSatelliteLayer.value ? TDTSatelliteUrls : TDTNormalUrls,
tileSize: 256,
attribution: isSatelliteLayer.value ? '天地图卫星影像图' : '天地图矢量图',
},
tianmapAnnotation: {
type: 'raster',
tiles: TDTAnnotationUrls,
tileSize: 256,
attribution: '天地图注记图层',
},
},
layers: [
{
id: 'tianmap-layer',
type: 'raster',
source: 'tianmap',
},
{
id: 'tianmap-annotation-layer',
type: 'raster',
source: 'tianmapAnnotation',
},
],
glyphs,
}));
// 添加搜索输入框
const geocoder = new MapboxGeocoder({
accessToken: mapBoxToken,
mapboxgl: mapboxgl,
placeholder: '输入地点搜索...',
marker: false // 不自动加 marker,可自行控制
});
onMounted(() => {
getCurrentPosition()
.then((position) => {
const { latitude, longitude } = position.coords;
GpsConfig.center = [longitude, latitude]
})
.catch((err) => {
console.warn("⚠️ 定位失败:", err.message);
})
.finally(() => {
console.log("📍 定位流程结束(成功或失败都会执行)");
fetchData()
});
});
// 获取定位信息
function getCurrentPosition(options = { enableHighAccuracy: true, timeout: 10000, maximumAge: 0 }) {
return new Promise((resolve, reject) => {
if (!navigator.geolocation) {
reject(new Error("浏览器不支持地理定位"));
return;
}
navigator.geolocation.getCurrentPosition(resolve, reject, options);
});
}
// 发起请求获取数据
const fetchData = async () => {
loading.value = true
let params = {
......@@ -600,6 +652,11 @@
/**------------------------ 地图初始化 start ------------------------**/
// 地图对象
let map = ref(null);
// 监听选中事件
geocoder.on('result', (e) => {
const { center, place_name } = e.result;
console.log('选中地点:', place_name, center);
});
// 初始化地图
const initMap = () => {
// 确保容器已完全渲染
......@@ -608,7 +665,7 @@
if (!map.value) {
map.value = new mapboxgl.Map({
container: 'map',
style: defaultStyle,
style: mapStyle.value,
container: 'map',
center: GpsConfig.map.center,
zoom: GpsConfig.map.zoom,
......@@ -946,6 +1003,8 @@
if (!map.value) return;
// 添加比例尺控件到地图
map.value.addControl(new mapboxgl.ScaleControl(), 'bottom-right');
// 将搜索框添加到地图
map.value.addControl(geocoder, 'top-left');
};
/**
......@@ -1347,6 +1406,10 @@
// 回退
window.history.back()
}
// 切换底图
const toggleMapLayer = () => {
map.value.setStyle(mapStyle.value);
};
/**------------------------ marker end ------------------------**/
// 对外返回的信息
return {
......@@ -1371,6 +1434,8 @@
isAddMode,
fileList,
onBack,
isSatelliteLayer,
toggleMapLayer,
uploadUrl,
uploadFinish
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment