JSFiddle - React, Tailwind, and code Playground

by der_robert

HTML

<div class="toolbar">
    <div class="title">🏗️ Tech‑Tree – Gebäude</div>
    <div class="legend">
      <span class="badge"><span class="dot" style="background: var(--brand)"></span> Abhängigkeit</span>
      <span class="badge"><span class="dot" style="background: var(--warn)"></span> Voraussetzung (Pfad ↑)</span>
      <span class="badge"><span class="dot" style="background: var(--brand-2)"></span> Nachfolger (Pfad ↓)</span>
    </div>
    <div class="spacer"></div>
    <label class="badge">Zoom
      <input id="zoom" type="range" min="50" max="160" value="100">
    </label>
    <label class="badge">Linien
      <input id="toggleLines" type="checkbox" checked>
    </label>
  </div>

  <div class="viewport" id="viewport">
    <div class="canvas" id="canvas">
      <svg class="lines" id="lines"></svg>
    </div>
  </div>

  <div class="footer">Datenquelle: Tabellen <code>buildings</code> & <code>building_requirements</code> (Dump vom Nutzer)</div>

CSS

:root {
      --bg: #0f1222;
      --panel: #171a2b;
      --panel-2: #1f2340;
      --text: #e9ecf1;
      --muted: #9aa3b2;
      --brand: #6aa2ff;
      --brand-2: #9d7cff;
      --good: #36d399;
      --warn: #fbbf24;
      --danger: #f87272;
      --line: #3a436b;
      --shadow: 0 6px 24px rgba(0,0,0,.25);
    }

    html, body {
      height: 100%;
    }
    body {
      margin: 0; background: radial-gradient(1200px 800px at 20% 10%, rgba(106,162,255,.12), transparent 50%),
                                   radial-gradient(1000px 800px at 90% 90%, rgba(157,124,255,.12), transparent 50%),
                                   var(--bg);
      color: var(--text);
      font: 14px/1.4 system-ui, -apple-system, Segoe UI, Roboto, "Helvetica Neue", Arial, "Noto Sans", "Apple Color Emoji", "Segoe UI Emoji";
      overflow: hidden;
    }

    .toolbar {
      position: fixed;
      top: 12px; left: 12px; right: 12px;
      display: flex; gap: 10px; align-items: center;
      background: color-mix(in srgb, var(--panel), transparent 25%);
      backdrop-filter: blur(6px);
      border: 1px solid #2a3159;
      padding: 8px 10px; border-radius: 12px; box-shadow: var(--shadow);
    }
    .toolbar .title { font-weight: 700; letter-spacing: .3px; }
    .toolbar .spacer { flex: 1; }
    .toolbar input[type="range"] { width: 160px; }
    .toolbar .legend { display: flex; gap: 12px; align-items: center; color: var(--muted); }
    .legend .dot { width: 10px; height: 10px; border-radius: 999px; }

    .viewport {
      position: absolute; inset: 0; overflow: auto; cursor: grab;
    }
    .viewport:active { cursor: grabbing; }

    .canvas {
      position: relative;
      width: 3200px; /* plenty of space – will auto-fit to content later */
      height: 2000px;
      margin: 80px 0 0; /* leave room for toolbar */
      transform-origin: 0 0;
    }

    svg.lines {
      position: absolute; inset: 0; pointer-events:...

JavaScript

/* =====================
   Daten aus dem SQL-Dump
   (auf das Wesentliche reduziert)
===================== */
const BUILDINGS = [
  {id:1,  name:'Goldmine', icon:'⚜️', max_level:60, description:'Produziert pro Minute 1 Gold × Level.'},
  {id:2,  name:'Steinbruch', icon:'⛏️', max_level:50, description:'Produziert pro Minute 1 Stein × Level.'},
  {id:3,  name:'Sägewerk', icon:'🪓', max_level:50, description:'Produziert pro Minute 1 Holz × Level.'},
  {id:4,  name:'Kohlemine', icon:'🪨', max_level:50, description:'Produziert pro Minute 1 Kohle × Level.'},
  {id:5,  name:'Eisenerzmine', icon:'⛏️', max_level:50, description:'Produziert pro Minute 1 Eisenerz × Level.'},
  {id:6,  name:'Schmiede', icon:'⚒️', max_level:50, description:'Produziert Waffen (manuell).'},
  {id:7,  name:'Kaserne', icon:'🛡️', max_level:50, description:'Rekrutiert Kämpfer.'},
  {id:8,  name:'Werft', icon:'🚢', max_level:50, description:'Produziert Schiffe & Spionageschiffe.'},
  {id:9,  name:'Lagerhaus', icon:'📦', max_level:50, description:'Erhöht die Lagerkapazität.'},
  {id:10, name:'Steinwall', icon:'🧱', max_level:10, description:'+50 Verteidigung pro Level.'},
  {id:11, name:'Akademie', icon:'🎓', max_level:50, description:'Ermöglicht Forschung.'},
  {id:12, name:'Wachturm', icon:'🗼', max_level:1,  description:'Erkennt Schiffe & Angriffe.'},
  {id:13, name:'Marktplatz', icon:'🏪', max_level:1,  description:'Handel mit Spielern (Steuern!).'},
  {id:15, name:'Stallungen', icon:'🐎', max_level:5,  description:'Produziert/lagert Pferde.'},
  {id:16, name:'Belagerungswerkstatt', icon:'⚙️', max_level:10, description:'Katapult/Ballista/Rammbock.'},
  {id:17, name:'Kirche', icon:'⛪', max_level:5,  description:'Moral/Verteidigung (WIP).'},
  {id:18, name:'Friedhof', icon:'🪦', max_level:1,  description:'Statistik gefallener Einheiten.'},
  {id:19, name:'Hafen', icon:'⚓️', max_level:5,  description:'Erhöht Schiffslimit.'},
  {id:20, name:'Brunnen', icon:'⛲', max_level:50,...