63 lines
2.0 KiB
Vue
63 lines
2.0 KiB
Vue
<script setup lang="ts">
|
|
import { ref, onMounted, provide, watch } from 'vue';
|
|
import 'leaflet/dist/leaflet.css';
|
|
import useMap from '../hook/useMap.ts';
|
|
import { useResizeObserver } from '@vueuse/core';
|
|
import { setOptions } from 'leaflet';
|
|
|
|
const mapContainer = ref();
|
|
const { map, tileLayers, props: mapProps } = useMap(mapContainer, { use: 'gaode', zoom: 13 });
|
|
|
|
// const config = defineModel<Object>()
|
|
|
|
const slotProps = ref({
|
|
contextmenu: {},
|
|
});
|
|
|
|
const mapFilter = ref('invert(1) grayscale(.2) saturate(0.8) brightness(1.8) opacity(1) hue-rotate(184deg) sepia(17%)'); // 地图滤镜
|
|
|
|
provide('map', map); // 注入的内容 mapChild 下
|
|
|
|
onMounted(() => {
|
|
map.value?.addEventListener('contextmenu', (e) => {
|
|
slotProps.value.contextmenu = e;
|
|
});
|
|
});
|
|
|
|
watch({ center: mapProps.value.center }, ({ center }) => center && map.value?.flyTo(center));
|
|
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' | 'brightness' | 'contrast' | 'drop-shadow' | 'grayscale' | 'hue-rotate' | 'invert' | 'opacity' | 'saturate' | 'sepia', string | number>
|
|
) {
|
|
mapFilter.value = Object.entries(filterInfo)
|
|
.map(([key, value]) => `${key}(${value})`)
|
|
.join(' ');
|
|
}
|
|
|
|
useResizeObserver(mapContainer, () => map.value?.invalidateSize(true));
|
|
|
|
defineExpose({ changeMapFilter, setOptions });
|
|
</script>
|
|
|
|
<template>
|
|
<div class="mapContainer" ref="mapContainer" :style="{ '--mapFilter': mapFilter }">
|
|
<slot v-if="map" v-bind="slotProps"></slot>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss">
|
|
.mapContainer {
|
|
grid-area: map;
|
|
}
|
|
|
|
body.body--dark {
|
|
.mapFilter {
|
|
filter: var(--mapFilter);
|
|
}
|
|
}
|
|
</style>
|