Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Toronto 3D Map Viewer</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link href="https://unpkg.com/maplibre-gl@3.1.0/dist/maplibre-gl.css" rel="stylesheet"> | |
| <script src="https://unpkg.com/maplibre-gl@3.1.0/dist/maplibre-gl.js"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); | |
| body { | |
| font-family: 'Poppins', sans-serif; | |
| background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c); | |
| background-size: 400% 400%; | |
| animation: gradientBG 15s ease infinite; | |
| height: 100vh; | |
| overflow-x: hidden; | |
| } | |
| @keyframes gradientBG { | |
| 0% { background-position: 0% 50% } | |
| 50% { background-position: 100% 50% } | |
| 100% { background-position: 0% 50% } | |
| } | |
| #map { | |
| height: 100%; | |
| width: 100%; | |
| border-radius: 16px; | |
| box-shadow: 0 10px 30px rgba(0,0,0,0.3); | |
| } | |
| .sidebar { | |
| backdrop-filter: blur(10px); | |
| background: rgba(255, 255, 255, 0.1); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| } | |
| .model-card { | |
| transition: transform 0.3s ease, box-shadow 0.3s ease; | |
| background: rgba(255, 255, 255, 0.12); | |
| backdrop-filter: blur(10px); | |
| } | |
| .model-card:hover { | |
| transform: translateY(-5px); | |
| box-shadow: 0 10px 25px rgba(0,0,0,0.2); | |
| } | |
| .control-btn { | |
| transition: all 0.3s ease; | |
| background: rgba(255, 255, 255, 0.12); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| } | |
| .control-btn:hover { | |
| background: rgba(255, 255, 255, 0.2); | |
| transform: scale(1.05); | |
| } | |
| .fade-in { | |
| animation: fadeIn 0.8s ease-out; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(20px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| .location-pill { | |
| transition: all 0.3s ease; | |
| } | |
| .location-pill:hover { | |
| background: rgba(59, 130, 246, 0.2); | |
| transform: translateX(5px); | |
| } | |
| .map-marker { | |
| position: relative; | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 50% 50% 50% 0; | |
| background: #3b82f6; | |
| transform: rotate(-45deg); | |
| box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); | |
| cursor: pointer; | |
| } | |
| .map-marker::after { | |
| content: ''; | |
| position: absolute; | |
| width: 20px; | |
| height: 20px; | |
| background: white; | |
| border-radius: 50%; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%) rotate(45deg); | |
| } | |
| .glow { | |
| animation: glowPulse 2s infinite alternate; | |
| } | |
| @keyframes glowPulse { | |
| from { box-shadow: 0 0 5px -5px #3b82f6; } | |
| to { box-shadow: 0 0 15px 5px #3b82f6; } | |
| } | |
| </style> | |
| </head> | |
| <body class="flex flex-col lg:flex-row h-screen text-white p-4 gap-6"> | |
| <!-- Left Sidebar --> | |
| <div class="sidebar w-full lg:w-1/3 rounded-xl p-6 flex flex-col gap-6"> | |
| <!-- Header --> | |
| <div class="fade-in"> | |
| <div class="flex items-center gap-3"> | |
| <div class="w-10 h-10 bg-gradient-to-r from-blue-500 to-indigo-600 rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-torii-gate text-xl"></i> | |
| </div> | |
| <h1 class="text-2xl font-bold">Toronto 3D Map Viewer</h1> | |
| </div> | |
| <p class="text-gray-200 mt-2">Explore iconic Toronto landmarks with interactive 3D models</p> | |
| </div> | |
| <!-- Search Controls --> | |
| <div class="fade-in"> | |
| <div class="flex gap-2 mb-4"> | |
| <div class="flex-1"> | |
| <label class="text-gray-300 text-sm font-medium">Search Locations</label> | |
| <div class="flex mt-1"> | |
| <input | |
| type="text" | |
| placeholder="Type to search..." | |
| class="px-4 py-2 rounded-l-lg bg-gray-800 border border-gray-700 w-full focus:outline-none focus:ring-2 focus:ring-blue-500"> | |
| <button class="bg-gradient-to-r from-blue-500 to-indigo-600 px-4 rounded-r-lg"> | |
| <i class="fas fa-search"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Location Selection --> | |
| <div class="fade-in"> | |
| <h2 class="font-semibold mb-3">Popular Locations</h2> | |
| <div class="flex flex-wrap gap-2"> | |
| <div class="location-pill px-4 py-2 rounded-full bg-gray-800 cursor-pointer hover:bg-gray-700"> | |
| <i class="fas fa-tower mr-2 text-blue-400"></i> CN Tower | |
| </div> | |
| <div class="location-pill px-4 py-2 rounded-full bg-gray-800 cursor-pointer hover:bg-gray-700"> | |
| <i class="fas fa-landmark mr-2 text-purple-400"></i> City Hall | |
| </div> | |
| <div class="location-pill px-4 py-2 rounded-full bg-gray-800 cursor-pointer hover:bg-gray-700"> | |
| <i class="fas fa-home mr-2 text-yellow-400"></i> Casa Loma | |
| </div> | |
| <div class="location-pill px-4 py-2 rounded-full bg-gray-800 cursor-pointer hover:bg-gray-700"> | |
| <i class="fas fa-ship mr-2 text-red-400"></i> Harbourfront | |
| </div> | |
| </div> | |
| </div> | |
| <!-- 3D Model Selection --> | |
| <div class="fade-in flex-grow overflow-auto"> | |
| <h2 class="font-semibold mb-3">3D Models</h2> | |
| <div class="grid grid-cols-1 gap-4"> | |
| <div class="model-card p-4 rounded-xl flex flex-col cursor-pointer"> | |
| <div class="flex items-center gap-3"> | |
| <div class="w-14 h-14 bg-gradient-to-br from-blue-400 to-indigo-700 rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-tower text-2xl"></i> | |
| </div> | |
| <div> | |
| <h3 class="font-semibold">CN Tower</h3> | |
| <p class="text-sm text-gray-300">Iconic Communications Tower</p> | |
| </div> | |
| </div> | |
| <div class="flex mt-4 justify-between text-sm"> | |
| <span><i class="fas fa-ruler mr-1 text-blue-300"></i> 553 m</span> | |
| <span><i class="fas fa-calendar mr-1 text-blue-300"></i> Built: 1976</span> | |
| </div> | |
| </div> | |
| <div class="model-card p-4 rounded-xl flex flex-col cursor-pointer"> | |
| <div class="flex items-center gap-3"> | |
| <div class="w-14 h-14 bg-gradient-to-br from-amber-500 to-orange-700 rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-landmark text-2xl"></i> | |
| </div> | |
| <div> | |
| <h3 class="font-semibold">Toronto City Hall</h3> | |
| <p class="text-sm text-gray-300">Distinctive Saucer Towers</p> | |
| </div> | |
| </div> | |
| <div class="flex mt-4 justify-between text-sm"> | |
| <span><i class="fas fa-ruler mr-1 text-amber-300"></i> 103 m</span> | |
| <span><i class="fas fa-calendar mr-1 text-amber-300"></i> Built: 1965</span> | |
| </div> | |
| </div> | |
| <div class="model-card p-4 rounded-xl flex flex-col cursor-pointer"> | |
| <div class="flex items-center gap-3"> | |
| <div class="w-14 h-14 bg-gradient-to-br from-emerald-500 to-green-700 rounded-lg flex items-center justify-center"> | |
| <i class="fas fa-home text-2xl"></i> | |
| </div> | |
| <div> | |
| <h3 class="font-semibold">Casa Loma</h3> | |
| <p class="text-sm text-gray-300">Gothic Revival Castle</p> | |
| </div> | |
| </div> | |
| <div class="flex mt-4 justify-between text-sm"> | |
| <span><i class="fas fa-ruler mr-1 text-emerald-300"></i> 65 m</span> | |
| <span><i class="fas fa-calendar mr-1 text-emerald-300"></i> Built: 1914</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Controls --> | |
| <div class="fade-in"> | |
| <h2 class="font-semibold mb-3">Map Controls</h2> | |
| <div class="grid grid-cols-4 gap-3"> | |
| <button class="control-btn py-3 rounded-lg flex flex-col items-center justify-center"> | |
| <i class="fas fa-plus text-xl mb-1"></i> | |
| <span class="text-xs">Zoom In</span> | |
| </button> | |
| <button class="control-btn py-3 rounded-lg flex flex-col items-center justify-center"> | |
| <i class="fas fa-minus text-xl mb-1"></i> | |
| <span class="text-xs">Zoom Out</span> | |
| </button> | |
| <button class="control-btn py-3 rounded-lg flex flex-col items-center justify-center"> | |
| <i class="fas fa-compass text-xl mb-1"></i> | |
| <span class="text-xs">Reset View</span> | |
| </button> | |
| <button class="control-btn py-3 rounded-lg flex flex-col items-center justify-center"> | |
| <i class="fas fa-layer-group text-xl mb-1"></i> | |
| <span class="text-xs">3D View</span> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Map Container --> | |
| <div class="w-full lg:w-2/3 rounded-xl overflow-hidden shadow-2xl relative"> | |
| <div id="map" class="glow"></div> | |
| <!-- Info Panel --> | |
| <div class="absolute top-4 right-4 w-80 bg-black bg-opacity-70 backdrop-blur rounded-xl p-4"> | |
| <div class="flex items-start gap-3"> | |
| <div class="bg-gradient-to-br from-blue-500 to-indigo-600 p-2 rounded-lg"> | |
| <i class="fas fa-tower text-2xl"></i> | |
| </div> | |
| <div> | |
| <h3 class="font-bold text-lg">CN Tower - Toronto</h3> | |
| <p class="text-sm text-gray-300">One of the world's tallest free-standing structures</p> | |
| <div class="flex mt-2 text-xs"> | |
| <span class="mr-3"><i class="fas fa-ruler mr-1"></i> 553m tall</span> | |
| <span><i class="fas fa-map-pin mr-1"></i> 301 Front St W</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="mt-3 flex"> | |
| <button class="text-xs bg-gradient-to-r from-blue-500 to-indigo-600 py-1.5 px-3 rounded-lg mr-2"> | |
| <i class="fas fa-3d-modeling mr-1"></i> View in 3D | |
| </button> | |
| <button class="text-xs bg-gray-800 py-1.5 px-3 rounded-lg"> | |
| <i class="fas fa-directions mr-1"></i> Directions | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Initialize Map | |
| const map = new maplibregl.Map({ | |
| container: 'map', | |
| style: 'https://tiles.stadiamaps.com/styles/osm_bright.json', | |
| center: [-79.3832, 43.6532], // Toronto coordinates | |
| zoom: 12, | |
| pitch: 45, // Tilt for 3D effect | |
| bearing: 0, | |
| antialias: true | |
| }); | |
| // Add 3D terrain and buildings | |
| map.on('load', () => { | |
| // Add terrain with exaggerated elevation | |
| // Remove terrain source since it requires MapTiler | |
| // Add sky styling | |
| map.addLayer({ | |
| 'id': 'sky', | |
| 'type': 'sky', | |
| 'paint': { | |
| 'sky-type': 'atmosphere', | |
| 'sky-atmosphere-sun': [0.0, 0.0], | |
| 'sky-atmosphere-sun-intensity': 15 | |
| } | |
| }); | |
| // Add custom marker for the CN Tower | |
| const cnTowerElement = document.createElement('div'); | |
| cnTowerElement.className = 'map-marker glow'; | |
| cnTowerElement.title = 'CN Tower'; | |
| // Add marker to map | |
| new maplibregl.Marker({ | |
| element: cnTowerElement, | |
| anchor: 'bottom' | |
| }) | |
| .setLngLat([-79.3871, 43.6426]) // CN Tower coordinates | |
| .addTo(map); | |
| // Add fly-to animation for card clicks | |
| document.querySelectorAll('.model-card').forEach(card => { | |
| card.addEventListener('click', () => { | |
| map.flyTo({ | |
| center: [-79.3871, 43.6426], // CN Tower coordinates | |
| zoom: 15, | |
| pitch: 60, | |
| bearing: 0, | |
| speed: 1.5, | |
| curve: 1.5, | |
| easing: (t) => t | |
| }); | |
| }); | |
| }); | |
| // Add location selector functionality | |
| document.querySelectorAll('.location-pill').forEach(loc => { | |
| loc.addEventListener('click', () => { | |
| let target; | |
| if (loc.textContent.includes('CN Tower')) { | |
| target = [-79.3871, 43.6426]; | |
| } else if (loc.textContent.includes('City Hall')) { | |
| target = [-79.3847, 43.6531]; | |
| } else if (loc.textContent.includes('Casa Loma')) { | |
| target = [-79.4094, 43.6780]; | |
| } else if (loc.textContent.includes('Harbourfront')) { | |
| target = [-79.3876, 43.6388]; | |
| } else { | |
| target = [-79.3832, 43.6532]; | |
| } | |
| map.flyTo({ | |
| center: target, | |
| zoom: 14, | |
| pitch: 45, | |
| bearing: 0, | |
| speed: 1.2, | |
| curve: 1.5, | |
| easing: (t) => t | |
| }); | |
| }); | |
| }); | |
| // Add control buttons functionality | |
| document.querySelectorAll('.control-btn').forEach((btn, index) => { | |
| btn.addEventListener('click', () => { | |
| if (index === 0) { | |
| map.zoomIn(); | |
| } else if (index === 1) { | |
| map.zoomOut(); | |
| } else if (index === 2) { | |
| map.flyTo({ | |
| center: [-79.3832, 43.6532], | |
| zoom: 12, | |
| pitch: 45, | |
| bearing: 0 | |
| }); | |
| } else if (index === 3) { | |
| // Toggle between 2D and 3D view | |
| const currentPitch = map.getPitch(); | |
| map.flyTo({ | |
| pitch: currentPitch === 0 ? 60 : 0, | |
| zoom: currentPitch === 0 ? 14 : map.getZoom(), | |
| speed: 1.2 | |
| }); | |
| } | |
| }); | |
| }); | |
| }); | |
| // Add animation to sidebar cards on load | |
| setTimeout(() => { | |
| const cards = document.querySelectorAll('.fade-in'); | |
| cards.forEach((card, idx) => { | |
| card.style.animationDelay = `${idx * 0.15}s`; | |
| }); | |
| }, 100); | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=kksharma3951/kk" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |