测试页面
parent
a7b3afeb64
commit
ca28c0851e
|
@ -8,7 +8,7 @@ pnpm-debug.log*
|
||||||
lerna-debug.log*
|
lerna-debug.log*
|
||||||
|
|
||||||
node_modules
|
node_modules
|
||||||
dist
|
# dist
|
||||||
dist-ssr
|
dist-ssr
|
||||||
*.local
|
*.local
|
||||||
|
|
||||||
|
|
25
README.md
25
README.md
|
@ -1,8 +1,19 @@
|
||||||
##
|
整理
|
||||||
|
|
||||||
// L.tileLayer("http://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}", {
|
# 配置
|
||||||
// attribution: '© ',
|
|
||||||
// maxZoom: 15,
|
useConfig(map) , 类似的全局配置
|
||||||
// minZoom: 10,
|
|
||||||
// subdomains: "1234"
|
# 地图
|
||||||
// }).addTo(map.value)
|
|
||||||
|
useMap(map,options)
|
||||||
|
|
||||||
|
# 图层
|
||||||
|
|
||||||
|
useTileLayer(map,url,options)
|
||||||
|
|
||||||
|
绘制多个底图
|
||||||
|
|
||||||
|
# 绘制图层
|
||||||
|
|
||||||
|
useGeoJSON(map,data)
|
||||||
|
|
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,15 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Vite + Vue + TS</title>
|
||||||
|
<script type="module" crossorigin src="/assets/index-3e0c8030.js"></script>
|
||||||
|
<link rel="stylesheet" href="/assets/index-f637f0ab.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
15
src/App.vue
15
src/App.vue
|
@ -5,9 +5,10 @@ import Mark from './components/mapChild/Mark.vue'
|
||||||
import useMarks, { markType } from './hook/useMarks.ts'
|
import useMarks, { markType } from './hook/useMarks.ts'
|
||||||
import ThemeSwitch from './components/ThemeSwitch.vue'
|
import ThemeSwitch from './components/ThemeSwitch.vue'
|
||||||
import MarkMenu from './components/left/MarkMenu.vue'
|
import MarkMenu from './components/left/MarkMenu.vue'
|
||||||
import CtrlMenu, { DataProps } from './components/left/CtrlMenu.vue'
|
import CtrlMenu from './components/left/CtrlMenu.vue'
|
||||||
import { mdiLanConnect } from '@quasar/extras/mdi-v7'
|
import { mdiLanConnect } from '@quasar/extras/mdi-v7'
|
||||||
import { useWindowSize } from '@vueuse/core';
|
import { useWindowSize } from '@vueuse/core';
|
||||||
|
import { Config } from './hook/useConfig';
|
||||||
|
|
||||||
|
|
||||||
const map = ref<InstanceType<typeof Map>>(); // 获取地图的实例 纂取实例方法
|
const map = ref<InstanceType<typeof Map>>(); // 获取地图的实例 纂取实例方法
|
||||||
|
@ -15,6 +16,7 @@ const marks = useMarks([{ latlng: [39.92647400, 116.40328300], title: '北京故
|
||||||
const tab = ref('mark')
|
const tab = ref('mark')
|
||||||
const sideStyle = ref('20em,logo');
|
const sideStyle = ref('20em,logo');
|
||||||
const { width } = useWindowSize()
|
const { width } = useWindowSize()
|
||||||
|
const mapConfig = ref()
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
sideStyle.value = width.value > 600 ? '20em,logo' : '0em,bar'
|
sideStyle.value = width.value > 600 ? '20em,logo' : '0em,bar'
|
||||||
|
@ -37,21 +39,18 @@ function removeMark(index: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function flytoMark(index: number) {
|
function flytoMark(index: number) {
|
||||||
map.value?.flyTo(marks.value[index].latlng)
|
mapConfig.value.center = marks.value[index].latlng
|
||||||
}
|
}
|
||||||
|
|
||||||
function ctrlMap(e: DataProps) {
|
function ctrlMap(e: Config) {
|
||||||
const { zoom, errorTileUrl, urlTemplate, zoomSnap } = e;
|
mapConfig.value = e
|
||||||
map.value?.changeZoom([zoom.min, zoom.max])
|
|
||||||
map.value?.changeMapUrl(urlTemplate, errorTileUrl)
|
|
||||||
map.value?.changeZoomSnap(zoomSnap)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<h5 class="logo">离线地图</h5>
|
<h5 class="logo">离线地图</h5>
|
||||||
<Map ref="map" v-slot="{ contextmenu }">
|
<Map ref="map" v-slot="{ contextmenu }" v-model="mapConfig">
|
||||||
<q-menu touch-position context-menu>
|
<q-menu touch-position context-menu>
|
||||||
<q-list dense style="min-width: 100px">
|
<q-list dense style="min-width: 100px">
|
||||||
<q-item clickable v-close-popup>
|
<q-item clickable v-close-popup>
|
||||||
|
|
|
@ -1,99 +1,37 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, provide } from 'vue'
|
import { ref, onMounted, provide, watch } from 'vue'
|
||||||
import L from 'leaflet'
|
|
||||||
import 'leaflet/dist/leaflet.css'
|
import 'leaflet/dist/leaflet.css'
|
||||||
import useCrs from '../hook/useCrs.ts'
|
import useMap from '../hook/useMap.ts'
|
||||||
import useZoom from '../hook/useZoom.ts'
|
|
||||||
import { useResizeObserver } from '@vueuse/core'
|
import { useResizeObserver } from '@vueuse/core'
|
||||||
|
import { setOptions } from 'leaflet'
|
||||||
|
|
||||||
const mapContainer = ref()
|
const mapContainer = ref()
|
||||||
const map = ref<L.Map>()
|
const { map, tileLayers, props: mapProps } = useMap(mapContainer, { use: 'gaode', zoom: 13 });
|
||||||
const layers = ref<L.TileLayer[]>([])
|
|
||||||
|
// const config = defineModel<Object>()
|
||||||
|
|
||||||
const slotProps = ref({
|
const slotProps = ref({
|
||||||
contextmenu: {}
|
contextmenu: {}
|
||||||
})
|
})
|
||||||
|
|
||||||
const baiduCrs = useCrs('baiduCrs')
|
|
||||||
const gaodeCrs = useCrs('gaodeCrs')
|
|
||||||
|
|
||||||
const mapFilter = ref('invert(1) grayscale(.2) saturate(0.8) brightness(1.8) opacity(1) hue-rotate(184deg) sepia(17%)'); // 地图滤镜
|
const mapFilter = ref('invert(1) grayscale(.2) saturate(0.8) brightness(1.8) opacity(1) hue-rotate(184deg) sepia(17%)'); // 地图滤镜
|
||||||
|
|
||||||
|
|
||||||
const mapInfo: Record<string, { crs: L.Proj.CRS | L.CRS, url: string, error: string, center: L.LatLngExpression }> = {
|
|
||||||
baidu: {
|
|
||||||
crs: baiduCrs,
|
|
||||||
url: "http://172.20.10.2/baidumaps/roadmap/{z}/{x}/{y}.png",
|
|
||||||
error: 'http://172.20.10.2/baidumaps/roadmap/error.png',
|
|
||||||
center: [39.926474, 116.403283]
|
|
||||||
},
|
|
||||||
gaode: {
|
|
||||||
crs: gaodeCrs,
|
|
||||||
url: "http://172.20.10.2/mapabc/roadmap/{z}/{x}/{y}.png",
|
|
||||||
error: 'http://172.20.10.2/baidumaps/roadmap/error.png',
|
|
||||||
center: [-97.00238024827533, 210.7725501856634]
|
|
||||||
},
|
|
||||||
gaodeLine: {
|
|
||||||
crs: gaodeCrs,
|
|
||||||
url: "http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
|
|
||||||
error: 'http://172.20.10.2/baidumaps/roadmap/error.png',
|
|
||||||
center: [-97.00238024827533, 210.7725501856634]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
provide('map', map) // 注入的内容 mapChild 下
|
provide('map', map) // 注入的内容 mapChild 下
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// const selfZoom = useZoom(mapContainer,map, [3,6,9,14,16,18])
|
map.value?.addEventListener("contextmenu", (e) => {
|
||||||
|
|
||||||
// L.Map.addInitHook('addHandler','scrollWheelZoom', selfZoom)
|
|
||||||
// L.Map.mergeOptions({
|
|
||||||
// scrollWheelZoom:true
|
|
||||||
// })
|
|
||||||
|
|
||||||
const use: keyof typeof mapInfo = 'gaode'
|
|
||||||
|
|
||||||
map.value = L.map(mapContainer.value, {
|
|
||||||
center: mapInfo[use].center,
|
|
||||||
zoom: 13,
|
|
||||||
attributionControl: false,
|
|
||||||
crs: mapInfo[use].crs,
|
|
||||||
zoomControl: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
// const scale= L.control.scale({ maxWidth: 200, metric: true, imperial: true });
|
|
||||||
// map.value.addControl(scale)
|
|
||||||
const layer = L.tileLayer(mapInfo[use].url, {
|
|
||||||
minZoom: 3,
|
|
||||||
maxZoom: 18,
|
|
||||||
tms: true,
|
|
||||||
errorTileUrl: mapInfo[use].error,
|
|
||||||
className: "mapFilter",
|
|
||||||
})
|
|
||||||
|
|
||||||
// map.value.on('zoom', (e) => {
|
|
||||||
// console.log(e.target._animateToZoom)
|
|
||||||
// })
|
|
||||||
|
|
||||||
layers.value?.push(layer)
|
|
||||||
|
|
||||||
layer.addTo(map.value)
|
|
||||||
|
|
||||||
map.value.addEventListener("contextmenu", (e) => {
|
|
||||||
slotProps.value.contextmenu = e
|
slotProps.value.contextmenu = e
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function flyTo(latLng: [number, number]) {
|
|
||||||
map.value?.flyTo(L.latLng(latLng[0], latLng[1]))
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeZoom(zoomSize: [number, number]) {
|
|
||||||
map.value?.setMinZoom(zoomSize[0])
|
watch({ center: mapProps.value.center }, ({ center }) => center && map.value?.flyTo(center))
|
||||||
map.value?.setMaxZoom(zoomSize[1])
|
watch({ max: mapProps.value.maxZoom || 0 }, ({ max }) => map.value?.setMaxZoom(max))
|
||||||
}
|
watch({ min: mapProps.value.minZoom || 0 }, ({ min }) => map.value?.setMaxZoom(min))
|
||||||
|
watch({ url: mapProps.value.urlTemplate }, ({ url }) => url && tileLayers.value[0].setUrl(url))
|
||||||
|
watch({ zoomSnap: mapProps.value.zoomSnap }, ({ zoomSnap }) => map.value && (map.value.options.zoomSnap = zoomSnap))
|
||||||
|
|
||||||
function changeMapFilter(filterInfo: Record<'blur' |
|
function changeMapFilter(filterInfo: Record<'blur' |
|
||||||
'brightness' |
|
'brightness' |
|
||||||
|
@ -108,38 +46,9 @@ function changeMapFilter(filterInfo: Record<'blur' |
|
||||||
mapFilter.value = Object.entries(filterInfo).map(([key, value]) => `${key}(${value})`).join(' ')
|
mapFilter.value = Object.entries(filterInfo).map(([key, value]) => `${key}(${value})`).join(' ')
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeMapUrl(urlTemplate: string, errorTileUrl: string) {
|
|
||||||
if (!layers.value[0]) return;
|
|
||||||
layers.value[0].setUrl(urlTemplate);
|
|
||||||
layers.value[0].options.errorTileUrl = errorTileUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeAnimation(zoomAnimation: boolean, fadeAnimation: boolean) {
|
|
||||||
if (!map.value) return;
|
|
||||||
map.value.options.zoomAnimation = zoomAnimation
|
|
||||||
map.value.options.fadeAnimation = fadeAnimation
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function changeZoomSnap(zoomAnimation: number) {
|
|
||||||
if (!map.value) return;
|
|
||||||
map.value.options.zoomSnap = zoomAnimation
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function pushLayers(addlayers: L.TileLayer[]) {
|
|
||||||
const _map = map.value
|
|
||||||
if (!_map) return
|
|
||||||
addlayers.forEach(l => {
|
|
||||||
if (_map.hasLayer(l)) return;
|
|
||||||
layers.value.push(l)
|
|
||||||
l.addTo(_map)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
useResizeObserver(mapContainer, () => map.value?.invalidateSize(true))
|
useResizeObserver(mapContainer, () => map.value?.invalidateSize(true))
|
||||||
|
|
||||||
defineExpose({ flyTo, changeZoom, changeMapFilter, changeMapUrl, pushLayers, changeAnimation,changeZoomSnap })
|
defineExpose({ changeMapFilter, setOptions })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
@ -1,28 +1,39 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export type DataProps = { zoom: { min: number, max: number }, urlTemplate: string, errorTileUrl: string ,zoomSnap:number}
|
export type DataProps = { zoom: { min: number, max: number }, urlTemplate: string, errorTileUrl: string, zoomSnap: number }
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
const data = ref<DataProps>({
|
import useConfig from '../../hook/useConfig';
|
||||||
zoom: { min: 3, max: 17 },
|
import { MapType } from '../../lib/mapType';
|
||||||
urlTemplate: 'http://localhost/mapabc/roadmap/{z}/{x}/{y}.png', // TODO 动态化,
|
const _configGetter = useConfig()
|
||||||
errorTileUrl: 'http://localhost/baidumaps/roadmap/error.png',
|
const maptype = ref<MapType>('gaode')
|
||||||
zoomSnap:1,
|
const data = ref(_configGetter('gaode'))
|
||||||
})
|
|
||||||
const emit = defineEmits(['change'])
|
const emit = defineEmits(['change'])
|
||||||
|
|
||||||
|
watch(maptype, v => data.value = _configGetter(v))
|
||||||
watch(data, (v) => emit('change', v), { deep: true })
|
watch(data, (v) => emit('change', v), { deep: true })
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<q-list>
|
<q-list>
|
||||||
|
<q-item>
|
||||||
|
<q-btn-group push>
|
||||||
|
<q-btn-toggle v-model="maptype" toggle-color="primary" :options="[
|
||||||
|
{ label: '百度', value: 'baidu' },
|
||||||
|
{ label: '高德', value: 'gaode' },
|
||||||
|
{ label: '高德在线', value: 'gaodeLine' }
|
||||||
|
]" />
|
||||||
|
</q-btn-group>
|
||||||
|
</q-item>
|
||||||
<q-item clickable v-close-popup>
|
<q-item clickable v-close-popup>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>缩放控制</q-item-label>
|
<q-item-label>缩放控制</q-item-label>
|
||||||
<q-item-label caption>
|
<q-item-label caption>
|
||||||
<q-range v-model="data.zoom" :min="3" :max="19" color="deep-orange" label-always markers
|
<q-range :model-value="{ max: data.maxZoom, min: data.minZoom }"
|
||||||
switch-label-side />
|
@update:model-value="({ max, min }) => { data.maxZoom = max; data.minZoom = min; }" :min="3"
|
||||||
|
:max="19" color="deep-orange" label-always markers switch-label-side />
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
<!-- TODO 控制多图层 ?? 缩放级别减少 直接控制路线等 -->
|
<!-- TODO 控制多图层 ?? 缩放级别减少 直接控制路线等 -->
|
||||||
<!-- TODO 地图不清楚 -->
|
<!-- TODO 地图不清楚 -->
|
||||||
|
@ -48,7 +59,7 @@ watch(data, (v) => emit('change', v), { deep: true })
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label>缩放倍数</q-item-label>
|
<q-item-label>缩放倍数</q-item-label>
|
||||||
<q-item-label caption>
|
<q-item-label caption>
|
||||||
<q-input v-model.number="data.zoomSnap" type="number" />
|
<q-input v-model.number="data.zoomSnap" type="number" />
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { MapType } from "../lib/mapType";
|
||||||
|
|
||||||
|
export type Config = L.TileLayerOptions & { urlTemplate: string, center: L.LatLngExpression, zoomSnap?: number }
|
||||||
|
|
||||||
|
const mapConfig: Record<MapType, Config> = {
|
||||||
|
baidu: {
|
||||||
|
urlTemplate: "http://localhost/baidumaps/roadmap/{z}/{x}/{y}.png",
|
||||||
|
errorTileUrl: 'http://localhost/baidumaps/roadmap/error.png',
|
||||||
|
center: [39.926474, 116.403283],
|
||||||
|
maxZoom: 15, minZoom: 3
|
||||||
|
},
|
||||||
|
gaode: {
|
||||||
|
urlTemplate: "http://localhost/mapabc/roadmap/{z}/{x}/{y}.png",
|
||||||
|
errorTileUrl: 'http://localhost/baidumaps/roadmap/error.png',
|
||||||
|
center: [-97.00238024827533, 210.7725501856634],
|
||||||
|
maxZoom: 15, minZoom: 3
|
||||||
|
},
|
||||||
|
gaodeLine: {
|
||||||
|
urlTemplate: "http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
|
||||||
|
errorTileUrl: 'http://localhost/baidumaps/roadmap/error.png',
|
||||||
|
center: [-97.00238024827533, 210.7725501856634],
|
||||||
|
maxZoom: 15, minZoom: 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function useConfig(): (name: MapType) => Config {
|
||||||
|
return (name) => mapConfig[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default useConfig
|
|
@ -1,10 +1,11 @@
|
||||||
import L from 'leaflet'
|
import L from 'leaflet'
|
||||||
import 'proj4'
|
import 'proj4'
|
||||||
import 'proj4leaflet'
|
import 'proj4leaflet'
|
||||||
|
import { MapType } from '../lib/mapType';
|
||||||
const _level = 19;
|
const _level = 19;
|
||||||
|
|
||||||
const crss = {
|
const crss: Record<MapType, L.CRS> = {
|
||||||
baiduCrs: new L.Proj.CRS('EPSG:900913',
|
baidu: new L.Proj.CRS('EPSG:900913',
|
||||||
'+proj=merc +a=6378206 +b=6356584.314245179 +lat_ts=0.0 +lon_0=0.0 +x_0=0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs',
|
'+proj=merc +a=6378206 +b=6356584.314245179 +lat_ts=0.0 +lon_0=0.0 +x_0=0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs',
|
||||||
{
|
{
|
||||||
resolutions: function () {
|
resolutions: function () {
|
||||||
|
@ -19,10 +20,11 @@ const crss = {
|
||||||
origin: [0, 0],
|
origin: [0, 0],
|
||||||
bounds: L.bounds([20037508.342789244, 0], [0, 20037508.342789244])
|
bounds: L.bounds([20037508.342789244, 0], [0, 20037508.342789244])
|
||||||
}),
|
}),
|
||||||
gaodeCrs: L.CRS.Simple
|
gaode: L.CRS.Simple,
|
||||||
|
gaodeLine:L.CRS.EPSG4326
|
||||||
}
|
}
|
||||||
|
|
||||||
function useCrs(name: keyof typeof crss) {
|
function useCrs(name: MapType) {
|
||||||
return crss[name]
|
return crss[name]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
import L, { Layer } from "leaflet"
|
||||||
|
import { Ref, isRef, onMounted, reactive, ref, shallowRef, toRef, triggerRef, watch } from "vue"
|
||||||
|
import useCrs from "./useCrs"
|
||||||
|
import { MapType } from "../lib/mapType"
|
||||||
|
import useConfig, { Config } from "./useConfig"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地图接口 地图类型
|
||||||
|
*/
|
||||||
|
interface MapController {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type DefineProps = L.MapOptions & Partial<Config> & { use: MapType }
|
||||||
|
|
||||||
|
interface DefineExport {
|
||||||
|
map: Ref<L.Map | undefined>
|
||||||
|
tileLayers: Ref<L.TileLayer[]>
|
||||||
|
gridLayers: Ref<L.GridLayer[]>
|
||||||
|
geoJsons: Ref<L.GeoJSON[]>
|
||||||
|
props: Ref<DefineProps>
|
||||||
|
triggerProps: (options: Config) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
function useMap(dom: Ref<string | HTMLElement>, props: DefineProps | Ref<DefineProps>): DefineExport {
|
||||||
|
const _props = isRef(props) ? props : shallowRef(props)
|
||||||
|
const _map = ref<L.Map>()
|
||||||
|
const _tileLayers: Ref<L.TileLayer[]> = ref([])
|
||||||
|
const _gridLayers: Ref<L.GridLayer[]> = ref([])
|
||||||
|
const _geos: Ref<L.GeoJSON[]> = ref([])
|
||||||
|
const _configGetter = useConfig()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const _options = _props // FIXME 这里必须要强转嘛
|
||||||
|
if (!_options) return
|
||||||
|
const crs = useCrs(_options.value.use)
|
||||||
|
const _config = _configGetter(_options.value.use)
|
||||||
|
_map.value = L.map(dom.value, { ..._options.value, crs, center: _config.center })
|
||||||
|
const layer = L.tileLayer(_config.urlTemplate, _config);
|
||||||
|
layer.addTo(_map.value)
|
||||||
|
_tileLayers.value.push(layer)
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(_props, (options) => {
|
||||||
|
if (!_map.value) return
|
||||||
|
if (!options) return
|
||||||
|
_map.value.options.crs = useCrs(options.use)
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(_tileLayers, (layers) => {
|
||||||
|
if (!_map.value) return
|
||||||
|
if (layers.length < 1) return
|
||||||
|
const { hasLayer: _has, addLayer: _add } = _map.value
|
||||||
|
layers.forEach(l => !_has(l) && _add(l))
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(_geos, (geos) => {
|
||||||
|
const __map = _map.value
|
||||||
|
if (!__map) return
|
||||||
|
if (geos.length < 1) return
|
||||||
|
geos.forEach(geo => {
|
||||||
|
geo.addTo(__map)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改后激发props
|
||||||
|
*/
|
||||||
|
function triggerProps(options: Config) {
|
||||||
|
triggerRef(_props)
|
||||||
|
}
|
||||||
|
|
||||||
|
return { map: _map, props: _props, tileLayers: _tileLayers, gridLayers: _gridLayers, geoJsons: _geos, triggerProps }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useMap
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { MapType } from "../lib/mapType";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function useConfig<T>( configName:T ,type: Record<MapType, T>) { // TODO 对config监听??
|
||||||
|
|
||||||
|
|
||||||
|
return // TODO 配置
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useConfig
|
|
@ -0,0 +1,26 @@
|
||||||
|
import L from "leaflet"
|
||||||
|
import { Ref, onMounted, ref } from "vue"
|
||||||
|
|
||||||
|
function useGeoJson(map:Ref<L.Map>,json:GeoJSON.GeoJsonObject|GeoJSON.GeoJsonObject[],){
|
||||||
|
const geoJson = ref<L.GeoJSON>()
|
||||||
|
|
||||||
|
onMounted(()=>{
|
||||||
|
geoJson.value = L.geoJSON(json,)
|
||||||
|
})
|
||||||
|
|
||||||
|
function open(){
|
||||||
|
if (!geoJson.value) return;
|
||||||
|
if (!map.value) return;
|
||||||
|
geoJson.value.addTo(map.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function close(){
|
||||||
|
if (!geoJson.value) return;
|
||||||
|
if (!map.value) return;
|
||||||
|
geoJson.value.removeFrom(map.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return [geoJson,open,close]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useGeoJson
|
|
@ -0,0 +1,14 @@
|
||||||
|
import L from 'leaflet'
|
||||||
|
import { Ref, onMounted, ref } from 'vue'
|
||||||
|
|
||||||
|
function useMap(mapContainer: Ref<string | HTMLElement>, options: L.MapOptions) {
|
||||||
|
const map = ref<L.Map>();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
map.value = L.map(mapContainer.value, options)
|
||||||
|
})
|
||||||
|
|
||||||
|
return [map]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useMap
|
|
@ -0,0 +1,26 @@
|
||||||
|
import L from "leaflet";
|
||||||
|
import { ref, Ref, onMounted } from "vue";
|
||||||
|
|
||||||
|
|
||||||
|
function useTileLayer(map: Ref<L.Map>, url: string, options: L.TileLayerOptions) {
|
||||||
|
const tileLayer = ref<L.TileLayer>()
|
||||||
|
onMounted(() => {
|
||||||
|
tileLayer.value = L.tileLayer(url, options)
|
||||||
|
})
|
||||||
|
|
||||||
|
function open() {
|
||||||
|
if (!tileLayer.value) return;
|
||||||
|
if (!map.value) return;
|
||||||
|
tileLayer.value.addTo(map.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
if (!tileLayer.value) return;
|
||||||
|
if (!map.value) return;
|
||||||
|
tileLayer.value.removeFrom(map.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return [tileLayer, open, close]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useTileLayer
|
|
@ -0,0 +1 @@
|
||||||
|
export type MapType = 'baidu' | 'gaode' | 'gaodeLine'
|
Loading…
Reference in New Issue