<?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>Leaflet auf cbrueggenolte.de</title>
    <link>https://cbrueggenolte.de/tags/leaflet/</link>
    <description>Neueste Beiträge in Leaflet 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>Tue, 08 Jul 2025 00:00:00 +0200</lastBuildDate>
    <atom:link href="https://cbrueggenolte.de/tags/leaflet/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Geo‑Daten dynamisch mit Leaflet.js laden</title>
      <link>https://cbrueggenolte.de/geo-daten-dynamisch-mit-leaflet-js-laden/</link>
      <pubDate>Tue, 08 Jul 2025 00:00:00 +0200</pubDate><author>96ca5227@cbrueggenolte.de (cbrueggenolte.de)</author>
      <guid>https://cbrueggenolte.de/geo-daten-dynamisch-mit-leaflet-js-laden/</guid>
      <description>&lt;p&gt;Hier ein Überblick über die wichtigsten Änderungen:&lt;/p&gt;&#xA;&lt;p&gt;Statt die Layer-Reihenfolge mit &lt;code&gt;bringToFront()&lt;/code&gt; zu steuern, haben ich nun Leaflet-Panes benutzt.&#xA;So kann ich die Z-Index-Reihenfolge der Layer exakt bestimmen:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Länder liegen im Pane &lt;code&gt;countriesPane&lt;/code&gt; (zIndex 400)&lt;/li&gt;&#xA;&lt;li&gt;POIs im Pane &lt;code&gt;poiPane&lt;/code&gt; (zIndex 500)&lt;/li&gt;&#xA;&lt;li&gt;Hauptstädte/Capitals im Pane &lt;code&gt;capitalsPane&lt;/code&gt; (zIndex 600)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Das sorgt für eine saubere und vorhersehbare Darstellung – unabhängig von Interaktionen oder Nachladen von Daten.&#xA;Vorallem aber wird bei einem Hover-Over über Länder die Darstellung der POIs nicht mehr beeinflusst.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Hier ein Überblick über die wichtigsten Änderungen:</p>
<p>Statt die Layer-Reihenfolge mit <code>bringToFront()</code> zu steuern, haben ich nun Leaflet-Panes benutzt.
So kann ich die Z-Index-Reihenfolge der Layer exakt bestimmen:</p>
<ul>
<li>Länder liegen im Pane <code>countriesPane</code> (zIndex 400)</li>
<li>POIs im Pane <code>poiPane</code> (zIndex 500)</li>
<li>Hauptstädte/Capitals im Pane <code>capitalsPane</code> (zIndex 600)</li>
</ul>
<p>Das sorgt für eine saubere und vorhersehbare Darstellung – unabhängig von Interaktionen oder Nachladen von Daten.
Vorallem aber wird bei einem Hover-Over über Länder die Darstellung der POIs nicht mehr beeinflusst.</p>
<h3 id="neue-mapjs-datei">Neue map.js Datei</h3>
<p>Hier die neue <code>map.js</code> Datei, die die Ländergrenzen, POIs und Hauptstädte verwaltet:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><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="s1">&#39;map&#39;</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="nx">L</span><span class="p">.</span><span class="nx">tileLayer</span><span class="p">(</span><span class="s1">&#39;&#39;</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 class="kd">var</span> <span class="nx">capitalsIcon</span> <span class="o">=</span> <span class="nx">L</span><span class="p">.</span><span class="nx">divIcon</span><span class="p">({</span> <span class="nx">className</span><span class="o">:</span> <span class="s1">&#39;capitals-icon&#39;</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="c1">// Create custom panes for z-order control
</span></span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="nx">map</span><span class="p">.</span><span class="nx">createPane</span><span class="p">(</span><span class="s1">&#39;countriesPane&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="nx">map</span><span class="p">.</span><span class="nx">getPane</span><span class="p">(</span><span class="s1">&#39;countriesPane&#39;</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">zIndex</span> <span class="o">=</span> <span class="mi">400</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">  8</span><span class="cl">
</span></span><span class="line"><span class="ln">  9</span><span class="cl"><span class="nx">map</span><span class="p">.</span><span class="nx">createPane</span><span class="p">(</span><span class="s1">&#39;poiPane&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 10</span><span class="cl"><span class="nx">map</span><span class="p">.</span><span class="nx">getPane</span><span class="p">(</span><span class="s1">&#39;poiPane&#39;</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">zIndex</span> <span class="o">=</span> <span class="mi">500</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 11</span><span class="cl">
</span></span><span class="line"><span class="ln"> 12</span><span class="cl"><span class="nx">map</span><span class="p">.</span><span class="nx">createPane</span><span class="p">(</span><span class="s1">&#39;capitalsPane&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 13</span><span class="cl"><span class="nx">map</span><span class="p">.</span><span class="nx">getPane</span><span class="p">(</span><span class="s1">&#39;capitalsPane&#39;</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">zIndex</span> <span class="o">=</span> <span class="mi">600</span><span class="p">;</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="c1">// Highlight-Funktionen
</span></span></span><span class="line"><span class="ln"> 16</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"> 17</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"> 18</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"> 19</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"> 20</span><span class="cl">    <span class="nx">color</span><span class="o">:</span> <span class="s1">&#39;#ff0000&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 21</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"> 22</span><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="ln"> 23</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"> 24</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 25</span><span class="cl">
</span></span><span class="line"><span class="ln"> 26</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"> 27</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"> 28</span><span class="cl">  <span class="nx">overlayGroup</span><span class="p">.</span><span class="nx">bringToFront</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 29</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 30</span><span class="cl">
</span></span><span class="line"><span class="ln"> 31</span><span class="cl"><span class="c1">// Layer groups for better control
</span></span></span><span class="line"><span class="ln"> 32</span><span class="cl"><span class="kr">const</span> <span class="nx">baseGroup</span> <span class="o">=</span> <span class="nx">L</span><span class="p">.</span><span class="nx">layerGroup</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"> 33</span><span class="cl"><span class="kr">const</span> <span class="nx">overlayGroup</span> <span class="o">=</span> <span class="nx">L</span><span class="p">.</span><span class="nx">layerGroup</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"> 34</span><span class="cl"><span class="kr">const</span> <span class="nx">capitalsLayer</span> <span class="o">=</span> <span class="nx">L</span><span class="p">.</span><span class="nx">layerGroup</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"> 35</span><span class="cl">
</span></span><span class="line"><span class="ln"> 36</span><span class="cl"><span class="c1">// Country boundaries with outlines and optional fill
</span></span></span><span class="line"><span class="ln"> 37</span><span class="cl"><span class="kd">let</span> <span class="nx">geojson</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 38</span><span class="cl">
</span></span><span class="line"><span class="ln"> 39</span><span class="cl"><span class="c1">// Call layers in correct order
</span></span></span><span class="line"><span class="ln"> 40</span><span class="cl"><span class="kd">function</span> <span class="nx">initLayers</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 41</span><span class="cl">  <span class="nx">addCountryLayer</span><span class="p">(</span><span class="nx">addPOILayer</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></span><span class="line"><span class="ln"> 44</span><span class="cl"><span class="kd">function</span> <span class="nx">addCountryLayer</span><span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 45</span><span class="cl">  <span class="nx">fetch</span><span class="p">(</span><span class="s1">&#39;/data/vm_medium_countries.geo.json&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 46</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"> 47</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"> 48</span><span class="cl">      <span class="k">if</span> <span class="p">(</span><span class="nx">baseGroup</span><span class="p">)</span> <span class="nx">baseGroup</span><span class="p">.</span><span class="nx">clearLayers</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 49</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"> 50</span><span class="cl">        <span class="nx">pane</span><span class="o">:</span> <span class="s1">&#39;countriesPane&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 51</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"> 52</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="s1">&#39;#333&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 53</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"> 54</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"> 55</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="s1">&#39;#eee&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 56</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"> 57</span><span class="cl">        <span class="p">}),</span>
</span></span><span class="line"><span class="ln"> 58</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"> 59</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"> 60</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"> 61</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"> 62</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"> 63</span><span class="cl">          <span class="p">});</span>
</span></span><span class="line"><span class="ln"> 64</span><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 65</span><span class="cl">      <span class="p">}).</span><span class="nx">addTo</span><span class="p">(</span><span class="nx">baseGroup</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 66</span><span class="cl">      <span class="k">if</span> <span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="nx">callback</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 67</span><span class="cl">    <span class="p">})</span>
</span></span><span class="line"><span class="ln"> 68</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"> 69</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 70</span><span class="cl">
</span></span><span class="line"><span class="ln"> 71</span><span class="cl"><span class="kd">function</span> <span class="nx">addPOILayer</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 72</span><span class="cl">  <span class="nx">fetch</span><span class="p">(</span><span class="s1">&#39;/data/poi.geo.json&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 73</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"> 74</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"> 75</span><span class="cl">      <span class="k">if</span> <span class="p">(</span><span class="nx">overlayGroup</span><span class="p">)</span> <span class="nx">overlayGroup</span><span class="p">.</span><span class="nx">clearLayers</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 76</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"> 77</span><span class="cl">        <span class="nx">pane</span><span class="o">:</span> <span class="s1">&#39;poiPane&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 78</span><span class="cl">        <span class="nx">style</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">feature</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 79</span><span class="cl">          <span class="k">if</span> <span class="p">(</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="k">return</span> <span class="p">{};</span>
</span></span><span class="line"><span class="ln"> 80</span><span class="cl">          <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 81</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">stroke</span> <span class="o">||</span> <span class="s1">&#39;#3388ff&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 82</span><span class="cl">            <span class="nx">weight</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="s1">&#39;stroke-width&#39;</span><span class="p">]</span> <span class="o">||</span> <span class="mi">3</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 83</span><span class="cl">            <span class="nx">opacity</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="s1">&#39;stroke-opacity&#39;</span><span class="p">]</span> <span class="o">||</span> <span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 84</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">fill</span> <span class="o">||</span> <span class="s1">&#39;#3388ff&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 85</span><span class="cl">            <span class="nx">fillOpacity</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="s1">&#39;fill-opacity&#39;</span><span class="p">]</span> <span class="o">||</span> <span class="mf">0.2</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 86</span><span class="cl">          <span class="p">};</span>
</span></span><span class="line"><span class="ln"> 87</span><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 88</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"> 89</span><span class="cl">          <span class="k">if</span> <span class="p">(</span><span class="nx">feature</span><span class="p">.</span><span class="nx">properties</span> <span class="o">&amp;&amp;</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 class="p">{</span>
</span></span><span class="line"><span class="ln"> 90</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"> 91</span><span class="cl">          <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 92</span><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="ln"> 93</span><span class="cl">      <span class="p">}).</span><span class="nx">addTo</span><span class="p">(</span><span class="nx">overlayGroup</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 94</span><span class="cl">    <span class="p">});</span>
</span></span><span class="line"><span class="ln"> 95</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 96</span><span class="cl">
</span></span><span class="line"><span class="ln"> 97</span><span class="cl"><span class="c1">// Capitals logic
</span></span></span><span class="line"><span class="ln"> 98</span><span class="cl"><span class="kd">function</span> <span class="nx">clearCapitals</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 99</span><span class="cl">  <span class="nx">capitalsLayer</span><span class="p">.</span><span class="nx">clearLayers</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">100</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">101</span><span class="cl">
</span></span><span class="line"><span class="ln">102</span><span class="cl"><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;capitals-btn&#39;</span><span class="p">).</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kr">async</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">103</span><span class="cl">  <span class="nx">clearCapitals</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">104</span><span class="cl">  <span class="kr">const</span> <span class="nx">res</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">fetch</span><span class="p">(</span><span class="s1">&#39;/api/capitals&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">105</span><span class="cl">  <span class="kr">const</span> <span class="nx">capitals</span> <span class="o">=</span> <span class="kr">await</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">106</span><span class="cl">  <span class="nx">capitals</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">capital</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">107</span><span class="cl">    <span class="kr">const</span> <span class="nx">marker</span> <span class="o">=</span> <span class="nx">L</span><span class="p">.</span><span class="nx">marker</span><span class="p">([</span><span class="nx">capital</span><span class="p">.</span><span class="nx">lat</span><span class="p">,</span> <span class="nx">capital</span><span class="p">.</span><span class="nx">lng</span><span class="p">],</span> <span class="p">{</span> <span class="nx">icon</span><span class="o">:</span> <span class="nx">capitalsIcon</span><span class="p">,</span> <span class="nx">pane</span><span class="o">:</span> <span class="s1">&#39;capitalsPane&#39;</span> <span class="p">}).</span><span class="nx">bindPopup</span><span class="p">(</span><span class="nx">capital</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">108</span><span class="cl">    <span class="nx">capitalsLayer</span><span class="p">.</span><span class="nx">addLayer</span><span class="p">(</span><span class="nx">marker</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">109</span><span class="cl">  <span class="p">});</span>
</span></span><span class="line"><span class="ln">110</span><span class="cl">  <span class="nx">capitalsLayer</span><span class="p">.</span><span class="nx">bringToFront</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">111</span><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="ln">112</span><span class="cl">
</span></span><span class="line"><span class="ln">113</span><span class="cl"><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;remove-capitals-btn&#39;</span><span class="p">).</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">114</span><span class="cl">  <span class="nx">clearCapitals</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">115</span><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="ln">116</span><span class="cl">
</span></span><span class="line"><span class="ln">117</span><span class="cl"><span class="nx">initLayers</span><span class="p">();</span></span></span></code></pre></div><p>Die Layer für Länder, POIs und Hauptstädte werden jetzt in eigenen LayerGroups verwaltet. Das macht das Nachladen, Entfernen und Aktualisieren von Daten viel einfacher und übersichtlicher.</p>
<h3 id="neue-html-struktur">Neue HTML-Struktur</h3>
<p>Hier die neue <code>index.html</code> Datei, die die Karte und die Buttons enthält:</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">button</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;capitals-btn&#34;</span><span class="p">&gt;</span>Load Capitals via API<span class="p">&lt;/</span><span class="nt">button</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">      <span class="p">&lt;</span><span class="nt">button</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;remove-capitals-btn&#34;</span><span class="p">&gt;</span>Remove Capitals<span class="p">&lt;/</span><span class="nt">button</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="ln">15</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">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</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">18</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">19</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">20</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">21</span><span class="cl"><span class="p">&lt;/</span><span class="nt">html</span><span class="p">&gt;</span></span></span></code></pre></div><h3 id="neue-styles">Neue Styles</h3>
<p>Dazu passend die neuen Styles in der <code>styles.css</code> Datei, für die Karte und die Buttons:</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="c">/* Header ersetzen */</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="nt">header</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  <span class="k">background-color</span><span class="p">:</span> <span class="mh">#f8f9fa</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">1</span><span class="kt">em</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 5</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"> 6</span><span class="cl">  <span class="k">border-bottom</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"> 7</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c">/* und in der Map die Werte für &#39;margin&#39; neu setzen */</span>
</span></span><span class="line"><span class="ln">10</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">11</span><span class="cl">  <span class="k">margin</span><span class="p">:</span> <span class="mi">1</span><span class="kt">rem</span> <span class="mi">1</span><span class="kt">rem</span><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></span><span class="line"><span class="ln">14</span><span class="cl"><span class="nt">button</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">  <span class="k">padding</span><span class="p">:</span> <span class="mf">0.5</span><span class="kt">em</span> <span class="mi">1</span><span class="kt">em</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">  <span class="k">margin</span><span class="p">:</span> <span class="mf">0.5</span><span class="kt">em</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">  <span class="k">border</span><span class="p">:</span> <span class="kc">none</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">  <span class="k">border-radius</span><span class="p">:</span> <span class="mi">4</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">  <span class="k">background-color</span><span class="p">:</span> <span class="mh">#007bff</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">  <span class="k">color</span><span class="p">:</span> <span class="kc">white</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">  <span class="k">cursor</span><span class="p">:</span> <span class="kc">pointer</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="p">.</span><span class="nc">capitals-icon</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">  <span class="k">background-color</span><span class="p">:</span> <span class="mh">#007bff</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">  <span class="k">border-radius</span><span class="p">:</span> <span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">  <span class="k">width</span><span class="p">:</span> <span class="mi">24</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">  <span class="k">height</span><span class="p">:</span> <span class="mi">24</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">29</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">30</span><span class="cl">  <span class="k">align-items</span><span class="p">:</span> <span class="kc">center</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">  <span class="k">justify-content</span><span class="p">:</span> <span class="kc">center</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><h3 id="neue-indexts-datei">Neue index.ts Datei</h3>
<p>Jetzt noch die <code>index.ts</code> Datei, die die API für die Hauptstädte bereitstellt:</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-typescript" data-lang="typescript"><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="s1">&#39;@hono/node-server&#39;</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="s1">&#39;hono&#39;</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="s1">&#39;@hono/node-server/serve-static&#39;</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="s1">&#39;/public/*&#39;</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="s1">&#39;./&#39;</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="s1">&#39;/data/*&#39;</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="s1">&#39;./&#39;</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="c1">// API endpoint for dynamic location data
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="s1">&#39;/api/capitals&#39;</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">15</span><span class="cl">  <span class="kr">const</span> <span class="nx">capitals</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">1</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Berlin&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">52.52</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">13.405</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">2</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Paris&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">48.8566</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">2.3522</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">3</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;London&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">51.5074</span><span class="p">,</span> <span class="nx">lng</span><span class="o">:</span> <span class="o">-</span><span class="mf">0.1278</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">4</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Madrid&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">40.4168</span><span class="p">,</span> <span class="nx">lng</span><span class="o">:</span> <span class="o">-</span><span class="mf">3.7038</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">5</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Rome&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">41.9028</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">12.4964</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">6</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Vienna&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">48.2082</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">16.3738</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">7</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Amsterdam&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">52.3676</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">4.9041</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">8</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Brussels&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">50.8503</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">4.3517</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">id</span>: <span class="kt">9</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Copenhagen&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">55.6761</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">12.5683</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">id</span>: <span class="kt">10</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Stockholm&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">59.3293</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">18.0686</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">11</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Oslo&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">59.9139</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">10.7522</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">12</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Helsinki&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">60.1695</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">24.9354</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">13</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Lisbon&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">38.7223</span><span class="p">,</span> <span class="nx">lng</span><span class="o">:</span> <span class="o">-</span><span class="mf">9.1393</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">14</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Dublin&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">53.3498</span><span class="p">,</span> <span class="nx">lng</span><span class="o">:</span> <span class="o">-</span><span class="mf">6.2603</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">15</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Warsaw&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">52.2297</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">21.0122</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">16</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Prague&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">50.0755</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">14.4378</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">17</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Budapest&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">47.4979</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">19.0402</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">18</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Bratislava&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">48.1482</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">17.1067</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">19</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Ljubljana&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">46.0569</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">14.5051</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="p">{</span> <span class="nx">id</span>: <span class="kt">20</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="s1">&#39;Zagreb&#39;</span><span class="p">,</span> <span class="nx">lat</span>: <span class="kt">45.815</span><span class="p">,</span> <span class="nx">lng</span>: <span class="kt">15.9819</span> <span class="p">},</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">  <span class="p">];</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">  <span class="k">return</span> <span class="nx">c</span><span class="p">.</span><span class="nx">json</span><span class="p">(</span><span class="nx">capitals</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="p">});</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">
</span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="c1">// Redirect root to public/index.html
</span></span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="nx">app</span><span class="p">.</span><span class="kr">get</span><span class="p">(</span><span class="s1">&#39;/&#39;</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="nx">c</span><span class="p">.</span><span class="nx">html</span><span class="p">(</span><span class="s1">&#39;&lt;script&gt;location.href=&#34;https://cbrueggenolte.de/public/index.html&#34;&lt;/script&gt;&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">
</span></span><span class="line"><span class="ln">43</span><span class="cl"><span class="c1">// Start the server
</span></span></span><span class="line"><span class="ln">44</span><span class="cl"><span class="nx">serve</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="ln">46</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">47</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">48</span><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="ln">49</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">50</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">51</span><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="ln">52</span><span class="cl"><span class="p">);</span></span></span></code></pre></div><p>Die API liefert eine Liste von Hauptstädten mit ihren Koordinaten. Diese werden später in der Karte als Marker angezeigt. Und mit den neu hinzugefügten Buttons kann der Nutzer die Hauptstädte dynamisch laden und entfernen.</p>
<h3 id="neue-daten">Neue Daten</h3>
<p>Und ins Verzeichnis <code>data</code> kommt neben der GeoJSON-Datei <code>vm_medium_countries.geo.json</code>, die du von <a href="https://geojson-maps.kyd.au/">geojson-maps.kyd.au</a> heruntergeladen hast, die neue Version der <a href="/geo-daten-dynamisch-mit-leaflet-js-laden/poi.geo.json">`poi.geo.json</a> Datei welche neue POI enthält.</p>
<p>Wie in der <code>map.js</code> Datei zu sehen ist, werden die Information zur Darstellung der POIs jetzt direkt aus den GeoJSON-Properties (<code>stroke</code>, <code>stroke-width</code>, <code>fill</code>, etc.) übernommen. So kann jeder POI individuell gestaltet werden – z.B. für besondere Städte oder Flächen.</p>
<h2 id="fazit">Fazit</h2>
<p>Durch die Nutzung von LayerGroups, Panes und klaren Funktionsaufrufen ist der Code jetzt deutlich modularer und leichter zu erweitern.</p>
<p>Wenn alles geklappt hat, solltest du nun eine funktionierende Leaflet-Karte haben, die Ländergrenzen anzeigt und dynamisch POIs und Hauptstädte laden kann und ungefähr so aussieht:</p>
]]></content:encoded>
    </item>
    <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>
