<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Offline auf cbrueggenolte.de</title>
    <link>https://cbrueggenolte.de/tags/offline/</link>
    <description>Neueste Beiträge in Offline auf cbrueggenolte.de</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>de-DE</language>
    <managingEditor>96ca5227@cbrueggenolte.de (cbrueggenolte.de)</managingEditor>
    <webMaster>96ca5227@cbrueggenolte.de (cbrueggenolte.de)</webMaster>
    <copyright>2018-2026 cbrueggenolte</copyright>
    <lastBuildDate>Mon, 07 Jul 2025 00:00:00 +0200</lastBuildDate>
    <atom:link href="https://cbrueggenolte.de/tags/offline/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Minimalistische Offline-Leaflet-Karte mit Node.js &amp; Hono</title>
      <link>https://cbrueggenolte.de/minimalistische-offline-leaflet-karte-mit-node-js-hono/</link>
      <pubDate>Mon, 07 Jul 2025 00:00:00 +0200</pubDate><author>96ca5227@cbrueggenolte.de (cbrueggenolte.de)</author>
      <guid>https://cbrueggenolte.de/minimalistische-offline-leaflet-karte-mit-node-js-hono/</guid>
      <description>&lt;p&gt;Für ein Projekt benötigte ich eine einfache, offlinefähige &lt;a href=&#34;https://leafletjs.com/&#34;&gt;Leaflet&lt;/a&gt;-Karte, die nur Ländergrenzen und dynamisch injizierte Punkte anzeigt. Hier ist eine Schritt-für-Schritt-Anleitung, wie du so etwas mit Node.js und &lt;a href=&#34;https://hono.dev&#34;&gt;Hono&lt;/a&gt; umsetzen kannst.&lt;/p&gt;&#xA;&lt;p&gt;Hono ist ein leichtgewichtiger Web-Framework für Node.js, das sich hervorragend für einfache APIs eignet.&#xA;Wenn wir fertig sind, haben wir eine minimalistische Leaflet-Karte, die offline funktioniert und die Ländergrenzen sowie dynamisch geladene Punkte anzeigt.&lt;/p&gt;&#xA;&lt;h2 id=&#34;schritt-1-projekt-initialisieren&#34;&gt;Schritt 1: Projekt initialisieren&lt;/h2&gt;&#xA;&lt;p&gt;Erstelle ein neues Hono-Projekt:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Für ein Projekt benötigte ich eine einfache, offlinefähige <a href="https://leafletjs.com/">Leaflet</a>-Karte, die nur Ländergrenzen und dynamisch injizierte Punkte anzeigt. Hier ist eine Schritt-für-Schritt-Anleitung, wie du so etwas mit Node.js und <a href="https://hono.dev">Hono</a> umsetzen kannst.</p>
<p>Hono ist ein leichtgewichtiger Web-Framework für Node.js, das sich hervorragend für einfache APIs eignet.
Wenn wir fertig sind, haben wir eine minimalistische Leaflet-Karte, die offline funktioniert und die Ländergrenzen sowie dynamisch geladene Punkte anzeigt.</p>
<h2 id="schritt-1-projekt-initialisieren">Schritt 1: Projekt initialisieren</h2>
<p>Erstelle ein neues Hono-Projekt:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">npm create hono@latest</span></span></code></pre></div><p>Folge den Anweisungen im Terminal und wähle die folgenden Optionen:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">create-hono version 0.19.2
</span></span><span class="line"><span class="ln">2</span><span class="cl">✔ Target directory leaflet-hono
</span></span><span class="line"><span class="ln">3</span><span class="cl">✔ Which template <span class="k">do</span> you want to use? nodejs
</span></span><span class="line"><span class="ln">4</span><span class="cl">✔ Do you want to install project dependencies? Yes
</span></span><span class="line"><span class="ln">5</span><span class="cl">✔ Which package manager <span class="k">do</span> you want to use? npm
</span></span><span class="line"><span class="ln">6</span><span class="cl">✔ Cloning the template
</span></span><span class="line"><span class="ln">7</span><span class="cl">✔ Installing project dependencies
</span></span><span class="line"><span class="ln">8</span><span class="cl">🎉 Copied project files
</span></span><span class="line"><span class="ln">9</span><span class="cl">Get started with: <span class="nb">cd</span> leaflet-hono</span></span></code></pre></div><p>Wir installieren hier auch Leaflet um aus dem node_modules Verzeichnis auf die Leaflet-Bibliothek zugreifen zu können.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">cd</span> leaflet-hono
</span></span><span class="line"><span class="ln">2</span><span class="cl">npm install leaflet</span></span></code></pre></div><hr>
<h2 id="schritt-2-projektstruktur-anlegen">Schritt 2: Projektstruktur anlegen</h2>





<pre tabindex="0"><code>leaflet-hono/
├── data/
├── public/
│   ├── leaflet/
│   │   ├── images/ ( &lt;&lt; siehe unten für Details &gt;&gt; )
│   │   ├── leaflet.css
│   │   ├── leaflet.js
│   │   └── leaflet.js.map
├── src/
│   ├── index.ts</code></pre><ul>
<li><strong>data/</strong> enthält heruntergeladene GeoJSON-Dateien (z. B. Natural Earth 50m).</li>
<li><strong>public/</strong> enthält Frontend-Dateien.</li>
<li><strong>server.js</strong> enthält den Hono-Server und API-Endpunkte.</li>
<li><code>public/leaflet/images</code> Ordner mit Leaflet-Bildern aus dem node_modules/leaflet/dist/images Verzeichnis)</li>
</ul>
<p>Kopiere die Leaflet Dateien aus <code>node_modules/leaflet/dist/</code> in den <code>public/leaflet/</code> Ordner:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">mkdir -p public/leaflet/images
</span></span><span class="line"><span class="ln">2</span><span class="cl">cp node_modules/leaflet/dist/images/* public/leaflet/images/
</span></span><span class="line"><span class="ln">3</span><span class="cl">cp node_modules/leaflet/dist/leaflet.css public/leaflet/
</span></span><span class="line"><span class="ln">4</span><span class="cl">cp node_modules/leaflet/dist/leaflet.js public/leaflet/
</span></span><span class="line"><span class="ln">5</span><span class="cl">cp node_modules/leaflet/dist/leaflet.js.map public/leaflet/</span></span></code></pre></div><hr>
<h2 id="schritt-3-app-starten">Schritt 3: App starten</h2>
<p>Bevor wir weiter machen, stellen wir sicher, dass wir unsere App einmal starten können. Starte dazu den Hono-Server:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">npm run dev</span></span></code></pre></div><p>Wenn alles richtig eingerichtet ist, solltest du die Standard-Hono-Seite unter <strong><a href="http://localhost:3000">http://localhost:3000</a></strong> sehen.</p>
<hr>
<h2 id="schritt-4-srcindexts">Schritt 4: <code>src/index.ts</code></h2>
<p>Nun erweitern wir die <code>src/index.ts</code> Datei, um die Daten aus dem <code>public</code> und <code>data</code> Ordner bereitzustellen.</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ts" data-lang="ts"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">serve</span> <span class="p">}</span> <span class="kr">from</span> <span class="s2">&#34;@hono/node-server&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">Hono</span> <span class="p">}</span> <span class="kr">from</span> <span class="s2">&#34;hono&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kr">import</span> <span class="p">{</span> <span class="nx">serveStatic</span> <span class="p">}</span> <span class="kr">from</span> <span class="s2">&#34;@hono/node-server/serve-static&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="kr">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Hono</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1">// Serve static files from &#39;public&#39;
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="s2">&#34;/public/*&#34;</span><span class="p">,</span> <span class="nx">serveStatic</span><span class="p">({</span> <span class="nx">root</span><span class="o">:</span> <span class="s2">&#34;./&#34;</span> <span class="p">}));</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1">// Serve static files from &#39;data&#39;
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="s2">&#34;/data/*&#34;</span><span class="p">,</span> <span class="nx">serveStatic</span><span class="p">({</span> <span class="nx">root</span><span class="o">:</span> <span class="s2">&#34;./&#34;</span> <span class="p">}));</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="s2">&#34;/&#34;</span><span class="p">,</span> <span class="p">(</span><span class="nx">c</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">  <span class="k">return</span> <span class="nx">c</span><span class="p">.</span><span class="nx">text</span><span class="p">(</span><span class="s2">&#34;Hello Hono!&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="nx">serve</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="nx">fetch</span>: <span class="kt">app.fetch</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="nx">port</span>: <span class="kt">3000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">  <span class="p">(</span><span class="nx">info</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="sb">`Server is running on http://localhost:</span><span class="si">${</span><span class="nx">info</span><span class="p">.</span><span class="nx">port</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="p">);</span></span></span></code></pre></div><p>Zum Testen erstellen wir eine einfache Test-Datei, die wir später in der Karte verwenden werden. Erstelle dazu eine Datei <code>data/poi.geo.json</code> mit folgendem Inhalt:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;FeatureCollection&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  <span class="nt">&#34;features&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;Feature&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">      <span class="nt">&#34;properties&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;Den Haag&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">      <span class="nt">&#34;geometry&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;Point&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="nt">&#34;coordinates&#34;</span><span class="p">:</span> <span class="p">[</span><span class="mf">4.3007</span><span class="p">,</span> <span class="mf">52.0705</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;Feature&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">      <span class="nt">&#34;properties&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;Utrecht&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">      <span class="nt">&#34;geometry&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;Point&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="nt">&#34;coordinates&#34;</span><span class="p">:</span> <span class="p">[</span><span class="mf">5.09</span><span class="p">,</span> <span class="mf">52.0907</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">  <span class="p">]</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>Wenn nun <code>&lt;https://localhost:3000/data/poi.geo.json&gt;</code> aufgerufen wird, sollte die GeoJSON-Datei angezeigt werden.</p>
<hr>
<h2 id="schritt-5-publicindexhtml-und-publicstylescss">Schritt 5: <code>public/index.html</code> und <code>public/styles.css</code></h2>
<p>In die <code>index.html</code> Datei fügen wir die grundlegende Struktur für die Leaflet-Karte ein. Erstelle die Datei <code>public/index.html</code> mit folgendem Inhalt:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp">&lt;!DOCTYPE html&gt;</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="p">&lt;</span><span class="nt">html</span> <span class="na">lang</span><span class="o">=</span><span class="s">&#34;de&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  <span class="p">&lt;</span><span class="nt">head</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="p">&lt;</span><span class="nt">meta</span> <span class="na">charset</span><span class="o">=</span><span class="s">&#34;UTF-8&#34;</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="p">&lt;</span><span class="nt">title</span><span class="p">&gt;</span>Minimal Leaflet Karte<span class="p">&lt;/</span><span class="nt">title</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&#34;stylesheet&#34;</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;styles.css&#34;</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&#34;stylesheet&#34;</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;/public/leaflet/leaflet.css&#34;</span> <span class="na">crossorigin</span><span class="o">=</span><span class="s">&#34;&#34;</span> <span class="p">/&gt;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  <span class="p">&lt;/</span><span class="nt">head</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  <span class="p">&lt;</span><span class="nt">body</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="p">&lt;</span><span class="nt">header</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">      <span class="p">&lt;</span><span class="nt">h1</span><span class="p">&gt;</span>Leaflet Demo Map<span class="p">&lt;/</span><span class="nt">h1</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">      <span class="p">&lt;</span><span class="nt">p</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;subtitle&#34;</span><span class="p">&gt;</span>A simple demonstration of a Leaflet map<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="p">&lt;/</span><span class="nt">header</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="p">&lt;</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;map&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="p">&lt;</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;/public/leaflet/leaflet.js&#34;</span> <span class="na">crossorigin</span><span class="o">=</span><span class="s">&#34;&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="p">&lt;</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">&#34;map.js&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">  <span class="p">&lt;/</span><span class="nt">body</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="p">&lt;/</span><span class="nt">html</span><span class="p">&gt;</span></span></span></code></pre></div><p>Um das nicht ganz so langweilig zu gestalten, fügen wir noch etwas CSS hinzu. Erstelle die Datei <code>public/styles.css</code> mit folgendem Inhalt:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="nt">html</span><span class="o">,</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="nt">body</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  <span class="k">margin</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  <span class="k">padding</span><span class="p">:</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">  <span class="k">width</span><span class="p">:</span> <span class="mi">100</span><span class="kt">%</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  <span class="k">height</span><span class="p">:</span> <span class="mi">100</span><span class="kt">%</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="nt">body</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  <span class="k">font-family</span><span class="p">:</span> <span class="n">Arial</span><span class="p">,</span> <span class="kc">sans-serif</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">  <span class="k">height</span><span class="p">:</span> <span class="mi">100</span><span class="kt">vh</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">  <span class="k">box-sizing</span><span class="p">:</span> <span class="kc">border-box</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">  <span class="k">display</span><span class="p">:</span> <span class="kc">flex</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">  <span class="k">flex-direction</span><span class="p">:</span> <span class="kc">column</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="nt">h1</span><span class="o">,</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="p">.</span><span class="nc">subtitle</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">  <span class="k">margin</span><span class="p">:</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mf">0.5</span><span class="kt">em</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">  <span class="k">text-align</span><span class="p">:</span> <span class="kc">center</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="p">.</span><span class="nc">subtitle</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">  <span class="k">font-size</span><span class="p">:</span> <span class="mf">1.2</span><span class="kt">em</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">  <span class="k">color</span><span class="p">:</span> <span class="mh">#666</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">  <span class="k">margin-bottom</span><span class="p">:</span> <span class="mi">1</span><span class="kt">em</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="p">#</span><span class="nn">map</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">  <span class="k">flex</span><span class="p">:</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">  <span class="k">margin</span><span class="p">:</span> <span class="mi">0</span> <span class="mi">2</span><span class="kt">vw</span> <span class="mi">2</span><span class="kt">vw</span> <span class="mi">2</span><span class="kt">vw</span><span class="p">;</span> <span class="c">/* margin around the map */</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">  <span class="k">background-color</span><span class="p">:</span> <span class="mh">#f0f0f0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">  <span class="k">border</span><span class="p">:</span> <span class="mi">1</span><span class="kt">px</span> <span class="kc">solid</span> <span class="mh">#ccc</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">  <span class="k">border-radius</span><span class="p">:</span> <span class="mi">8</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><hr>
<h2 id="schritt-6-publicmapjs">Schritt 6: <code>public/map.js</code></h2>
<p>Was nun noch fehlt, ist die Logik, um die Karte zu initialisieren und die GeoJSON-Daten zu laden. Erstelle die Datei <code>public/map.js</code> mit folgendem Inhalt:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kr">const</span> <span class="nx">map</span> <span class="o">=</span> <span class="nx">L</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="s2">&#34;map&#34;</span><span class="p">).</span><span class="nx">setView</span><span class="p">([</span><span class="mf">52.0705</span><span class="p">,</span> <span class="mf">4.707</span><span class="p">],</span> <span class="mi">11</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="nx">L</span><span class="p">.</span><span class="nx">tileLayer</span><span class="p">(</span><span class="s2">&#34;https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png&#34;</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  <span class="nx">maxZoom</span><span class="o">:</span> <span class="mi">19</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="p">}).</span><span class="nx">addTo</span><span class="p">(</span><span class="nx">map</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="nx">fetch</span><span class="p">(</span><span class="s2">&#34;/data/poi.geo.json&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">response</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">response</span><span class="p">.</span><span class="nx">json</span><span class="p">())</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">data</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="nx">L</span><span class="p">.</span><span class="nx">geoJSON</span><span class="p">(</span><span class="nx">data</span><span class="p">).</span><span class="nx">addTo</span><span class="p">(</span><span class="nx">map</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">  <span class="p">});</span></span></span></code></pre></div><p>Hiermit initialisieren wir die Karte auf den Koordinaten zwischen Den Haag und Utrecht und laden die GeoJSON-Daten von unserem Hono-Server. Die Punkte werden dann als Layer zur Karte hinzugefügt.</p>
<p>Wenn alles geklappt hat, sollte es ungefähr so aussehen:</p>
<p><a href="/minimalistische-offline-leaflet-karte-mit-node-js-hono/leaflet-demo_hu_772b2bc636fdd6d6.webp"><img class="content-image" src="/minimalistische-offline-leaflet-karte-mit-node-js-hono/leaflet-demo_hu_8590a9d8d27efc5c.webp" alt="Screenshot Leaflet Karte im Browser" loading="lazy" width="1440" height="1129" /></a></p>
<hr>
<h2 id="schritt-7-osm-ersetzen-und-ländergrenzen-hinzufügen">Schritt 7: OSM ersetzen und Ländergrenzen hinzufügen</h2>
<p>Da wir aber eine offlinefähige Karte erstellen wollen, müssen wir die Ländergrenzen und andere Geodaten lokal bereitstellen. Wir verwenden dafür GeoJSON-Dateien von <a href="https://www.naturalearthdata.com/downloads/50m-cultural-vectors/">Natural Earth</a> die sich gut für kleinere Karten eignen.</p>
<p>Um die Ländergrenzen herunterzuladen, navigiere zu <a href="https://geojson-maps.kyd.au/">geojson-maps.kyd.au</a>, wähle &ldquo;Medium Resolution&rdquo; und aktiviere die Checkbox &ldquo;All&rdquo;. Die mittlere Auflösung ist für unsere Zwecke ausreichend und hat mit nur 4,5 MB eine handhabbare Größe. Die Option &ldquo;All&rdquo; stellt sicher, dass alle Ländergrenzen enthalten sind.</p>
<p><a href="/minimalistische-offline-leaflet-karte-mit-node-js-hono/download-geojson-countries_hu_737010276674c80d.webp"><img class="content-image" src="/minimalistische-offline-leaflet-karte-mit-node-js-hono/download-geojson-countries_hu_edc6e6d41c2b19c3.webp" alt="Leaflet Ländergrenzen Download" loading="lazy" width="1440" height="1151" /></a></p>
<p>Klicke anschließend auf &ldquo;Build Custom GeoJSON&rdquo; in der rechten unteren Ecke, um die Datei herunterzuladen. Diese Datei enthält alle Ländergrenzen im GeoJSON-Format, das mit Leaflet kompatibel ist. Speichere die Datei im <code>data</code>-Ordner unter dem Namen <code>vm_medium_countries.geo.json</code>.</p>
<p>Anschließend erweitern wir die <code>public/map.js</code> Datei, um die Ländergrenzen zu laden und anzuzeigen:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kr">const</span> <span class="nx">map</span> <span class="o">=</span> <span class="nx">L</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="s2">&#34;map&#34;</span><span class="p">).</span><span class="nx">setView</span><span class="p">([</span><span class="mf">52.0705</span><span class="p">,</span> <span class="mf">4.707</span><span class="p">],</span> <span class="mi">5</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="nx">L</span><span class="p">.</span><span class="nx">tileLayer</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="p">{}).</span><span class="nx">addTo</span><span class="p">(</span><span class="nx">map</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="nx">fetch</span><span class="p">(</span><span class="s2">&#34;/data/vm_medium_countries.geo.json&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">  <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">response</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">response</span><span class="p">.</span><span class="nx">json</span><span class="p">())</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">data</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="nx">L</span><span class="p">.</span><span class="nx">geoJSON</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">      <span class="nx">style</span><span class="o">:</span> <span class="p">(</span><span class="nx">feature</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">({</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="nx">color</span><span class="o">:</span> <span class="nx">feature</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">color</span> <span class="o">||</span> <span class="s2">&#34;#333&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="nx">weight</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="nx">opacity</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="nx">fillColor</span><span class="o">:</span> <span class="nx">feature</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">fillColor</span> <span class="o">||</span> <span class="s2">&#34;#eee&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="nx">fillOpacity</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">      <span class="p">}),</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="p">}).</span><span class="nx">addTo</span><span class="p">(</span><span class="nx">map</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">  <span class="p">});</span></span></span></code></pre></div><p>Der Code initialisiert eine Leaflet-Karte ohne Hintergrund-Layer (also ohne Basiskarte) und zeigt die Ländergrenzen aus einer lokalen GeoJSON-Datei an.</p>
<ul>
<li>Die Karte wird auf Europa zentriert und auf Zoomstufe 5 gesetzt.</li>
<li>Es wird ein leerer Tile-Layer hinzugefügt, damit Leaflet korrekt funktioniert, aber keine Online-Kartenkacheln geladen werden.</li>
<li>Die Ländergrenzen werden per <code>fetch</code> aus der Datei <code>/data/vm_medium_countries.geo.json</code> geladen.</li>
<li>Mit <code>L.geoJSON</code> werden die Länder als Layer zur Karte hinzugefügt. Die Darstellung (Linienfarbe, Füllfarbe) kann für jedes Land individuell über die Eigenschaften im GeoJSON gesteuert werden (<code>feature.properties.color</code> und <code>feature.properties.fillColor</code>). Gibt es keine Angabe, werden Standardwerte verwendet.</li>
</ul>
<p>Um das ganze noch etwas abzurunden können wir die Hintergrundfarbe der Karte in der <code>public/styles.css</code> Datei anpassen:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-css" data-lang="css"><span class="line"><span class="ln">1</span><span class="cl"><span class="p">#</span><span class="nn">map</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">  <span class="k">flex</span><span class="p">:</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">  <span class="k">margin</span><span class="p">:</span> <span class="mi">0</span> <span class="mi">2</span><span class="kt">vw</span> <span class="mi">2</span><span class="kt">vw</span> <span class="mi">2</span><span class="kt">vw</span><span class="p">;</span> <span class="c">/* margin around the map */</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">  <span class="k">background-color</span><span class="p">:</span> <span class="mh">#87ceeb</span><span class="p">;</span> <span class="c">/* light blue, resembling the sea */</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">  <span class="k">border</span><span class="p">:</span> <span class="mi">1</span><span class="kt">px</span> <span class="kc">solid</span> <span class="mh">#ccc</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">  <span class="k">border-radius</span><span class="p">:</span> <span class="mi">8</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>Damit erhält die Karte eine hellblaue Hintergrundfarbe, die visuell das Meer andeuten soll. Die Länder werden in einem neutralen Grau dargestellt.</p>
<p><a href="/minimalistische-offline-leaflet-karte-mit-node-js-hono/leaflet-with-countries_hu_703e1f339303e184.webp"><img class="content-image" src="/minimalistische-offline-leaflet-karte-mit-node-js-hono/leaflet-with-countries_hu_914aca009a1ac637.webp" alt="Leaflet Karte im Browser" loading="lazy" width="1440" height="1129" /></a></p>
<hr>
<h2 id="schritt-8-ländergrenzen-und-poi-kombinieren">Schritt 8: Ländergrenzen und POI kombinieren</h2>
<p>Nun wollen wir noch die POI-Punkte aus der <code>data/poi.geo.json</code> Datei auf der Karte anzeigen. Dazu erweitern wir die <code>public/map.js</code> Datei:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="ln">1</span><span class="cl"><span class="nx">fetch</span><span class="p">(</span><span class="s2">&#34;/data/poi.geo.json&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">  <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">response</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">response</span><span class="p">.</span><span class="nx">json</span><span class="p">())</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">  <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">data</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">    <span class="nx">L</span><span class="p">.</span><span class="nx">geoJSON</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">      <span class="nx">onEachFeature</span><span class="o">:</span> <span class="p">(</span><span class="nx">feature</span><span class="p">,</span> <span class="nx">layer</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">        <span class="nx">layer</span><span class="p">.</span><span class="nx">bindPopup</span><span class="p">(</span><span class="nx">feature</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">    <span class="p">}).</span><span class="nx">addTo</span><span class="p">(</span><span class="nx">map</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl">  <span class="p">});</span></span></span></code></pre></div><p>Nach dem Neuladen der Seite sollten nun die POI-Punkte (Den Haag und Utrecht) auf der Karte angezeigt werden. Wenn du auf einen Punkt klickst, öffnet sich ein Popup mit dem Namen des Ortes.</p>
<p><a href="/minimalistische-offline-leaflet-karte-mit-node-js-hono/leaflet-with-countries-and-poi_hu_e2e98c4609c4b661.webp"><img class="content-image" src="/minimalistische-offline-leaflet-karte-mit-node-js-hono/leaflet-with-countries-and-poi_hu_1e4550772837d4ee.webp" alt="Leaflet Karte im Browser" loading="lazy" width="1440" height="1036" /></a></p>
<hr>
<h2 id="bonus-fancy-leaflet-funktionen">Bonus: Fancy Leaflet Funktionen</h2>
<p>Um die Karte ein wenig interaktiver zu gestalten, können wir noch einige zusätzliche Features hinzufügen. Leaflet bietet viele Möglichkeiten, um die Benutzererfahrung zu verbessern. Ersetze die <code>public/map.js</code> Datei mit folgendem Inhalt:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kr">const</span> <span class="nx">map</span> <span class="o">=</span> <span class="nx">L</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="s2">&#34;map&#34;</span><span class="p">).</span><span class="nx">setView</span><span class="p">([</span><span class="mf">52.0705</span><span class="p">,</span> <span class="mf">4.707</span><span class="p">],</span> <span class="mi">6</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1">// Leaflet benötigt mindestens einen Tile-Layer, auch wenn er leer ist.
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1">// Deshalb wird hier ein leerer Tile-Layer eingebunden, um die Engine korrekt zu initialisieren.
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="nx">L</span><span class="p">.</span><span class="nx">tileLayer</span><span class="p">(</span><span class="s2">&#34;&#34;</span><span class="p">,</span> <span class="p">{}).</span><span class="nx">addTo</span><span class="p">(</span><span class="nx">map</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1">// Highlight-Funktionen
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="kd">function</span> <span class="nx">highlightFeature</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  <span class="kr">const</span> <span class="nx">layer</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  <span class="nx">layer</span><span class="p">.</span><span class="nx">setStyle</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="nx">weight</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="nx">color</span><span class="o">:</span> <span class="s2">&#34;#ff0000&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="nx">fillOpacity</span><span class="o">:</span> <span class="mf">0.7</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">  <span class="nx">layer</span><span class="p">.</span><span class="nx">bringToFront</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="kd">function</span> <span class="nx">resetHighlight</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">  <span class="nx">geojson</span><span class="p">.</span><span class="nx">resetStyle</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">target</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="c1">// Country boundaries with outlines and optional fill
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="kd">let</span> <span class="nx">geojson</span><span class="p">;</span> <span class="c1">// Global variable to hold the geojson layer
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="nx">fetch</span><span class="p">(</span><span class="s2">&#34;/data/vm_medium_countries.geo.json&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">  <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">res</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">res</span><span class="p">.</span><span class="nx">json</span><span class="p">())</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">  <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">data</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="nx">geojson</span> <span class="o">=</span> <span class="nx">L</span><span class="p">.</span><span class="nx">geoJSON</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">      <span class="nx">style</span><span class="o">:</span> <span class="p">(</span><span class="nx">feature</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">({</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">        <span class="nx">color</span><span class="o">:</span> <span class="nx">feature</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">color</span> <span class="o">||</span> <span class="s2">&#34;#333&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="nx">weight</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="nx">opacity</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">        <span class="nx">fillColor</span><span class="o">:</span> <span class="nx">feature</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">fillColor</span> <span class="o">||</span> <span class="s2">&#34;#eee&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">        <span class="nx">fillOpacity</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">      <span class="p">}),</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">      <span class="nx">onEachFeature</span><span class="o">:</span> <span class="p">(</span><span class="nx">feature</span><span class="p">,</span> <span class="nx">layer</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">        <span class="nx">layer</span><span class="p">.</span><span class="nx">bindPopup</span><span class="p">(</span><span class="nx">feature</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">        <span class="nx">layer</span><span class="p">.</span><span class="nx">on</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">          <span class="nx">mouseover</span><span class="o">:</span> <span class="nx">highlightFeature</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">          <span class="nx">mouseout</span><span class="o">:</span> <span class="nx">resetHighlight</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">        <span class="p">});</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">    <span class="p">}).</span><span class="nx">addTo</span><span class="p">(</span><span class="nx">map</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">  <span class="p">})</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">  <span class="p">.</span><span class="k">catch</span><span class="p">(</span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">
</span></span><span class="line"><span class="ln">45</span><span class="cl"><span class="c1">// POI data with popups
</span></span></span><span class="line"><span class="ln">46</span><span class="cl"><span class="nx">fetch</span><span class="p">(</span><span class="s2">&#34;/data/poi.geo.json&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl">  <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">response</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="nx">response</span><span class="p">.</span><span class="nx">json</span><span class="p">())</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">  <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">data</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">49</span><span class="cl">    <span class="nx">L</span><span class="p">.</span><span class="nx">geoJSON</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">50</span><span class="cl">      <span class="nx">onEachFeature</span><span class="o">:</span> <span class="p">(</span><span class="nx">feature</span><span class="p">,</span> <span class="nx">layer</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl">        <span class="nx">layer</span><span class="p">.</span><span class="nx">bindPopup</span><span class="p">(</span><span class="nx">feature</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">52</span><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="ln">53</span><span class="cl">    <span class="p">}).</span><span class="nx">addTo</span><span class="p">(</span><span class="nx">map</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">54</span><span class="cl">  <span class="p">});</span></span></span></code></pre></div><p>Dieser Code fügt folgende Features hinzu:</p>
<ul>
<li><strong>Hover-Effekte</strong>: Länder werden hervorgehoben, wenn der Mauszeiger darüber schwebt.</li>
<li><strong>Popups</strong>: Beim Klicken auf Länder oder POI-Punkte öffnet sich ein Popup mit dem Namen.</li>
<li><strong>Popup für Länder</strong>: Beim Klicken auf ein Land öffnet sich ein Popup mit dem Namen des Landes.</li>
<li><strong>Popup für POI-Punkte</strong>: Beim Klicken auf einen POI-Punkt öffnet sich ein Popup mit dem Namen des Ortes.</li>
</ul>
<hr>
<h2 id="-fazit">🧭 Fazit</h2>
<p><a href="/minimalistische-offline-leaflet-karte-mit-node-js-hono/cloc-without-css_hu_f8aa5fa6c2a886f2.webp"><img class="content-image" src="/minimalistische-offline-leaflet-karte-mit-node-js-hono/cloc-without-css_hu_1490c2b7d8b18c1e.webp" alt="CLOC" loading="lazy" width="1440" height="1048" /></a></p>
<p>Mit weniger als 100 Zeilen Code lässt sich eine minimalistische, offlinefähige Leaflet-Karte mit Hono realisieren. Ideal für Prototyping oder einfache Anwendungen – ohne externe Abhängigkeiten und voll anpassbar.</p>
<p>Die Karte kann leicht erweitert werden, um weitere Features hinzuzufügen, wie z. B. Marker, Polygone oder andere GeoJSON-Daten. <a href="https://leafletjs.com/">Leaflet</a> bietet eine Vielzahl von Möglichkeiten, um Karten interaktiv und ansprechend zu gestalten.</p>
<p>Das Projekt in Version 1 kannst du hier herunterladen: <a href="https://codeberg.org/cblte/leaflet-hono-offline/releases/tag/v1">https://codeberg.org/cblte/leaflet-hono-offline/releases/tag/v1</a></p>
]]></content:encoded>
    </item>
  </channel>
</rss>
