| | <!DOCTYPE html>
|
| | <html lang="de">
|
| | <head>
|
| | <meta charset="UTF-8" />
|
| | <meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
| | <title>Woods Karte</title>
|
| | <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI=" crossorigin="" />
|
| | <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js" integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" crossorigin=""></script>
|
| | <style>
|
| | * {
|
| | margin: 0;
|
| | padding: 0;
|
| | }
|
| | #map {
|
| | width: 100%;
|
| | height: 100vh;
|
| | }
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | </style>
|
| | <link rel="stylesheet" href="woods.css" />
|
| | </head>
|
| | <body>
|
| | <div id="map"></div>
|
| | <script>
|
| | const transform = [0.1855, 113.1, 0.1855, 167.8]
|
| | const svgBounds = [
|
| | [650, -945],
|
| | [-695, 470],
|
| | ]
|
| | const bounds = [
|
| | [650, -945],
|
| | [-762, 470],
|
| | ]
|
| | const coordinateRotation = 180
|
| | const svgPath = "Woods.svg"
|
| | const minZoom = 1
|
| | const maxZoom = 6
|
| |
|
| | function getCRS(transform) {
|
| | let scaleX = 1
|
| | let scaleY = 1
|
| | let marginX = 0
|
| | let marginY = 0
|
| | if (transform) {
|
| | scaleX = transform[0]
|
| | scaleY = transform[2] * -1
|
| | marginX = transform[1]
|
| | marginY = transform[3]
|
| | }
|
| | return L.extend({}, L.CRS.Simple, {
|
| | transformation: new L.Transformation(scaleX, marginX, scaleY, marginY),
|
| | projection: L.extend({}, L.Projection.LonLat, {
|
| | project: (latLng) => {
|
| | return L.Projection.LonLat.project(applyRotation(latLng, coordinateRotation))
|
| | },
|
| | unproject: (point) => {
|
| | return applyRotation(L.Projection.LonLat.unproject(point), coordinateRotation * -1)
|
| | },
|
| | }),
|
| | })
|
| | }
|
| |
|
| | function applyRotation(latLng, rotation) {
|
| | if (!latLng.lng && !latLng.lat) {
|
| | return L.latLng(0, 0)
|
| | }
|
| | if (!rotation) {
|
| | return latLng
|
| | }
|
| |
|
| | const angleInRadians = (rotation * Math.PI) / 180
|
| | const cosAngle = Math.cos(angleInRadians)
|
| | const sinAngle = Math.sin(angleInRadians)
|
| |
|
| | const { lng: x, lat: y } = latLng
|
| | const rotatedX = x * cosAngle - y * sinAngle
|
| | const rotatedY = x * sinAngle + y * cosAngle
|
| | return L.latLng(rotatedY, rotatedX)
|
| | }
|
| |
|
| | function pos(position) {
|
| | return [position.z, position.x]
|
| | }
|
| |
|
| | function getScaledBounds(bounds, scaleFactor) {
|
| |
|
| | const centerX = (bounds[0][0] + bounds[1][0]) / 2
|
| | const centerY = (bounds[0][1] + bounds[1][1]) / 2
|
| |
|
| |
|
| | const width = bounds[1][0] - bounds[0][0]
|
| | const height = bounds[1][1] - bounds[0][1]
|
| | const newWidth = width * scaleFactor
|
| | const newHeight = height * scaleFactor
|
| |
|
| |
|
| | const newBounds = [
|
| | [centerY - newHeight / 2, centerX - newWidth / 2],
|
| | [centerY + newHeight / 2, centerX + newWidth / 2],
|
| | ]
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | return newBounds
|
| | }
|
| |
|
| |
|
| |
|
| |
|
| | const map = L.map("map", {
|
| | maxBounds: getScaledBounds(svgBounds, 1.5),
|
| |
|
| | center: [0, 0],
|
| | zoom: 2,
|
| | minZoom: 1,
|
| | maxZoom: 6,
|
| | zoomSnap: 0.1,
|
| | scrollWheelZoom: true,
|
| | wheelPxPerZoomLevel: 120,
|
| | crs: getCRS(transform),
|
| | attributionControl: false,
|
| | id: "wwoodsMap",
|
| | })
|
| |
|
| |
|
| | const imageUrl = "Woods.svg"
|
| |
|
| | const overlay = L.imageOverlay(imageUrl, getBounds(svgBounds))
|
| | overlay.addTo(map)
|
| |
|
| |
|
| |
|
| |
|
| | const labels = [
|
| | { position: [10, -3], text: "Sawmill" },
|
| | { position: [-485, -390], text: "Scav Town" },
|
| | { position: [-517, -210], text: "Old Sawmill" },
|
| | { position: [-80, -680], text: "Cultist Village" },
|
| | { position: [290, -475], text: "USEC Camp" },
|
| | { position: [-188, 235], text: "Military Camp" },
|
| | { position: [-5, -515], text: "Ponds", size: 80 },
|
| | { position: [-252, -37], text: "Crash Site", size: 80 },
|
| | { position: [239, -65], text: "Checkpoint", size: 70 },
|
| | { position: [244, 125], text: "Shack", size: 70 },
|
| | { position: [-16, -122], text: "Lumber", size: 70 },
|
| | { position: [-3, -74], text: "Cabins", size: 70 },
|
| | { position: [-234, 357], text: "Bus Stop", size: 70 },
|
| | { position: [-327, 19], text: "Jaeger's Camp", size: 70 },
|
| | { position: [85, -147], text: "Sniper Rock", size: 70 },
|
| | { position: [200, -606], text: "Convoy", size: 70 },
|
| | ]
|
| |
|
| | function getBounds(bounds) {
|
| | if (!bounds) {
|
| | return undefined
|
| | }
|
| | return L.latLngBounds([bounds[0][1], bounds[0][0]], [bounds[1][1], bounds[1][0]])
|
| |
|
| | }
|
| |
|
| | const layerOptions = {
|
| | maxZoom: maxZoom,
|
| | maxNativeZoom: maxZoom,
|
| | extents: [
|
| | {
|
| | height: [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER],
|
| | bounds: [bounds],
|
| | },
|
| | ],
|
| | type: "map-layer",
|
| | }
|
| | let tileLayer = false
|
| | const baseLayers = []
|
| | const tileSize = 256
|
| | let svgLayer = false
|
| | if (svgPath) {
|
| | const svgBounds2 = svgBounds ? getBounds(svgBounds) : bounds
|
| | svgLayer = L.imageOverlay(svgPath, svgBounds2, layerOptions)
|
| | baseLayers.push(svgLayer)
|
| | }
|
| |
|
| | if (labels?.length > 0) {
|
| | const labelsGroup = L.layerGroup()
|
| | const defaultHeight = (layerOptions.extents[0].height[1] - layerOptions.extents[0].height[0]) / 2 + layerOptions.extents[0].height[0]
|
| | for (const label of labels) {
|
| | const fontSize = label.size ? label.size : 100
|
| | const height = label.position.length < 3 ? defaultHeight : label.position[2]
|
| | const rotation = label.rotation ? label.rotation : 0
|
| | L.marker(pos({ x: label.position[0], z: label.position[1] }), {
|
| | icon: L.divIcon({
|
| | html: `<div class="label" style="font-size: ${fontSize}%; transform: translate3d(-50%, -50%, 0) rotate(${rotation}deg)">${label.text}</div>`,
|
| | className: "map-area-label",
|
| | layers: baseLayers,
|
| | }),
|
| | interactive: false,
|
| | zIndexOffset: -100000,
|
| | position: {
|
| | x: label.position[0],
|
| | y: height,
|
| | z: label.position[1],
|
| | },
|
| | top: typeof label.top !== "undefined" ? label.top : 1000,
|
| | bottom: typeof label.bottom !== "undefined" ? label.bottom : -1000,
|
| | }).addTo(labelsGroup)
|
| | }
|
| |
|
| | labelsGroup.addTo(map)
|
| | }
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | </script>
|
| | <style>
|
| | .label {
|
| | text-align: center;
|
| | }
|
| | </style>
|
| | </body>
|
| | </html>
|
| |
|