A Pen by Konstantin (Konsti) on CodePen.
Created
December 25, 2025 19:29
-
-
Save thekonsti1/3a87722e3f8c5b50f0fb431a11a65832 to your computer and use it in GitHub Desktop.
Untitled
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="de"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Preis-Tracker Weltweit</title> | |
| <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> | |
| <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> | |
| <style> | |
| body { margin: 0; font-family: 'Segoe UI', sans-serif; background: #f0f2f5; } | |
| #map { height: 100vh; width: 100%; background: #aad3df; } | |
| #ui { | |
| position: absolute; top: 15px; left: 50%; transform: translateX(-50%); | |
| z-index: 1000; width: 90%; max-width: 400px; | |
| background: white; padding: 15px; border-radius: 15px; | |
| box-shadow: 0 10px 25px rgba(0,0,0,0.2); | |
| } | |
| .search-box { display: flex; gap: 8px; } | |
| input { flex: 1; padding: 12px; border: 1px solid #ddd; border-radius: 8px; outline: none; } | |
| button { padding: 10px 15px; background: #1a73e8; color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: bold; } | |
| .price-popup { text-align: center; } | |
| .price-val { color: #d93025; font-size: 1.4em; font-weight: bold; display: block; } | |
| .product-name { font-size: 1.1em; color: #3c4043; font-weight: 500; } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="ui"> | |
| <div class="search-box"> | |
| <input type="text" id="cityInput" placeholder="Stadt suchen (z.B. New York)..."> | |
| <button onclick="search()">Suchen</button> | |
| </div> | |
| <div style="font-size: 0.75rem; color: #70757a; margin-top: 8px; text-align: center;"> | |
| Tippe auf die Karte, um einen Preis zu melden. | |
| </div> | |
| </div> | |
| <div id="map"></div> | |
| <script> | |
| // 1. Karte begrenzen (Keine Wiederholung) | |
| const southWest = L.latLng(-85, -180); | |
| const northEast = L.latLng(85, 180); | |
| const bounds = L.latLngBounds(southWest, northEast); | |
| const map = L.map('map', { | |
| maxBounds: bounds, // Verhindert das Scrollen aus der Welt heraus | |
| maxBoundsViscosity: 1.0, // "Gummiband"-Effekt beim Rand | |
| minZoom: 2, // Verhindert zu weites Rauszoomen | |
| worldCopyJump: false // Keine Kopien der Welt | |
| }).setView([20, 0], 2); | |
| L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { | |
| noWrap: true, // Wichtig: Verhindert die unendliche Wiederholung | |
| bounds: bounds | |
| }).addTo(map); | |
| // Daten-Speicher | |
| let sharedPrices = JSON.parse(localStorage.getItem('my_prices') || '[]'); | |
| function displayMarkers() { | |
| sharedPrices.forEach(item => { | |
| const popupContent = ` | |
| <div class="price-popup"> | |
| <span class="product-name">${item.product}</span> | |
| <span class="price-val">${item.price} €</span> | |
| <small>${item.date}</small> | |
| </div>`; | |
| L.marker([item.lat, item.lng]).addTo(map).bindPopup(popupContent); | |
| }); | |
| } | |
| displayMarkers(); | |
| // Preis hinzufügen | |
| map.on('click', function(e) { | |
| const product = prompt("Produkt-Name (z.B. Diesel, Big Mac, Miete):"); | |
| if (!product) return; | |
| const price = prompt("Preis in €:"); | |
| if (!price) return; | |
| const newEntry = { | |
| lat: e.latlng.lat, | |
| lng: e.latlng.lng, | |
| product: product, | |
| price: price, | |
| date: new Date().toLocaleDateString() | |
| }; | |
| sharedPrices.push(newEntry); | |
| localStorage.setItem('my_prices', JSON.stringify(sharedPrices)); | |
| const popupContent = `<div class="price-popup"><span class="product-name">${newEntry.product}</span><span class="price-val">${newEntry.price} €</span></div>`; | |
| L.marker([newEntry.lat, newEntry.lng]).addTo(map).bindPopup(popupContent).openPopup(); | |
| }); | |
| // Suche | |
| async function search() { | |
| const query = document.getElementById('cityInput').value; | |
| const response = await fetch(`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(query)}`); | |
| const data = await response.json(); | |
| if (data.length > 0) { | |
| map.setView([data[0].lat, data[0].lon], 12); | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| body { | |
| font-family: system-ui; | |
| background: #f06d06; | |
| color: white; | |
| text-align: center; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment