Zoom
vue
<template>
<Map
v-if="data"
:data="data"
:projection="projection"
>
<MapZoom @zoom="updateMarkerScale">
<MapGraticule border />
<MapFeatures />
<MapMesh />
<MapMarker
v-for="(item, index) in cities"
:key="index"
:coordinates="[item.lon, item.lat]"
>
<g :transform="`scale(${markerScale})`">
<text
font-size="14"
y="-8"
text-anchor="middle"
>{{ item.city }}</text>
<circle
r="3"
/>
</g>
</MapMarker>
</MapZoom>
</Map>
</template>
<script setup lang="ts">
import type { ZoomEvent } from '@d3-maps/core'
import { geoNaturalEarth1 } from 'd3-geo'
import { withBase } from 'vitepress'
import { onMounted, ref } from 'vue'
interface City {
city: string
lon: number
lat: number
}
const initialCities: City[] = [
{ city: 'Minsk', lon: 27.34, lat: 53.54 },
{ city: 'Dili', lon: 125.36, lat: -8.35 },
{ city: 'Dushanbe', lon: 68.48, lat: 38.35 },
{ city: 'Guatemala City', lon: -90.31, lat: 14.37 },
{ city: 'Njamena', lon: 12.1348, lat: 15.0557 },
{ city: 'Tokyo', lon: 139.45, lat: 35.41 },
{ city: 'Georgetown', lon: -58.1, lat: 6.48 },
]
const data = ref<unknown>()
const projection = geoNaturalEarth1
const cities = ref<City[]>(initialCities)
const markerScale = ref(1)
const currentZoom = ref(1)
onMounted(async () => {
const response = await fetch(withBase('/example-data/countries-110m.json'))
data.value = await response.json()
})
function updateMarkerScale(e: ZoomEvent) {
if (currentZoom.value === e.transform.k) return
currentZoom.value = e.transform.k
markerScale.value = 1 / e.transform.k
}
</script>