JSFiddle - React, Tailwind, and code Playground

by der_robert

HTML

<div id="map-container">
  <canvas id="island-map" width="1000" height="1000"></canvas>
</div>

CSS

#map-container {
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
  background-color: #004488; // dunkles Meer
  canvas {
    display: block;
    cursor: grab;
  }
}

JavaScript

// File: mapRenderer.js

const canvas = document.getElementById('island-map');
const ctx = canvas.getContext('2d');
const tooltip = document.createElement('div');
tooltip.id = 'map-tooltip';
tooltip.style.position = 'absolute';
tooltip.style.background = '#222';
tooltip.style.color = '#fff';
tooltip.style.padding = '4px 8px';
tooltip.style.borderRadius = '4px';
tooltip.style.fontSize = '12px';
tooltip.style.pointerEvents = 'none';
tooltip.style.display = 'none';
document.body.appendChild(tooltip);

let scale = 2;
let offsetX = 0;
let offsetY = 0;
let zoomCenterX = 0;
let zoomCenterY = 0;

let dragging = false, lastX = 0, lastY = 0;

canvas.addEventListener('mousedown', (e) => {
  dragging = true;
  lastX = e.clientX;
  lastY = e.clientY;
});
canvas.addEventListener('mouseup', () => dragging = false);
canvas.addEventListener('mouseleave', () => dragging = false);
canvas.addEventListener('mousemove', (e) => {
  if (!dragging) return;
  offsetX += e.clientX - lastX;
  offsetY += e.clientY - lastY;
  lastX = e.clientX;
  lastY = e.clientY;
});

canvas.addEventListener('wheel', (e) => {
  e.preventDefault();
  const rect = canvas.getBoundingClientRect();
  const mouseX = (e.clientX - rect.left - offsetX) / scale;
  const mouseY = (e.clientY - rect.top - offsetY) / scale;
  const zoom = e.deltaY < 0 ? 1.1 : 0.9;
  scale *= zoom;
  offsetX = e.clientX - mouseX * scale;
  offsetY = e.clientY - mouseY * scale;
});

canvas.addEventListener('mousemove', (e) => {
  const rect = canvas.getBoundingClientRect();
  const mouseX = (e.clientX - rect.left - offsetX) / scale;
  const mouseY = (e.clientY - rect.top - offsetY) / scale;

  tooltip.style.display = 'none';
  mapData.islands.forEach(i => {
    const dx = i.x - mouseX;
    const dy = i.y - mouseY;
    if (Math.sqrt(dx * dx + dy * dy) < 5) {
      tooltip.style.left = `${e.pageX + 10}px`;
      tooltip.style.top = `${e.pageY + 10}px`;
      tooltip.innerText =...