<script lang="ts">
export let position: undefined | { lat: number; lng: number }
import { onMount } from 'svelte'
const assets = '/static'
const mapsrv =
'https://wxs.ign.fr/essentiels/geoportail/wmts?REQUEST=GetTile&SERVICE=WMTS&VERSION=1.0.0&STYLE=normal&TILEMATRIXSET=PM&FORMAT=image/png&LAYER=GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2&'
import { browser } from '$app/environment'
export let zoom = 5
let dot: null | L.Marker = null
let redIcon: any = null
let map: any = null
onMount(async () => {
console.log('map onload', browser)
if (!browser) {
return
}
const L = await import('leaflet')
await import('leaflet.fullscreen')
const G = await import('leaflet-gesture-handling')
// @ts-ignore
L.Map.addInitHook('addHandler', 'gestureHandling', G.GestureHandling)
map = L.map('descrmap', {
// @ts-ignore
fullscreenControl: true,
fullscreenControlOptions: {
position: 'topleft',
},
// @ts-ignore
gestureHandling: true,
// attributionControl: false,
})
;(<any>document).coturnixMap = map
if (position) {
map.setView(position, zoom)
} else {
map.setView({ lat: 46, lng: 3 }, 5)
}
let layer = L.tileLayer(
`${mapsrv}TILEMATRIX={z}&TILEROW={y}&TILECOL={x}`,
{
minZoom: 0,
maxZoom: 18,
attribution: 'IGN-F/Geoportail',
tileSize: 256,
noWrap: true,
}
).addTo(map)
layer.on('tileerror', (e) => {
console.log(e)
// e.tile.src = `${mapsrv}TILEMATRIX=${e.coords.z}&TILEROW=${e.coords.y}&TILECOL=${e.coords.x}`
})
if (!redIcon) {
redIcon = L.icon({
iconUrl: `${assets}/marker-icon-red.png`,
iconRetinaUrl: `${assets}/marker-icon-red.png`,
shadowUrl: `${assets}/marker-shadow.png`,
iconAnchor: [12, 41],
} as L.IconOptions)
}
if (position) {
dot = L.marker(position, {
icon: redIcon!,
draggable: false,
})
dot.addTo(map)
}
// position = { lat: 45, lng: 3 }
map.on('click', function (e: any) {
position = e.latlng
console.log(position)
if (dot) {
dot.setLatLng(position!)
} else {
dot = L.marker(position!, {
icon: redIcon!,
draggable: false,
})
dot.addTo(map)
}
})
recentrer()
})
function recentrer(zoom?: number) {
if (!position || !map) {
return
}
let lng0 = 180
let lng1 = -180
let lat0 = 90
let lat1 = -90
let mar = 0.5 / 111.111 // 500m en longitude (111.111km par degré)
let lat2 = position.lat - mar
let lat3 = position.lat + mar
let dx = mar / Math.cos((position.lat * Math.PI) / 180)
let lng2 = position.lng - dx
let lng3 = position.lng + dx
lng0 = Math.min(lng0, lng2)
lng1 = Math.max(lng1, lng3)
lat0 = Math.min(lat0, lat2)
lat1 = Math.max(lat1, lat3)
if (lng0 < lng1 && lat0 < lat1) {
console.log([
[lat0, lng0],
[lat1, lng1],
])
map.fitBounds(
[
[lat0, lng0],
[lat1, lng1],
],
{ maxZoom: 14 }
)
} else {
map.setView(position, zoom)
}
}
</script>
<svelte:head>
<link rel="stylesheet" href="{assets}/leaflet.css" />
<link rel="stylesheet" href="{assets}/leafletfs.css" />
<link rel="stylesheet" href="{assets}/leaflet-gesture-handling.min.css" />
</svelte:head>
<div id="descrmap" class="w-100" style="height:500px" />
<div class="d-flex">
<button
class="btn btn-sm btn-outline-secondary my-2 ms-auto"
on:click={(_) => recentrer(zoom)}>Recentrer</button>
</div>