Create interactive map with custom elements
by der_robert
HTML
<div id="map-wrapper">
<div id="map-content"></div>
</div>
CSS
#map-content {
position: absolute;
width: 500px; /* oder abhängig vom Koordinatensystem */
height: 500px;
background-color: #0066aa;
background-image: url('/assets/water-tile.png'); /* z. B. wellige Textur */
background-size: 200px 200px;
background-repeat: repeat;
transform-origin: top left;
border: 1px solid red;
}
.map-island {
position: absolute;
width: 32px;
height: 32px;
pointer-events: auto;
}
.map-ship,
.map-spyship {
position: absolute;
width: 24px;
height: 24px;
pointer-events: auto;
}
/* Wrack oder Sturmereignisse */
.map-event.wrack,
.map-event.storm {
width: 24px;
height: 24px;
position: absolute;
}
/* Routenlinien */
.map-route {
height: 2px;
background: rgba(255, 255, 255, 0.5);
position: absolute;
transform-origin: 0 0;
}
/* Marker auf Routen */
.map-route-marker {
width: 16px;
height: 16px;
position: absolute;
pointer-events: none;
}
JavaScript
// File: mapRenderer.js (HTML-DOM-basierte Version ohne Canvas)
const wrapper = document.getElementById('map-wrapper');
const content = document.getElementById('map-content');
let scale = 1.2;
let offsetX = 0;
let offsetY = 0;
const ICONS = {
island: 'https://i.imgur.com/geQzFeP.png',
storm: 'https://i.imgur.com/kxXEafT.png',
wrack: 'https://i.imgur.com/opO5psc.png',
ship: 'https://i.imgur.com/xxeziBr.png',
spyship: 'https://i.imgur.com/TJL9lHe.png'
};
const mapData = {
islands: [],
events: [],
routes: [] // enthält nun auch ships/spyships
};
const staticMapData = {
islands: [
{ id: 1, name: "Insel Alpha", x: 100, y: 150 },
{ id: 2, name: "Insel Beta", x: 300, y: 200 },
{ id: 3, name: "root:root", x: 423, y: 435 }
],
events: [
{ type: "wrack", x: 180, y: 180 },
{ type: "storm", x: 250, y: 220 }
],
routes: [
{
type: "ship",
from: [100, 150],
to: [300, 200],
marker: [200, 175]
},
{
type: "spyship",
from: [100, 150],
to: [423, 435],
marker: [260, 290]
}
]
};
const useStaticData = true;
function renderMap(data) {
content.innerHTML = '';
content.style.backgroundImage = 'url(/assets/water-texture.png)';
content.style.backgroundSize = '256px 256px';
const allCoords = [
...data.islands.map(i => [i.x, i.y]),
...data.events.map(e => [e.x, e.y]),
...data.routes.map(r => [r.from, r.to, r.marker]).flat()
];
const maxX = Math.max(...allCoords.map(c => c[0])) + 50;
const maxY = Math.max(...allCoords.map(c => c[1])) + 50;
content.style.width = `${maxX * scale}px`;
content.style.height = `${maxY * scale}px`;
data.routes.forEach(r => {
const x1 = r.from[0] * scale;
const y1 = r.from[1] * scale;
const x2 = r.to[0] * scale;
const y2 = r.to[1] * scale;
const angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
const length = Math.sqrt((x2...