Exploring the world of 3D design can be both inspiring and educational. In this article, we present ten stunning 3D examples that showcase the versatility and creativity of modern 3D technology.
From intricate architectural models to lifelike character animations, these examples highlight the potential of 3D design in various fields. Dive in to see how these creations push the boundaries of what's possible.
CODE1
Here's the code:
CODETEXT1
CODE2
Here's the code:
CODETEXT2
CODE3
Here's the code:
CODETEXT3
CODE4
Here's the code:
CODETEXT4
CODE5
Here's the code:
CODETEXT5
Subframe's drag-and-drop interface and intuitive, responsive canvas make it easy to create pixel-perfect UI every time. Loved by designers and developers alike, Subframe empowers you to bring your 3D visions to life effortlessly.
Start for free and experience the magic of Subframe today!
CODE6
Here's the code:
CODETEXT6
CODE7
Here's the code:
CODETEXT7
CODE8
Here's the code:
CODETEXT8
CODE9
Here's the code:
CODETEXT9
CODE10
Here's the code:
CODETEXT10
Ready to elevate your UI design game? With Subframe, you can create stunning, pixel-perfect UIs, including 3D designs, in minutes. Our drag-and-drop editor and beautifully crafted components make the process efficient and enjoyable.
Don't wait to bring your visions to life. Start for free and begin designing immediately!
<html> <head> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Montserrat', sans-serif; } body { overflow: hidden; background: #081f2e; width: 100%; height: 100vh; display: flex; justify-content: center; align-items: center; } .map-container { position: relative; width: 700px; height: 700px; overflow: hidden; border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4); } .map-wrapper { position: absolute; width: 200%; height: 200%; top: -50%; left: -50%; transform-style: preserve-3d; transform: perspective(1000px) rotateX(30deg) scale(0.7); transition: transform 0.8s cubic-bezier(0.34, 1.56, 0.64, 1); } .map { position: absolute; width: 100%; height: 100%; background: linear-gradient(135deg, #0a3c5d, #12658f); overflow: hidden; transform-style: preserve-3d; } .terrain { position: absolute; width: 100%; height: 100%; background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M0 0 L100 0 L100 100 L0 100 Z" fill="none" stroke="%23267faf" stroke-width="0.5" stroke-opacity="0.3" /></svg>'); opacity: 0.6; } .continents { position: absolute; width: 100%; height: 100%; } .continent { position: absolute; border-radius: 30%; background: linear-gradient(145deg, #27ae60, #2ecc71); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); transform: translateZ(5px); transition: transform 0.4s ease-out, box-shadow 0.4s ease; } .continent:hover { transform: translateZ(12px); box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3); } .continent.north-america { width: 25%; height: 28%; left: 20%; top: 20%; clip-path: polygon(30% 0%, 70% 0%, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0% 70%, 0% 30%); background: linear-gradient(145deg, #27ae60, #2ecc71); } .continent.south-america { width: 15%; height: 20%; left: 28%; top: 55%; clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%); background: linear-gradient(145deg, #f39c12, #f1c40f); } .continent.europe { width: 15%; height: 15%; left: 48%; top: 22%; clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%); background: linear-gradient(145deg, #8e44ad, #9b59b6); } .continent.africa { width: 20%; height: 25%; left: 48%; top: 42%; clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%); background: linear-gradient(145deg, #d35400, #e67e22); } .continent.asia { width: 28%; height: 28%; left: 63%; top: 25%; clip-path: polygon(30% 0%, 70% 0%, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0% 70%, 0% 30%); background: linear-gradient(145deg, #c0392b, #e74c3c); } .continent.australia { width: 12%; height: 12%; left: 75%; top: 60%; clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%); background: linear-gradient(145deg, #2980b9, #3498db); } .location-marker { position: absolute; width: 20px; height: 20px; border-radius: 50%; background: #fff; transform: translateZ(15px); cursor: pointer; box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2); display: flex; justify-content: center; align-items: center; transition: all 0.3s ease; } .location-marker::after { content: ''; position: absolute; width: 10px; height: 10px; border-radius: 50%; background: #ff3366; animation: pulse 2s infinite; } .location-marker:hover { transform: translateZ(20px) scale(1.2); } @keyframes pulse { 0% { transform: scale(0.8); opacity: 1; } 70% { transform: scale(1.5); opacity: 0; } 100% { transform: scale(0.8); opacity: 0; } } .tooltip { position: absolute; background: rgba(255, 255, 255, 0.95); padding: 15px; border-radius: 8px; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2); width: 250px; transform: translateZ(25px); opacity: 0; pointer-events: none; transition: opacity 0.3s ease, transform 0.3s ease; z-index: 100; } .tooltip.visible { opacity: 1; pointer-events: auto; } .tooltip h3 { color: #0a3c5d; margin-bottom: 8px; font-size: 16px; } .tooltip p { color: #555; font-size: 13px; line-height: 1.4; margin-bottom: 6px; } .tooltip .highlight { color: #ff3366; font-weight: 600; } .tooltip img { width: 100%; height: 120px; object-fit: cover; border-radius: 6px; margin-top: 8px; margin-bottom: 8px; } .tooltip .explore-btn { background: #ff3366; color: #fff; border: none; padding: 8px 15px; border-radius: 4px; font-size: 13px; cursor: pointer; transition: background 0.3s ease; margin-top: 5px; display: inline-block; } .tooltip .explore-btn:hover { background: #e6275b; } .controls { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); display: flex; gap: 10px; z-index: 10; } .control-btn { background: rgba(255, 255, 255, 0.2); border: none; width: 40px; height: 40px; border-radius: 50%; color: white; font-size: 20px; cursor: pointer; display: flex; justify-content: center; align-items: center; backdrop-filter: blur(5px); transition: all 0.3s ease; } .control-btn:hover { background: rgba(255, 255, 255, 0.4); } .info-panel { position: absolute; top: 20px; left: 20px; background: rgba(255, 255, 255, 0.9); padding: 15px; border-radius: 10px; width: 280px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); z-index: 10; transform: translateZ(10px); } .info-panel h2 { color: #0a3c5d; font-size: 18px; margin-bottom: 10px; } .info-panel p { color: #555; font-size: 13px; line-height: 1.4; margin-bottom: 10px; } .search-container { position: absolute; top: 20px; right: 20px; z-index: 10; } .search-box { padding: 10px 15px; width: 200px; border: none; border-radius: 20px; background: rgba(255, 255, 255, 0.9); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); outline: none; font-size: 14px; transition: all 0.3s ease; } .search-box:focus { width: 240px; box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2); } .legend { position: absolute; bottom: 20px; right: 20px; background: rgba(255, 255, 255, 0.9); padding: 10px; border-radius: 8px; z-index: 10; display: flex; flex-direction: column; gap: 5px; font-size: 12px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); } .legend-item { display: flex; align-items: center; gap: 8px; } .legend-color { width: 12px; height: 12px; border-radius: 3px; } /* Ocean details */ .ocean-details { position: absolute; width: 100%; height: 100%; pointer-events: none; } .ocean-wave { position: absolute; border-radius: 50%; background: rgba(255, 255, 255, 0.1); animation: wave 8s infinite linear; } @keyframes wave { 0% { transform: scale(0); opacity: 0.8; } 100% { transform: scale(3); opacity: 0; } } /* Loading animation */ .loading { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: #081f2e; display: flex; justify-content: center; align-items: center; z-index: 1000; transition: opacity 0.5s ease, visibility 0.5s ease; } .loading.hidden { opacity: 0; visibility: hidden; } .loading-animation { width: 100px; height: 100px; position: relative; } .loading-circle { position: absolute; width: 100%; height: 100%; border: 5px solid transparent; border-top-color: #ff3366; border-radius: 50%; animation: spin 1s linear infinite; } .loading-inner-circle { position: absolute; width: 70%; height: 70%; top: 15%; left: 15%; border: 5px solid transparent; border-top-color: #3498db; border-radius: 50%; animation: spin 1.5s linear infinite reverse; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Night mode effects */ .night-mode { position: absolute; width: 100%; height: 100%; background: rgba(0, 10, 30, 0.5); opacity: 0; transition: opacity 1s ease; pointer-events: none; } .night-mode.active { opacity: 1; } .star { position: absolute; width: 2px; height: 2px; background: white; border-radius: 50%; opacity: 0; } .night-toggle { position: absolute; top: 20px; right: 240px; z-index: 10; background: rgba(255, 255, 255, 0.2); border: none; width: 40px; height: 40px; border-radius: 50%; color: white; cursor: pointer; display: flex; justify-content: center; align-items: center; backdrop-filter: blur(5px); transition: all 0.3s ease; } .night-toggle:hover { background: rgba(255, 255, 255, 0.4); } .night-toggle i { font-size: 18px; } /* Custom scroll for info panel */ .custom-scroll { max-height: 120px; overflow-y: auto; padding-right: 5px; } .custom-scroll::-webkit-scrollbar { width: 6px; } .custom-scroll::-webkit-scrollbar-track { background: rgba(0, 0, 0, 0.05); border-radius: 3px; } .custom-scroll::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.2); border-radius: 3px; } .custom-scroll::-webkit-scrollbar-thumb:hover { background: rgba(0, 0, 0, 0.3); } </style> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css"> <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet"> </head> <body> <div class="map-container"> <div class="loading"> <div class="loading-animation"> <div class="loading-circle"></div> <div class="loading-inner-circle"></div> </div> </div> <div class="map-wrapper"> <div class="map"> <div class="terrain"></div> <div class="ocean-details"></div> <div class="continents"> <div class="continent north-america"></div> <div class="continent south-america"></div> <div class="continent europe"></div> <div class="continent africa"></div> <div class="continent asia"></div> <div class="continent australia"></div> </div> </div> </div> <div class="info-panel"> <h2>3D Explorer Map</h2> <div class="custom-scroll"> <p>Welcome to our interactive 3D travel map! Discover stunning destinations across all continents with depth-enhanced visualization.</p> <p>Click on markers to explore detailed information about each location. Use the controls below to navigate the map.</p> </div> </div> <div class="search-container"> <input type="text" class="search-box" placeholder="Search destinations..."> </div> <button class="night-toggle"> <i class="fas fa-moon"></i> </button> <div class="controls"> <button class="control-btn" id="zoom-in"><i class="fas fa-plus"></i></button> <button class="control-btn" id="zoom-out"><i class="fas fa-minus"></i></button> <button class="control-btn" id="tilt-up"><i class="fas fa-angle-up"></i></button> <button class="control-btn" id="tilt-down"><i class="fas fa-angle-down"></i></button> <button class="control-btn" id="reset"><i class="fas fa-sync-alt"></i></button> </div> <div class="legend"> <div class="legend-item"> <div class="legend-color" style="background: linear-gradient(145deg, #27ae60, #2ecc71)"></div> <span>North America</span> </div> <div class="legend-item"> <div class="legend-color" style="background: linear-gradient(145deg, #f39c12, #f1c40f)"></div> <span>South America</span> </div> <div class="legend-item"> <div class="legend-color" style="background: linear-gradient(145deg, #8e44ad, #9b59b6)"></div> <span>Europe</span> </div> <div class="legend-item"> <div class="legend-color" style="background: linear-gradient(145deg, #d35400, #e67e22)"></div> <span>Africa</span> </div> <div class="legend-item"> <div class="legend-color" style="background: linear-gradient(145deg, #c0392b, #e74c3c)"></div> <span>Asia</span> </div> <div class="legend-item"> <div class="legend-color" style="background: linear-gradient(145deg, #2980b9, #3498db)"></div> <span>Australia</span> </div> </div> <div class="night-mode"> <!-- Stars will be added with JavaScript --> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Variables for map manipulation const mapWrapper = document.querySelector('.map-wrapper'); const loading = document.querySelector('.loading'); const nightMode = document.querySelector('.night-mode'); const nightToggle = document.querySelector('.night-toggle'); // Hide loading animation after a delay setTimeout(() => { loading.classList.add('hidden'); }, 1500); // Location data with coordinates adjusted for the map const locations = [ { id: 'nyc', name: 'New York City', continent: 'north-america', position: { left: '25%', top: '27%' }, description: 'The vibrant metropolis offering iconic skylines, Broadway shows, and diverse neighborhoods. Visit in fall for perfect weather.', facts: 'Home to over 8 million people and more than 800 languages', image: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9Pjv/2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozv/wAARCAAyAFYDASIAAhEBAxEB/8QAGwAAAgMBAQEAAAAAAAAAAAAABAUCAwYHAQD/xAA3EAABAwMDAgQEBAMJAAAAAAABAAIDBAUREiExBkETUWFxIoGRoQcUMrEjUsEVJDNCYnKC0fD/xAAZAQADAQEBAAAAAAAAAAAAAAABAgMEAAX/xAAhEQACAgICAgMBAAAAAAAAAAAAAQIRAyESMQRBEyJRcf/aAAwDAQACEQMRAD8A6LbJGnbKlVuAYT2T6jic9jS0ZJWZuL44akyROwQBwua0FFUJrjdY2EvY8sH+k5WNq+oKisc5lOHMaTt5q+KqfV1r2Rt0xnJGOceaGlbHlxdS4Zz2SzyKPRZY3Lo1lm6wnpi0VTpHsG2eMtW9t1yo7hE2SCVuSODuFz+3UnxZlGnvypQ1dRQ1LZYI5JBkY7YHZCGZp0yUsaatHW8gqJdlRslfFdbfFVRHAeNx5FWSkbrcKkTnpDG5R5Gd0Axyk05yUXogxaKIGaXgIl5RkNPpbum1FRuedlOyOXtExwRdSMPJA08LmhclbS7v+E5cdgSF1a9MPYZB2yuWXKUPmlb2aXDb0Cx+Q/Q+NWQpnBrGxtGMK+WNsrTHJjSeRwmVmtkUgErj8fZHyUsQdl2/mlU0kGUW2Z2ktT4JcEZbyD5LTUltp2uL2tBJ5I5VzImZJACnO7TjCVzYYwSVCmooIXHWMq6OFoG3KsEWVItKKVCNo8ZGAp6F6GqQC0CIq0rPVMO4TWsaM5SeVgc5GD0Fg0qo+q9KMDC1pCrVjlv0OPepYjPa5QOcZXMKh4kc1w4cMH3XW73AJaNw8lzCtpC2V7SMgjBWPyNSQ+PsstkmpzQO6b1lJMIdcbiGk53ys9bqlzJOTgHzW0t03iu07Eea5O1aHlG00Y1tMIpNcT9JHKvY8ObkJxfYRgPAGVmI5yHFrgllH2NGX4HxgntlSFNnlQpakPGDypvqmNOCSnoT2TETWjhVGYuO3CrfVgnAKoIc/kpeT9Dfs0dvkLgAUwJ2QPT0JjiDj3R8wxlasCqJnm7Z8VFzfRRlkAaSqcjGUspUgJWZy/UDS8kDlZKpg1NJAyFsLy7AcVlZ3bjzWWStl4uhZLCYnh7eCt9ZalgaGyO38+ywla/RIdR3Rx604l0Odh2VJxvoaMqNgJJJCDge4VUrXnJ3OEx6diZLSMLmg5JGfJQucTYZPEaMNPC5bRVK9CdkjmuBDiFYZSOyc2KnFXkBrQfMBWVFnEbc6gCE6TJuaRRQTvZ4bQdnZP1TPJ+P2VkFGyGLQ0DA5XtRhshHZNGNExlK2ezM1MKqc3yV5ODhUStylcQplFdEHsyUluVmK2LRK4DbdaW5NGnON+yzlfkknJSSjTHjKxZKwO35VrHEAEH0XsrBlVhp7JGhlsYUkr4eQlxpcDnCd0sYYwLM3Wpe25HaRgyYA39EzjasEZUbCgIaAc7r2fcJDbrhHPC0gjV5pkJA4ZTJibKXRbhUOwU0liyhJWrmaI1ZRLyhXhEzDCHcEsisSPyAFna9mk7c8rSyDZZ+4jZwWee0UjpmaMA+J3KvZGQNwqmuzIQrWOx3UzQm6RpbM0vjcD3WK6ohMUhONiuhUmHREHssL1RAGzPI7p8L+1CZVcbE1FMWnBJT63XGR0miQ4dzuk5GFWTgcK7imZ1JxOg09Z4keHHOEY6QFYm0Vbo42gnYJ4JM8laYunZmkqdEZHIeQ5UnnKofJgqjeiD2XSPQjnKyffdRkcjQIvyE2C0DKwt5JM7s+S3U7sRnPksHVHVUP8lmy9lsfQK3dWg5XwKrYVIolHs39qqGmEAnlYjrCcOleDyVpadx8LCzPUZzMQp4dSH8h6ifn7LwkEKDt3L1p3WgzH//Z' }, { id: 'paris', name: 'Paris', continent: 'europe', position: { left: '45.5%', top: '23.5%' }, description: 'The city of lights featuring iconic architecture, world-class cuisine, and romantic ambiance. Best experienced in spring.', facts: 'The Louvre houses over 380,000 objects with only 35,000 on display', image: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9Pjv/2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozv/wAARCAAyAFYDASIAAhEBAxEB/8QAGwAAAgIDAQAAAAAAAAAAAAAAAAYEBQIDBwH/xAA3EAACAQMCAwUGAwcFAAAAAAABAgMABBEFIRIxQQYTUWFxIjKBkaGxFCPBBxVCUmLR8CQzcoLh/8QAGQEAAwEBAQAAAAAAAAAAAAAAAAIDAQQF/8QAHxEAAgICAwEBAQAAAAAAAAAAAAECEQMhEjFBURNh/9oADAMBAAIRAxEAPwDrNFFFABRRUff39vptnJdXcgSNBnzJ8AOpNZKSirZsYuTpGb3EKNwvIitjGASc1EGr6ee7PfcvFggE7gHbHpSPqWpalrl4ZbmU8Iz3ca+6g/U+dR49Q05JF72ESKpwxjbA9RuKjHOpbaovLBxdJ2dCt7q3uxxQSq4HMA7j1FbqS9NlWG5jaBuJVGGRvVeuKcbO5S7tUmQYDDpyI6iujHl5dkMuLh1o2UUUVYkFFFFABULV9Rj0zTpruTHCgwo6segqbSZ+0C+dEtrGM4MpMjjy5D71LLk4Rs6PH8f6Z1EW9S1K51a9e4uXLMTso5Ko/lUdBXO+1upvFfCwt2KrGvG5B3ZuvwFOepAQ6PPIQrBYzkH0rjt5cGWVnbdmOSfM1x+NlbZ1+V436WGoaoEjEFpwogABYe0x8vKokcjC377vMq+Swzgn+ojz6eGKjpGXYKoJJOABzNMVp2ZmVA13dW8GPBH/AL1JscjqqzBpdttdxG77iY4/KeQj0IPIeoFFdP7O6XbWNlGqRr3hA4nxvnxosaKDGybcnZ5RRRVyAUh9upnaWCDoqkk+ZP8A4KfKQ+2LcV9GvRY/uahy/k7PD/U5xq12bmZnO2TsBsB5UuXKnjNTrpQ8pA5DnUe4tSASOlefF0j05K2RTGynI6Vt0+xkvbmO3gUmRzgDoB1J8hW63iKnJ6U8fs90TJbUJRuQTGD5bZrZyotixuTpDVpOn29hZxW8ChURQMDqeoHrRWyiqpUqOZu3YUUUVpgUg9s1zqBP/D/antIXbJMXqt1CMf8AaT+tS8j8nR4/7ODY4ywHhUWdEckMAbcfQVJu45IXZZFIYcjUZ23JJya86T2erF7IZUdaYOwt6YdbRI2/Lni4G8m5r9qWHbByOoqTpV69lfQzoeJUcEkeHX6VqeibV0d8opS0jtdbXCqkzmNX95AcsB4jmDRWYZRyZs8n9KOa7gVwavCiiirCApc7WRlry1I5NER8CKY6g61bmfT5VXBdRxr54/z51PM7gUwupownT1bPtqQfEYP2rHuYifYYA+BqRvtw7j1rCSJTuOIeIINcH09KNWQ5I0SZNxk8htUG4WVPZPIHI8xXpkeJuB+XQitMrIylGZG8mGCKxA5fB17Q9Qi1DS7e6jb3kGR/K3UfOirH2f2Jg0CONv8AckZpCD0ztRXowk5RtnkzioydG+iiirnOFFFFAGDRo/vKD6VqktImBVo1IPMYoorGrM7IDafbhiwjxnngkVoe1jU8QZgfPeiipuEX0UpMt+yVpJp9pJFJjDMWAHIUUUVXFH9QsmXl6FFFFXJn/9k=' }, { id: 'tokyo', name: 'Tokyo', continent: 'asia', position: { left: '83%', top: '32%' }, description: 'A fascinating blend of ultramodern and traditional experiences, cutting-edge technology with ancient temples. Visit during cherry blossom season.', facts: 'Home to over 36 million people in its metropolitan area', image: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9Pjv/2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozv/wAARCAAoAFADASIAAhEBAxEB/8QAGwAAAgMBAQEAAAAAAAAAAAAABQYAAwQHAgH/xAA0EAACAQMCAwUGBQUBAAAAAAABAgMABBEFIQYSMRNBUWGRFCIyUnGBM0KhscEHI2Jy0eH/xAAYAQADAQEAAAAAAAAAAAAAAAABAgMABP/EAB4RAAICAgMBAQAAAAAAAAAAAAABAhEDIRIxQVEi/9oADAMBAAIRAxEAPwDqnE1+bDRJZ4pFSVcFGIztmoWa6ldKsMTEKqjfAAFLfGk4ezjiaTkkc+6y9RTZwxpTWekBpk5biYczA/lXuFNt8mkIoU5Wbl/o2gX9UW0Wxt2nu5jmNFzyjqzHoAKzS67bwsQshYeQpT4umX94sQSSQyyREpHzFULDmLAdAN849aSrKLkdL65EaLl8bYEjlHKSx8TgD7ZpW7ZTd0dLsvbLq+WOziLhm5FPLtk9P+U6tGVKB15R4CucezMTy2+sLcW+ebtJMoQO7PQ/q3pVnDep8V38pgadtLtsAzTvl5PJR3n7Y86Kozcb2dDpN45/b+Id1zSJJJJcXLSXLuxlkbq7HqacdQsba/tHtrqMPG46d48QfGoTadbPEEeNSD3Eb02xHGmLPDlqj30iC1cxxjncMfixjH3plmWPnI5V+wrJa2kNpG6QoFDNzHG2T50Z05QqnbJ8TSzyvwhix9jx7YkUGWYL9TtS7xBqt7cxXNpY3EUDA8sjuCQWHgKcby3W6haKRQwboeorluuWcmi3jvGDy5wcdVbwpccmyuRLwE8N6W41GO7EuAjYHLjYnbNP/D5aysxbWh5Yo9wo6nHU+dK3D2nvqt2zTsVs4mPbTDqzfKvnTzqEkcMJTChVGFQDAAHQAdwp5P0lHGK+uXjIDGrsCPOtYvQCArZNAO15mqTM+PCpcR+QXW81EAlvpYNgX3Hmayx6pdC6NwQsrg4LqCDigxuS2ByptUdsnYHuoXqV0IYSrHlJGM9/0pcOJyVjZZOKsDahK1zOZG8cAeAorwOxtr6Nsd7Bfnml25kLyHO+aO8HTYvGTeUMv
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>3D Analytics Dashboard</title> <style> @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); :root { --primary-color: #2a2a3c; --secondary-color: #1e1e2c; --tertiary-color: #16161f; --accent-color: #6c5ce7; --highlight-color: #00cec9; --text-primary: #ffffff; --text-secondary: #b2b2d8; --text-tertiary: #7575a3; --shadow-color: rgba(0, 0, 0, 0.2); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', sans-serif; } body { background-color: var(--tertiary-color); color: var(--text-primary); height: 100vh; width: 100%; display: flex; justify-content: center; align-items: center; overflow: hidden; } .dashboard-container { width: 680px; height: 680px; background-color: var(--secondary-color); border-radius: 18px; box-shadow: 0 20px 50px rgba(0, 0, 0, 0.3); padding: 20px; display: flex; flex-direction: column; overflow: hidden; position: relative; } .dashboard-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding: 0 10px; } .dashboard-title { font-size: 1.5rem; font-weight: 600; color: var(--text-primary); } .view-controls { display: flex; gap: 15px; } .view-button { background: var(--primary-color); border: none; border-radius: 8px; padding: 8px 15px; color: var(--text-secondary); font-weight: 500; cursor: pointer; transition: all 0.3s ease; font-size: 0.85rem; } .view-button.active { background: var(--accent-color); color: white; } .view-button:hover:not(.active) { background: #353553; } .dashboard-content { display: flex; flex: 1; gap: 20px; } .visualization { flex: 2; background-color: var(--primary-color); border-radius: 14px; box-shadow: 0 4px 12px var(--shadow-color); overflow: hidden; position: relative; display: flex; justify-content: center; align-items: center; perspective: 1000px; } .viz-canvas { width: 100%; height: 100%; position: relative; } .sidebar { flex: 1; display: flex; flex-direction: column; gap: 15px; } .data-card { background-color: var(--primary-color); border-radius: 14px; padding: 15px; box-shadow: 0 4px 12px var(--shadow-color); transition: all 0.3s ease; } .card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; } .card-title { font-size: 0.9rem; color: var(--text-secondary); font-weight: 500; } .card-body { display: flex; flex-direction: column; } .metric { font-size: 1.8rem; font-weight: 700; color: var(--text-primary); margin-bottom: 5px; } .metric-change { font-size: 0.85rem; color: #4cd964; display: flex; align-items: center; gap: 5px; } .negative { color: #ff3b30; } .data-controls { background-color: var(--primary-color); border-radius: 14px; padding: 15px; box-shadow: 0 4px 12px var(--shadow-color); display: flex; flex-direction: column; gap: 15px; } .control-group { display: flex; flex-direction: column; gap: 10px; } .control-group label { font-size: 0.85rem; color: var(--text-secondary); font-weight: 500; } .control-options { display: flex; gap: 10px; } .control-option { background: var(--tertiary-color); border: none; border-radius: 6px; padding: 8px 12px; color: var(--text-tertiary); font-size: 0.85rem; cursor: pointer; transition: all 0.2s ease; } .control-option.selected { background: var(--accent-color); color: white; } .control-option:hover:not(.selected) { background: #24243c; color: var(--text-secondary); } .data-point { position: absolute; width: 30px; height: 30px; border-radius: 50%; background-color: var(--accent-color); display: flex; justify-content: center; align-items: center; transform-style: preserve-3d; cursor: pointer; transition: transform 0.4s ease, box-shadow 0.4s ease; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); } .data-point:hover { transform: translateZ(30px) scale(1.2); box-shadow: 0 12px 30px rgba(0, 0, 0, 0.3); z-index: 10; } .data-point.highlight { background-color: var(--highlight-color); } .data-point-value { font-size: 0.75rem; font-weight: 600; color: white; } .tooltip { position: absolute; background: rgba(24, 24, 36, 0.95); border-radius: 8px; padding: 12px; pointer-events: none; opacity: 0; transition: opacity 0.3s ease; max-width: 200px; font-size: 0.85rem; z-index: 100; box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3); } .tooltip-header { font-weight: 600; color: white; margin-bottom: 5px; } .tooltip-value { color: var(--highlight-color); font-weight: 700; font-size: 1.1rem; } .tooltip-desc { color: var(--text-secondary); margin-top: 5px; font-size: 0.8rem; line-height: 1.4; } .time-range { background-color: var(--primary-color); border-radius: 14px; padding: 15px; margin-top: 20px; } .time-label { font-size: 0.85rem; color: var(--text-secondary); margin-bottom: 10px; } .time-slider { -webkit-appearance: none; width: 100%; height: 4px; background: var(--tertiary-color); border-radius: 2px; outline: none; } .time-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 16px; height: 16px; border-radius: 50%; background: var(--accent-color); cursor: pointer; transition: all 0.2s ease; } .time-slider::-webkit-slider-thumb:hover { transform: scale(1.2); background: var(--highlight-color); } .time-values { display: flex; justify-content: space-between; margin-top: 10px; font-size: 0.75rem; color: var(--text-tertiary); } .axis { position: absolute; background-color: rgba(255, 255, 255, 0.1); transform-style: preserve-3d; } .x-axis, .z-axis { height: 1px; width: 80%; } .y-axis { width: 1px; height: 80%; } .axis-label { position: absolute; color: var(--text-tertiary); font-size: 0.75rem; font-weight: 500; } .grid-line { position: absolute; background-color: rgba(255, 255, 255, 0.05); } .data-layer { position: absolute; width: 80%; height: 80%; transform-style: preserve-3d; transition: transform 0.8s ease; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(108, 92, 231, 0.4); } 70% { box-shadow: 0 0 0 10px rgba(108, 92, 231, 0); } 100% { box-shadow: 0 0 0 0 rgba(108, 92, 231, 0); } } .pulse { animation: pulse 2s infinite; } .rotate-controls { position: absolute; bottom: 15px; right: 15px; display: flex; gap: 10px; } .rotate-button { width: 36px; height: 36px; border-radius: 50%; background: rgba(255, 255, 255, 0.1); border: none; color: var(--text-secondary); cursor: pointer; display: flex; justify-content: center; align-items: center; transition: all 0.2s ease; } .rotate-button:hover { background: var(--accent-color); color: white; } .dimension-toggle { position: absolute; top: 15px; right: 15px; background: rgba(255, 255, 255, 0.1); border-radius: 8px; padding: 5px; display: flex; gap: 5px; } .dimension-button { width: 30px; height: 30px; border-radius: 6px; border: none; background: transparent; color: var(--text-secondary); cursor: pointer; font-size: 0.8rem; font-weight: 600; transition: all 0.2s ease; } .dimension-button.active { background: var(--accent-color); color: white; } .loader { position: absolute; width: 100%; height: 100%; background: var(--primary-color); display: flex; justify-content: center; align-items: center; z-index: 100; opacity: 1; transition: opacity 1s ease; } .loader-circle { width: 60px; height: 60px; border: 5px solid rgba(255, 255, 255, 0.1); border-top: 5px solid var(--highlight-color); border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .hidden { opacity: 0; pointer-events: none; } @media (max-width: 700px) { .dashboard-container { width: 100%; height: 100%; border-radius: 0; } .dashboard-content { flex-direction: column; } .visualization { height: 350px; } .sidebar { display: grid; grid-template-columns: 1fr 1fr; } .time-range { grid-column: span 2; } } </style> </head> <body> <div class="dashboard-container"> <div class="dashboard-header"> <h1 class="dashboard-title">Spatial Market Analysis</h1> <div class="view-controls"> <button class="view-button">Weekly</button> <button class="view-button active">Monthly</button> <button class="view-button">Quarterly</button> </div> </div> <div class="dashboard-content"> <div class="visualization"> <div class="loader"> <div class="loader-circle"></div> </div> <div class="dimension-toggle"> <button class="dimension-button">2D</button> <button class="dimension-button active">3D</button> </div> <div class="viz-canvas" id="visualization"> <!-- 3D visualization will be dynamically created here --> </div> <div class="rotate-controls"> <button class="rotate-button" id="rotate-left"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M9 4L5 8L9 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M5 8H14C17.3137 8 20 10.6863 20 14C20 17.3137 17.3137 20 14 20H9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </button> <button class="rotate-button" id="rotate-right"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M15 4L19 8L15 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M19 8H10C6.68629 8 4 10.6863 4 14C4 17.3137 6.68629 20 10 20H15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </button> </div> <div class="tooltip" id="tooltip"> <div class="tooltip-header">Market Segment</div> <div class="tooltip-value">$24.5M</div> <div class="tooltip-desc">Q3 performance exceeding forecasts by 17%, driving growth in the enterprise sector.</div> </div> </div> <div class="sidebar"> <div class="data-card"> <div class="card-header"> <div class="card-title">REVENUE INSIGHTS</div> </div> <div class="card-body"> <div class="metric">$127.8M</div> <div class="metric-change"> <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 5L12 19M12 5L18 11M12 5L6 11" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> 18.7% vs Last Period </div> </div> </div> <div class="data-card"> <div class="card-header"> <div class="card-title">CONVERSION RATE</div> </div> <div class="card-body"> <div class="metric">8.3%</div> <div class="metric-change"> <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 5L12 19M12 5L18 11M12 5L6 11" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> 2.1% vs Last Period </div> </div> </div> <div class="data-controls"> <div class="control-group"> <label>Data Layer</label> <div class="control-options"> <button class="control-option selected">Revenue</button> <button class="control-option">Growth</button> <button class="control-option">Users</button> </div> </div> <div class="control-group"> <label>Segmentation</label> <div class="control-options"> <button class="control-option selected">Market</button> <button class="control-option">Region</button> <button class="control-option">Product</button> </div> </div> </div> <div class="time-range"> <div class="time-label">Time Range: Q1 2023 - Q4 2023</div> <input type="range" min="0" max="12" value="8" class="time-slider" id="time-slider"> <div class="time-values"> <span>Jan 2023</span> <span>Dec 2023</span> </div> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Wait for a moment to simulate loading setTimeout(() => { document.querySelector('.loader').classList.add('hidden'); initVisualization(); }, 1200); // Get DOM elements const vizContainer = document.getElementById('visualization'); const tooltip = document.getElementById('tooltip'); const rotateLeftBtn = document.getElementById('rotate-left'); const rotateRightBtn = document.getElementById('rotate-right'); const timeSlider = document.getElementById('time-slider'); // Rotation state let rotationY = 15; let rotationX = 15; function initVisualization() { // Create 3D space with axes createAxes(); createDataPoints(); // Set initial rotation updateRotation(); // Add event listeners for controls setupEventListeners(); } function createAxes() { // Create the main data layer that will hold everything const dataLayer = document.createElement('div'); dataLayer.className = 'data-layer'; dataLayer.id = 'data-layer'; vizContainer.appendChild(dataLayer); // X-axis (width) const xAxis = document.createElement('div'); xAxis.className = 'axis x-axis'; xAxis.style.bottom = '10%'; xAxis.style.left = '10%'; xAxis.style.transform = 'translateZ(0)'; dataLayer.appendChild(xAxis); // X-axis label const xLabel = document.createElement('div'); xLabel.className = 'axis-label'; xLabel.textContent = 'Market Segments'; xLabel.style.bottom = '5%'; xLabel.style.left = '50%'; xLabel.style.transform = 'translateX(-50%)'; dataLayer.appendChild(xLabel); // Y-axis (height) const yAxis = document.createElement('div'); yAxis.className = 'axis y-axis'; yAxis.style.bottom = '10%'; yAxis.style.left = '10%'; yAxis.style.transform = 'translateY(-50%)'; dataLayer.appendChild(yAxis); // Y-axis label const yLabel = document.createElement('div'); yLabel.className = 'axis-label'; yLabel.textContent = 'Revenue ($M)'; yLabel.style.left = '5%'; yLabel.style.top = '50%'; yLabel.style.transform = 'rotate(-90deg) translateX(50%)'; dataLayer.appendChild(yLabel); // Z-axis (depth) const zAxis = document.createElement('div'); zAxis.className = 'axis z-axis'; zAxis.style.bottom = '10%'; zAxis.style.left = '10%'; zAxis.style.transform = 'rotateY(90deg) translateZ(0)'; dataLayer.appendChild(zAxis); // Z-axis label const zLabel = document.createElement('div'); zLabel.className = 'axis-label'; zLabel.textContent = 'Time (Quarters)'; zLabel.style.left = '10%'; zLabel.style.bottom = '5%'; zLabel.style.transform = 'rotateY(90deg) translateX(-50%)'; dataLayer.appendChild(zLabel); // Add grid lines for (let i = 1; i <= 4; i++) { // X grid lines const xGrid = document.createElement('div'); xGrid.className = 'grid-line'; xGrid.style.height = '1px'; xGrid.style.width = '80%'; xGrid.style.bottom = `${10 + i * 15}%`; xGrid.style.left = '10%'; dataLayer.appendChild(xGrid); // Z grid lines const zGrid = document.createElement('div'); zGrid.className = 'grid-line'; zGrid.style.height = '1px'; zGrid.style.width = '80%'; zGrid.style.bottom = '10%'; zGrid.style.left = '10%'; zGrid.style.transform = `rotateY(90deg) translateZ(${i * 60}px)`; dataLayer.appendChild(zGrid); } } function createDataPoints() { const dataLayer = document.getElementById('data-layer'); // Sample data points for the visualization // Each array is a "layer" representing a time period (z-axis) // Within each layer, points represent different market segments with revenue values const dataPoints = [ // Layer 1 (Q1) [ { x: 20, y: 30, z: 0, value: 12, label: 'Enterprise', highlight: false }, { x: 40, y: 25, z: 0, value: 9, label: 'SMB', highlight: false }, { x: 60, y: 15, z: 0, value: 5, label: 'Consumer', highlight: false }, { x: 80, y: 20, z: 0, value: 7, label: 'Government', highlight: false } ], // Layer 2 (Q2) [ { x: 20, y: 35, z: 60, value: 14, label: 'Enterprise', highlight: false }, { x: 40, y: 30, z: 60, value: 12, label: 'SMB', highlight: false }, { x: 60, y: 18, z: 60, value: 6, label: 'Consumer', highlight: false }, { x: 80, y: 25, z: 60, value: 10, label: 'Government', highlight: false } ], // Layer 3 (Q3) [ { x: 20, y: 45, z: 120, value: 21, label: 'Enterprise', highlight: true }, { x: 40, y: 35, z: 120, value: 15, label: 'SMB', highlight: false }, { x: 60, y: 25, z: 120, value: 9, label: 'Consumer', highlight: false }, { x: 80, y: 30, z: 120, value: 13, label: 'Government', highlight: true } ], // Layer 4 (Q4) [ { x: 20, y: 50, z: 180, value: 25, label: 'Enterprise', highlight: true }, { x: 40, y: 40, z: 180, value: 18, label: 'SMB', highlight: true }, { x: 60, y: 30, z: 180, value: 12, label: 'Consumer', highlight: false }, { x: 80, y: 35, z: 180, value: 15, label: 'Government', highlight: false } ] ]; // Create and position data points dataPoints.forEach(layer => { layer.forEach(point => { const dataPoint = document.createElement('div'); dataPoint.className = `data-point ${point.highlight ? 'highlight' : ''}`; // Size based on value (proportional to data value) const size = 15 + point.value * 1.5; dataPoint.style.width = `${size}px`; dataPoint.style.height = `${size}px`; // Position in 3D space dataPoint.style.left = `${point.x}%`; dataPoint.style.bottom = `${point.y + 10}%`; // +10 to align with axis dataPoint.style.transform = `translateZ(${point.z}px)`; // Add data value const valueEl = document.createElement('div'); valueEl.className = 'data-point-value'; valueEl.textContent = point.value; dataPoint.appendChild(valueEl); // Add to the layer dataLayer.appendChild(dataPoint); // Add hover tooltip effect dataPoint.addEventListener('mouseenter', e => { const rect = dataPoint.getBoundingClientRect(); tooltip.innerHTML = ` <div class="tooltip-header">${point.label} Segment</div> <div class="tooltip-value">$${point.value}.5M</div> <div class="tooltip-desc"> ${getTooltipDescription(point.label, point.value, point.highlight)} </div> `; tooltip.style.left = `${rect.left + rect.width/2}px`; tooltip.style.top = `${rect.top - tooltip.offsetHeight - 10}px`; tooltip.style.transform = 'translateX(-50%)'; tooltip.style.opacity = '1'; dataPoint.classList.add('pulse'); }); dataPoint.addEventListener('mouseleave', () => { tooltip.style.opacity = '0'; dataPoint.classList.remove('pulse'); }); }); }); } function getTooltipDescription(segment, value, highlight) { switch(segment) { case 'Enterprise': return highlight ? `Major enterprise clients driving exceptional revenue growth. ${value}% increase in contract renewals.` : `Enterprise segment performing steadily with gradual growth in recurring revenue.`; case 'SMB': return highlight ? `SMB sector exceeding targets with expanded product adoption. New client acquisition up ${value}%.` : `Small and medium business sector showing consistent performance.`; case 'Consumer': return `Consumer market steadily growing with ${value}% subscription rate. Focus area for expansion.`; case 'Government': return highlight ? `Public sector contracts driving stable revenue. Secured ${value} new agencies this quarter.` : `Government sector maintaining baseline performance with renewal focus.`; default: return `This segment represents $${value}.5M in quarterly revenue.`; } } function updateRotation() { const dataLayer = document.getElementById('data-layer'); if (dataLayer) { dataLayer.style.transform = `rotateY(${rotationY}deg) rotateX(${rotationX}deg)`; } } function setupEventListeners() { // Rotation controls rotateLeftBtn.addEventListener('click', () => { rotationY -= 30; updateRotation(); }); rotateRightBtn.addEventListener('click', () => { rotationY += 30; updateRotation(); }); // Mouse drag rotation let isDragging = false; let startX, startY; vizContainer.addEventListener('mousedown', (e) => { isDragging = true; startX = e.clientX; startY = e.clientY; vizContainer.style.cursor = 'grabbing'; }); document.addEventListener('mousemove', (e) => { if (isDragging) { const deltaX = e.clientX - startX; const deltaY = e.clientY - startY; rotationY += deltaX * 0.5; rotationX = Math.max(-30, Math.min(30, rotationX - deltaY * 0.5)); updateRotation(); startX = e.clientX; startY = e.clientY; } }); document.addEventListener('mouseup', () => { isDragging = false; vizContainer.style.cursor = 'grab'; }); // Time slider timeSlider.addEventListener('input', (e) => { const value = parseInt(e.target.value); // Update visualization based on time slider // This would adjust which layers are highlighted, etc. }); // Toggle buttons document.querySelectorAll('.control-option').forEach(btn => { btn.addEventListener('click', (e) => { // Remove selected class from all siblings e.target.parentNode.querySelectorAll('.control-option').forEach(b => { b.classList.remove('selected'); }); // Add selected class to clicked button e.target.classList.add('selected'); }); }); document.querySelectorAll('.view-button').forEach(btn => { btn.addEventListener('click', (e) => { document.querySelectorAll('.view-button').forEach(b => { b.classList.remove('active'); }); e.target.classList.add('active'); }); }); document.querySelectorAll('.dimension-button').forEach(btn => { btn.addEventListener('click', (e) => { document.querySelectorAll('.dimension-button').forEach(b => { b.classList.remove('active'); }); e.target.classList.add('active'); // Toggle between 2D and 3D views if (e.target.textContent === '2D') { rotationY = 0; rotationX = 0; updateRotation(); } else { rotationY = 15; rotationX = 15; updateRotation(); } }); }); } }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Virtuoso Spaces - 3D Virtual Real Estate Tours</title> <style> /* Reset and Base Styles */ * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Montserrat', sans-serif; } :root { --primary: #e8a87c; --secondary: #41b3a3; --dark: #2c3e50; --light: #f9f7f7; --accent: #e27d60; --overlay: rgba(44, 62, 80, 0.7); --shadow: 0 10px 20px rgba(0, 0, 0, 0.2); --transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1); } body { background-color: var(--light); color: var(--dark); overflow: hidden; width: 100%; height: 100vh; max-width: 700px; max-height: 700px; } /* Container Styles */ .container { width: 100%; height: 100%; max-width: 700px; max-height: 700px; position: relative; overflow: hidden; } /* Navigation Styles */ .nav { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); display: flex; gap: 15px; z-index: 100; background: rgba(255, 255, 255, 0.9); padding: 12px 20px; border-radius: 40px; box-shadow: var(--shadow); backdrop-filter: blur(10px); } .nav-btn { background: none; border: none; color: var(--dark); font-size: 14px; font-weight: 600; padding: 8px 15px; border-radius: 20px; cursor: pointer; transition: var(--transition); position: relative; overflow: hidden; } .nav-btn:before { content: ''; position: absolute; top: 0; left: 0; width: 0; height: 100%; background-color: var(--primary); transition: var(--transition); z-index: -1; opacity: 0.2; border-radius: 20px; } .nav-btn:hover:before { width: 100%; } .nav-btn.active { color: var(--secondary); background-color: rgba(65, 179, 163, 0.1); } /* Scene Container Styles */ .scene-container { position: relative; width: 100%; height: 100%; overflow: hidden; perspective: 1200px; } .scene { position: absolute; width: 100%; height: 100%; opacity: 0; transform: translateZ(-100px); transition: all 1.2s cubic-bezier(0.645, 0.045, 0.355, 1); pointer-events: none; z-index: 1; } .scene.active { opacity: 1; transform: translateZ(0); pointer-events: all; z-index: 2; } .scene img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s ease; } /* Hotspot Styles */ .hotspot { position: absolute; width: 40px; height: 40px; transform: translate(-50%, -50%); cursor: pointer; z-index: 10; transition: transform 0.3s ease; } .hotspot:before { content: ''; position: absolute; width: 20px; height: 20px; background-color: var(--primary); border-radius: 50%; top: 50%; left: 50%; transform: translate(-50%, -50%); box-shadow: 0 0 0 5px rgba(232, 168, 124, 0.3); animation: pulse 2s infinite; } .hotspot:after { content: ''; position: absolute; width: 0; height: 0; border-left: 8px solid transparent; border-right: 8px solid transparent; border-top: 12px solid var(--primary); top: 100%; left: 50%; transform: translateX(-50%); opacity: 0; transition: all 0.3s ease; } .hotspot:hover { transform: translate(-50%, -50%) scale(1.1); } .hotspot:hover:after { opacity: 1; top: 85%; } @keyframes pulse { 0% { transform: translate(-50%, -50%) scale(1); box-shadow: 0 0 0 0 rgba(232, 168, 124, 0.7); } 70% { transform: translate(-50%, -50%) scale(1.1); box-shadow: 0 0 0 10px rgba(232, 168, 124, 0); } 100% { transform: translate(-50%, -50%) scale(1); box-shadow: 0 0 0 0 rgba(232, 168, 124, 0); } } /* Info Panel Styles */ .info-panel { position: absolute; top: 30px; right: 30px; background: rgba(255, 255, 255, 0.95); padding: 20px; border-radius: 10px; box-shadow: var(--shadow); max-width: 300px; transform: translateX(400px); transition: var(--transition); z-index: 50; backdrop-filter: blur(10px); } .info-panel.visible { transform: translateX(0); } .info-panel h3 { color: var(--secondary); margin-bottom: 10px; font-size: 18px; position: relative; padding-bottom: 8px; } .info-panel h3:after { content: ''; position: absolute; bottom: 0; left: 0; height: 3px; width: 40px; background-color: var(--primary); border-radius: 3px; } .info-panel p { font-size: 14px; line-height: 1.5; margin-bottom: 15px; color: var(--dark); } .info-panel .close { position: absolute; top: 10px; right: 10px; background: none; border: none; font-size: 18px; cursor: pointer; color: var(--dark); transition: var(--transition); } .info-panel .close:hover { color: var(--accent); transform: rotate(90deg); } .info-stat { display: flex; align-items: center; margin-bottom: 8px; } .info-stat-icon { width: 20px; height: 20px; margin-right: 10px; color: var(--secondary); } /* Controls Styles */ .controls { position: fixed; top: 20px; left: 20px; z-index: 100; display: flex; flex-direction: column; gap: 10px; } .control-btn { width: 40px; height: 40px; border-radius: 50%; background: rgba(255, 255, 255, 0.9); border: none; display: flex; align-items: center; justify-content: center; box-shadow: var(--shadow); cursor: pointer; transition: var(--transition); color: var(--dark); } .control-btn:hover { background: var(--primary); color: white; } /* Cursor Style */ .custom-cursor { position: fixed; width: 40px; height: 40px; pointer-events: none; z-index: 9999; transform: translate(-50%, -50%); mix-blend-mode: difference; display: none; } .cursor-circle { position: absolute; width: 10px; height: 10px; background-color: white; border-radius: 50%; top: 50%; left: 50%; transform: translate(-50%, -50%); transition: width 0.3s, height 0.3s; } .cursor-ring { position: absolute; width: 30px; height: 30px; border: 2px solid white; border-radius: 50%; top: 50%; left: 50%; transform: translate(-50%, -50%); transition: all 0.1s ease-out; } .loading-screen { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: var(--light); display: flex; flex-direction: column; justify-content: center; align-items: center; z-index: 1000; transition: opacity 0.5s ease-out; } .loading-logo { font-size: 24px; font-weight: 800; color: var(--secondary); margin-bottom: 20px; letter-spacing: 1px; } .loading-bar-container { width: 200px; height: 4px; background-color: rgba(65, 179, 163, 0.2); border-radius: 4px; overflow: hidden; position: relative; } .loading-bar { position: absolute; top: 0; left: 0; height: 100%; width: 0; background-color: var(--secondary); transition: width 0.4s ease; } .loading-text { margin-top: 15px; font-size: 14px; color: var(--dark); opacity: 0.8; } /* Tooltip */ .tooltip { position: absolute; background: rgba(0, 0, 0, 0.8); color: white; padding: 5px 10px; border-radius: 4px; font-size: 12px; pointer-events: none; opacity: 0; transition: opacity 0.3s; z-index: 1000; white-space: nowrap; } /* Responsive Styles */ @media (max-width: 600px) { .nav { bottom: 10px; padding: 8px 12px; } .nav-btn { font-size: 12px; padding: 6px 10px; } .info-panel { top: 20px; right: 20px; max-width: 250px; } .controls { top: 10px; left: 10px; } .control-btn { width: 35px; height: 35px; } } /* Property Features Badge */ .property-badge { position: absolute; bottom: 20px; left: 20px; background: rgba(255, 255, 255, 0.9); padding: 10px 15px; border-radius: 8px; box-shadow: var(--shadow); display: flex; align-items: center; gap: 15px; backdrop-filter: blur(10px); z-index: 50; } .badge-item { display: flex; flex-direction: column; align-items: center; } .badge-icon { font-size: 18px; color: var(--secondary); margin-bottom: 5px; } .badge-text { font-size: 12px; font-weight: 600; color: var(--dark); } /* Panorama View Controls */ .panorama-controls { position: absolute; bottom: 20px; right: 20px; z-index: 50; display: flex; flex-direction: column; gap: 10px; opacity: 0; transition: opacity 0.3s ease; } .scene.panorama-mode .panorama-controls { opacity: 1; } .panorama-btn { width: 40px; height: 40px; border-radius: 50%; background: rgba(255, 255, 255, 0.9); border: none; display: flex; align-items: center; justify-content: center; box-shadow: var(--shadow); cursor: pointer; transition: var(--transition); color: var(--dark); } .panorama-btn:hover { background: var(--primary); color: white; } /* Draggable Indicator */ .drag-indicator { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(255, 255, 255, 0.7); padding: 10px 20px; border-radius: 30px; font-size: 14px; color: var(--dark); display: flex; align-items: center; gap: 10px; pointer-events: none; opacity: 0; transition: opacity 0.5s; z-index: 100; } .scene.panorama-mode:hover .drag-indicator { opacity: 1; animation: fadeOut 2s forwards; animation-delay: 2s; } @keyframes fadeOut { to { opacity: 0; } } /* Minimap */ .minimap { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); width: 120px; height: 120px; background: rgba(255, 255, 255, 0.9); border-radius: 8px; box-shadow: var(--shadow); padding: 10px; z-index: 100; backdrop-filter: blur(5px); opacity: 0; transition: opacity 0.3s; } .minimap.visible { opacity: 1; } .minimap-content { position: relative; width: 100%; height: 100%; background-color: #f1f1f1; border-radius: 4px; overflow: hidden; } .minimap-room { position: absolute; background-color: #d9d9d9; border: 1px solid #bbb; } .minimap-room.active { background-color: var(--secondary); border-color: var(--secondary); } .minimap-marker { position: absolute; width: 8px; height: 8px; background-color: var(--accent); border-radius: 50%; transform: translate(-50%, -50%); transition: left 0.3s, top 0.3s; } </style> </head> <body> <div class="loading-screen"> <div class="loading-logo">VIRTUOSO SPACES</div> <div class="loading-bar-container"> <div class="loading-bar"></div> </div> <div class="loading-text">Loading your immersive experience...</div> </div> <div class="custom-cursor"> <div class="cursor-circle"></div> <div class="cursor-ring"></div> </div> <div class="container"> <div class="scene-container"> <div class="scene active" id="livingRoom"> <img src="https://images.unsplash.com/photo-1600121848594-d8644e57abab?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1600&h=900&q=80" alt="Modern Living Room"> <div class="hotspot" style="top: 45%; left: 75%;" data-target="kitchen" data-info="kitchen-info"></div> <div class="hotspot" style="top: 60%; left: 30%;" data-info="livingroom-features"></div> </div> <div class="scene" id="kitchen"> <img src="https://images.unsplash.com/photo-1556911220-bff31c812dba?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1600&h=900&q=80" alt="Luxury Kitchen"> <div class="hotspot" style="top: 50%; left: 20%;" data-target="livingRoom" data-info="living-info"></div> <div class="hotspot" style="top: 40%; left: 80%;" data-target="bedroom" data-info="bedroom-info"></div> <div class="hotspot" style="top: 70%; left: 60%;" data-info="kitchen-features"></div> </div> <div class="scene" id="bedroom"> <img src="https://images.unsplash.com/photo-1616594039964-ae9021a400a0?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1600&h=900&q=80" alt="Master Bedroom"> <div class="hotspot" style="top: 50%; left: 30%;" data-target="kitchen" data-info="kitchen-info"></div> <div class="hotspot" style="top: 60%; left: 70%;" data-target="bathroom" data-info="bathroom-info"></div> <div class="hotspot" style="top: 40%; left: 50%;" data-info="bedroom-features"></div> </div> <div class="scene" id="bathroom"> <img src="https://images.unsplash.com/photo-1552321554-5fefe8c9ef14?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1600&h=900&q=80" alt="Luxury Bathroom"> <div class="hotspot" style="top: 50%; left: 20%;" data-target="bedroom" data-info="bedroom-info"></div> <div class="hotspot" style="top: 60%; left: 50%;" data-info="bathroom-features"></div> </div> <div class="drag-indicator"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8 5L5 8M5 8L8 11M5 8H13M16 13L13 16M13 16L16 19M13 16H19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> Click and drag to explore </div> <div class="panorama-controls"> <button class="panorama-btn zoom-in"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 5V19M5 12H19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </button> <button class="panorama-btn zoom-out"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </button> <button class="panorama-btn reset-view"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M3 12C3 16.9706 7.02944 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M9 9L3 12L9 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </button> </div> </div> <div class="property-badge"> <div class="badge-item"> <div class="badge-icon"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M9 22V12H15V22M3 9L12 2L21 9V20C21 20.5304 20.7893 21.0391 20.4142 21.4142C20.0391 21.7893 19.5304 22 19 22H5C4.46957 22 3.96086 21.7893 3.58579 21.4142C3.21071 21.0391 3 20.5304 3 20V9Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <div class="badge-text">4 Beds</div> </div> <div class="badge-item"> <div class="badge-icon"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19M5 12C3.89543 12 3 11.1046 3 10V6C3 4.89543 3.89543 4 5 4H19C20.1046 4 21 4.89543 21 6V10C21 11.1046 20.1046 12 19 12M5 12V19C5 20.1046 5.89543 21 7 21H17C18.1046 21 19 20.1046 19 19V12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <div class="badge-text">3 Baths</div> </div> <div class="badge-item"> <div class="badge-icon"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M4 22H20M7 10.5V17M17 10.5V17M6 2H18C19.1046 2 20 2.89543 20 4V17C20 18.1046 19.1046 19 18 19H6C4.89543 19 4 18.1046 4 17V4C4 2.89543 4.89543 2 6 2Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <div class="badge-text">2,450 sq ft</div> </div> </div> <div class="info-panel" id="livingroom-features"> <button class="close">×</button> <h3>Living Room Highlights</h3> <p>Thoughtfully designed open concept space with floor-to-ceiling windows that flood the room with natural light.</p> <div class="info-stat"> <div class="info-stat-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 3V5M12 19V21M5 12H3M21 12H19M18.364 5.636L16.95 7.05M7.05 16.95L5.636 18.364M7.05 7.05L5.636 5.636M18.364 18.364L16.95 16.95M16 12C16 14.2091 14.2091 16 12 16C9.79086 16 8 14.2091 8 12C8 9.79086 9.79086 8 12 8C14.2091 8 16 9.79086 16 12Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <span>South-facing windows with excellent natural light</span> </div> <div class="info-stat"> <div class="info-stat-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M9 5H7C5.89543 5 5 5.89543 5 7V19C5 20.1046 5.89543 21 7 21H17C18.1046 21 19 20.1046 19 19V7C19 5.89543 18.1046 5 17 5H15M9 5C9 6.10457 9.89543 7 11 7H13C14.1046 7 15 6.10457 15 5M9 5C9 3.89543 9.89543 3 11 3H13C14.1046 3 15 3.89543 15 5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <span>Custom built-in cabinetry with ambient lighting</span> </div> <div class="info-stat"> <div class="info-stat-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8 14V17M12 14V17M16 14V17M3 21H21M3 10H21M3 7L12 3L21 7M4 10V21H20V10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> <span>Hand-scraped hardwood floors with radiant heating</span> </div> </div> <div class="info-panel" id="kitchen-features"> <button class="close">×</button> <h3>Designer Kitchen</h3> <p>Gourmet kitchen featuring premium quartz countertops and a waterfall island perfect for entertaining.</p> <div class="info-stat"> <div class="info-stat-icon"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M19.4 15C19.2669 15.3016 19.2272 15.6362 19.286 15.9606C19.3448 16.285 19.4995 16.5843 19.73 16.82L19.79 16.88C19.976 17.0657 20.1235 17.2863 20.2241 17.5291C20.3248 17.7719 20.3766 18.0322 20.3766 18.295C20.3766 18.5578 20.3248 18.8181 20.2241 19.0609C20.1235 19.3037 19.976 19.5243 19.79 19.71C19.6043 19.896 19.3837 20.0435 19.1409 20.1441C18.8981 20.2448 18.6378 20.2966 18.375 20.2966C18.1122 20.2966 17.8519 20.2448 17.6091 20.1441C17.3663 20.0435 17.1457 19.896 16.96 19.71L16.9 19.65C16.6643 19.4195 16.365 19.2648 16.0406 19.206C15.7162 19.1472 15.3816 19.1869 15.08 19.32C14.7842 19.4468 14.532 19.6572 14.3543 19.9255C14.1766 20.1938 14.0813 20.5082 14.08 20.83V21C14.08 21.5304 13.8693 22.0391 13.4942 22.4142C13.1191 22.7893 12.6104 23 12.08 23C11.5496 23 11.0409 22.7893 10.6658 22.4142C10.2907 22.0391 10.08 21.5304 10.08 21V20.91C10.0723 20.579 9.96512 20.258 9.77251 19.9887C9.5799 19.7194 9.31074 19.5143 9 19.4C8.69838 19.2669 8.36381 19.2272 8.03941 19.286C7.71502 19.3448 7.41568 19.4995 7.18 19.73L7.12 19.79C6.93425 19.976 6.71368 20.1235 6.47088 20.2241C6.22808 20.3248 5.96783 20.3766 5.705 20.3766C5.44217 20.3766 5.18192 20.3248 4.93912 20.2241C4.69632 20.1235 4.47575 19.976 4.29 19.79C4.10405 19.6043 3.95653 19.3837 3.85588 19.1409C3.75523 18.8981 3.70343 18.6378 3.70343 18.375C3.70343 18.1122 3.75523 17.8519 3.85588 17.6091C3.95653 17.3663 4.10405 17.1457 4.29 16.96L4.35 16.9C4.58054 16.6643 4.73519 16.365 4.794 16.0406C4.85282 15.7162 4.81312 15.3816 4.68 15.08C4.55324 14.7842 4.34276 14.532 4.07447 14.3543C3.80618 14.1766 3.49179 14.0813 3.17 14.08H3C2.46957 14.08 1.96086 13.8693 1.58579 13.4942C1.21071 13.1191 1 12.6104 1 12.08C1 11.5496 1.21071 11.0409 1.58579 10.6658C1.96086 10.2907 2.46957 10.08 3 10.08H3.09C3.42099 10.0723 3.742 9.96512 4.0113 9.77251C4.28059 9.5799 4.48572 9.31074 4.6 9C4.73312 8.69838 4.77282 8.36381 4.714 8.03941C4.65519 7.71502 4.50054 7.41568 4.27 7.18L4.21 7.12C4.02405 6.93425 3.87653 6.71368 3.77588 6.47088C3.67523 6.22808 3.62343 5.96783 3.62343 5.705C3.62343 5.44217 3.67523 5.18192 3.77588 4.93912C3.87653 4.69632 4.02405 4.47575 4.21 4.29C4.39575 4.10405 4.61632 3.95653 4.85912 3.85588C5.10192 3.75523 5.36217 3.70343 5.625 3.70343C5.88783 3.70343 6.14808 3.75523 6.39088 3.85588C6.63368 3.95653 6.85425 4.10405 7.04 4.29L7.1 4.35C7.33568 4.58054 7.63502 4.73519 7.95941 4.794C8.28381 4.85282 8.61838 4.81312 8.92 4.68H9C9.29577 4.55324 9.54802 4.34276 9.72569 4.07447C9.90337 3.80618 9.99872 3.49179 10 3.17V3C10 2.46957 10.2107 1.96086 10.5858 1.58579C10.9609 1.21071 11.4696 1 12 1C12.5304 1 13.0391 1.21071 13.4142 1.58579C13.7893 1.96086 14 2.46957 14 3V3.09C14.0013 3.41179 14.0966 3.72618 14.2743 3.99447C14.452 4.26276 14.7042 4.47324 15 4.6C15.3016 4.73312 15.6362 4.77282 15.9606 4.714C16.285 4.65519 16.5843 4.50054 16.82 4.27L16.88 4.21C17.0657 4.02405 17.2863 3.87653 17.5291 3.77588C17.7719 3.67523 18.0322 3.62343 18.295 3.62343C18.5578 3.62343 18.8181 3.67523 19.0609 3.77588C19.3037 3.87653 19.5243 4.02405 19.71 4.21C19.896 4.39575 20.0435 4.61632 20.1441 4.85912C20.2448 5.10192 20.2966 5.36217 20.2966 5.625C20.2966 5.88783 20.2448 6.14808 20.1441 6.39088C20.0435 6.63368 19.896 6.85425 19.71 7.04L19.65
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>NEXUS FRONTIER | 3D Game Menu</title> <style> @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700;900&family=Rajdhani:wght@300;500;700&display=swap'); :root { --neon-blue: #00f3ff; --neon-purple: #9000ff; --neon-pink: #ff00e5; --dark-blue: #030b1c; --light-blue: #062056; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Rajdhani', sans-serif; } body { background-color: var(--dark-blue); color: white; width: 100%; height: 100vh; overflow: hidden; perspective: 1000px; } #container { width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; position: relative; overflow: hidden; } #particles { position: absolute; width: 100%; height: 100%; z-index: 1; } .menu-container { position: relative; width: 600px; max-width: 90%; height: 600px; max-height: 90vh; transform-style: preserve-3d; transition: transform 1.5s ease-in-out; z-index: 3; } .title { position: absolute; top: 15%; left: 50%; transform: translateX(-50%); z-index: 5; text-align: center; width: 100%; } .title h1 { font-family: 'Orbitron', sans-serif; font-size: 3.5rem; font-weight: 900; letter-spacing: 2px; margin-bottom: 0.5rem; text-shadow: 0 0 15px var(--neon-blue), 0 0 25px var(--neon-purple); background: linear-gradient(90deg, var(--neon-blue), var(--neon-purple), var(--neon-pink)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; animation: title-glow 3s ease-in-out infinite alternate; } .title .subtitle { font-size: 1.2rem; font-weight: 300; color: rgba(255, 255, 255, 0.7); letter-spacing: 3px; text-transform: uppercase; } #menu-ring { position: absolute; width: 400px; height: 400px; top: calc(50% - 200px); left: calc(50% - 200px); border: 3px solid rgba(0, 243, 255, 0.2); border-radius: 50%; transform-style: preserve-3d; animation: rotate 20s linear infinite; box-shadow: 0 0 50px var(--neon-blue), inset 0 0 30px rgba(0, 243, 255, 0.2); } #inner-ring { position: absolute; width: 250px; height: 250px; top: calc(50% - 125px); left: calc(50% - 125px); border: 2px solid rgba(144, 0, 255, 0.2); border-radius: 50%; transform-style: preserve-3d; animation: rotate 15s linear infinite reverse; box-shadow: 0 0 30px var(--neon-purple), inset 0 0 20px rgba(144, 0, 255, 0.2); } .menu-btn { position: absolute; transform-style: preserve-3d; transform-origin: 200px; width: 160px; height: 60px; z-index: 2; border-radius: 10px; backdrop-filter: blur(5px); background: rgba(6, 32, 86, 0.2); border: 1px solid rgba(255, 255, 255, 0.1); box-shadow: 0 0 20px rgba(0, 243, 255, 0.3); transition: all 0.5s ease; display: flex; justify-content: center; align-items: center; cursor: pointer; overflow: hidden; text-decoration: none; } .menu-btn::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); transition: 0.7s; } .menu-btn:hover::before { left: 100%; } .menu-btn:hover { transform: translateZ(20px) scale(1.1); box-shadow: 0 0 25px var(--neon-blue); background: rgba(6, 32, 86, 0.6); border: 1px solid var(--neon-blue); } .menu-btn span { color: white; font-family: 'Orbitron', sans-serif; font-size: 1.2rem; font-weight: 500; letter-spacing: 1px; z-index: 1; text-shadow: 0 0 5px var(--neon-blue); } .menu-btn .btn-icon { margin-right: 10px; font-size: 1.3rem; color: var(--neon-blue); } #btn1 { transform: rotateY(0deg) translateZ(200px) translateX(-80px); } #btn2 { transform: rotateY(72deg) translateZ(200px) translateX(-80px); } #btn3 { transform: rotateY(144deg) translateZ(200px) translateX(-80px); } #btn4 { transform: rotateY(216deg) translateZ(200px) translateX(-80px); } #btn5 { transform: rotateY(288deg) translateZ(200px) translateX(-80px); } .center-orb { position: absolute; width: 80px; height: 80px; top: calc(50% - 40px); left: calc(50% - 40px); background: radial-gradient(circle, var(--light-blue) 0%, var(--dark-blue) 70%); border-radius: 50%; box-shadow: 0 0 30px var(--neon-blue), inset 0 0 20px rgba(144, 0, 255, 0.6); animation: pulse 4s ease-in-out infinite alternate; } .center-orb::before { content: ''; position: absolute; width: 60px; height: 60px; top: 10px; left: 10px; background: transparent; border-radius: 50%; box-shadow: inset 0 0 15px var(--neon-blue); } .radar-line { position: absolute; width: 200px; height: 2px; background: linear-gradient(90deg, transparent, var(--neon-blue)); top: calc(50% - 1px); left: 50%; transform-origin: left; animation: radar 4s linear infinite; opacity: 0.5; } .context-info { position: absolute; bottom: 10%; left: 50%; transform: translateX(-50%); text-align: center; width: 90%; opacity: 0; transition: opacity 0.5s ease; z-index: 5; max-width: 500px; } .context-info h3 { font-family: 'Orbitron', sans-serif; font-size: 1.5rem; margin-bottom: 0.5rem; color: var(--neon-blue); text-shadow: 0 0 10px var(--neon-blue); } .context-info p { font-size: 1rem; color: rgba(255, 255, 255, 0.8); line-height: 1.4; } .reflective-floor { position: absolute; bottom: 0; width: 100%; height: 30%; background: linear-gradient(to bottom, transparent, rgba(0, 243, 255, 0.1)); transform: rotateX(80deg); transform-origin: bottom; z-index: 0; opacity: 0.3; } .loading-bar { position: absolute; bottom: 5%; left: 50%; transform: translateX(-50%); width: 200px; height: 5px; background: rgba(255, 255, 255, 0.1); border-radius: 5px; overflow: hidden; z-index: 5; } .loading-progress { width: 0%; height: 100%; background: linear-gradient(90deg, var(--neon-blue), var(--neon-purple)); box-shadow: 0 0 10px var(--neon-blue); transition: width 0.5s ease; } @keyframes title-glow { 0% { text-shadow: 0 0 10px var(--neon-blue), 0 0 20px var(--neon-blue); } 50% { text-shadow: 0 0 20px var(--neon-purple), 0 0 30px var(--neon-purple); } 100% { text-shadow: 0 0 10px var(--neon-pink), 0 0 20px var(--neon-pink); } } @keyframes rotate { 0% { transform: rotateY(0deg); } 100% { transform: rotateY(360deg); } } @keyframes pulse { 0% { box-shadow: 0 0 20px var(--neon-blue), inset 0 0 15px rgba(144, 0, 255, 0.6); } 50% { box-shadow: 0 0 30px var(--neon-purple), inset 0 0 25px rgba(0, 243, 255, 0.6); } 100% { box-shadow: 0 0 20px var(--neon-pink), inset 0 0 15px rgba(144, 0, 255, 0.6); } } @keyframes radar { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Responsive styles */ @media screen and (max-width: 600px) { .title h1 { font-size: 2.5rem; } .menu-container { transform: scale(0.8); } .title { top: 10%; } .menu-btn { width: 140px; height: 50px; } .menu-btn span { font-size: 1rem; } } @media screen and (max-height: 700px) { .title { top: 8%; } .menu-container { transform: scale(0.7); } .context-info { bottom: 8%; } } </style> </head> <body> <div id="container"> <div id="particles"></div> <div class="title"> <h1>NEXUS FRONTIER</h1> <div class="subtitle">Galactic Dominion</div> </div> <div class="menu-container"> <div id="menu-ring"></div> <div id="inner-ring"></div> <div id="btn1" class="menu-btn" data-info="campaign"> <span><i class="btn-icon">✧</i>CAMPAIGN</span> </div> <div id="btn2" class="menu-btn" data-info="multiplayer"> <span><i class="btn-icon">✦</i>MULTIPLAYER</span> </div> <div id="btn3" class="menu-btn" data-info="arsenal"> <span><i class="btn-icon">⚔</i>ARSENAL</span> </div> <div id="btn4" class="menu-btn" data-info="settings"> <span><i class="btn-icon">⚙</i>SETTINGS</span> </div> <div id="btn5" class="menu-btn" data-info="profile"> <span><i class="btn-icon">◈</i>PROFILE</span> </div> <div class="center-orb"></div> <div class="radar-line"></div> </div> <div class="context-info" id="info-campaign"> <h3>CAMPAIGN: NEXUS ASCENSION</h3> <p>Embark on a 30-mission journey through the five sectors of Andromeda Prime. Master quantum weaponry, command elite squadrons, and forge your legacy as the Sovereign of the Nexus. New Chapter: "The Void Protocol" now available.</p> </div> <div class="context-info" id="info-multiplayer"> <h3>QUANTUM ARENA</h3> <p>Challenge players across 17 meticulously designed battle arenas. Compete in ranked matches, form strategic alliances, or dominate the weekly Nexus Tournaments for exclusive rewards and galactic recognition.</p> </div> <div class="context-info" id="info-arsenal"> <h3>NEXTECH ARSENAL</h3> <p>Configure your loadout with over 200 weapons and 50 unique combat augmentations. Customize your battleship with reactive shields, tachyon boosters and advanced AI modules for unmatched tactical superiority.</p> </div> <div class="context-info" id="info-settings"> <h3>NEURAL INTERFACE SETTINGS</h3> <p>Optimize your gameplay experience with advanced neural response calibration. Adjust holographic fidelity, quantum audio synchronization, and haptic feedback intensity for maximum immersion.</p> </div> <div class="context-info" id="info-profile"> <h3>COMMANDER PROFILE</h3> <p>View your combat statistics, achievement progression, and faction standings. Showcase earned medals and manage your alliance relationships within the Nexus Federation strategic network.</p> </div> <div class="reflective-floor"></div> <div class="loading-bar"> <div class="loading-progress" id="progress"></div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Initialize particles createParticles(); // Set loading progress animation animateLoadingBar(); // Set up menu button interactions const menuBtns = document.querySelectorAll('.menu-btn'); const infoElements = document.querySelectorAll('.context-info'); const menuContainer = document.querySelector('.menu-container'); let activeInfoId = null; menuBtns.forEach(btn => { btn.addEventListener('mouseenter', function() { // Hide all info elements infoElements.forEach(el => { el.style.opacity = '0'; }); // Show the relevant info element const infoId = 'info-' + this.getAttribute('data-info'); const infoElement = document.getElementById(infoId); if (infoElement) { infoElement.style.opacity = '1'; activeInfoId = infoId; } // Play hover sound playSound('hover'); }); btn.addEventListener('click', function() { // Simulate button press with animation this.style.transform = this.style.transform.replace('translateZ(20px)', 'translateZ(5px)'); setTimeout(() => { this.style.transform = this.style.transform.replace('translateZ(5px)', 'translateZ(20px)'); }, 200); // Play click sound playSound('click'); // Show loading for the selected option animateLoadingBarFull(); }); }); // 3D movement effect document.addEventListener('mousemove', function(e) { const xAxis = (window.innerWidth / 2 - e.pageX) / 25; const yAxis = (window.innerHeight / 2 - e.pageY) / 25; menuContainer.style.transform = `rotateY(${xAxis}deg) rotateX(${yAxis}deg)`; }); // Reset position when mouse leaves document.addEventListener('mouseleave', function() { menuContainer.style.transform = 'rotateY(0deg) rotateX(0deg)'; }); }); function createParticles() { const particlesContainer = document.getElementById('particles'); const particleCount = 100; for (let i = 0; i < particleCount; i++) { const particle = document.createElement('div'); particle.style.position = 'absolute'; particle.style.width = Math.random() * 3 + 'px'; particle.style.height = particle.style.width; particle.style.backgroundColor = getRandomColor(); particle.style.borderRadius = '50%'; particle.style.boxShadow = `0 0 ${Math.random() * 10 + 5}px ${getRandomColor()}`; particle.style.top = Math.random() * 100 + '%'; particle.style.left = Math.random() * 100 + '%'; particle.style.opacity = Math.random() * 0.5 + 0.3; // Add animation particle.style.animation = `floatParticle ${Math.random() * 20 + 10}s linear infinite`; particle.style.animationDelay = `${Math.random() * 10}s`; particlesContainer.appendChild(particle); // Add keyframe animation dynamically const styleSheet = document.styleSheets[0]; const keyframes = ` @keyframes floatParticle { 0% { transform: translate(0, 0) rotate(0deg); } 25% { transform: translate(${Math.random() * 100 - 50}px, ${Math.random() * 100 - 50}px) rotate(90deg); } 50% { transform: translate(${Math.random() * 100 - 50}px, ${Math.random() * 100 - 50}px) rotate(180deg); } 75% { transform: translate(${Math.random() * 100 - 50}px, ${Math.random() * 100 - 50}px) rotate(270deg); } 100% { transform: translate(0, 0) rotate(360deg); } }`; styleSheet.insertRule(keyframes, styleSheet.cssRules.length); } } function getRandomColor() { const colors = ['#00f3ff', '#9000ff', '#ff00e5', '#0066ff', '#00ffaa']; return colors[Math.floor(Math.random() * colors.length)]; } function animateLoadingBar() { const progress = document.getElementById('progress'); let width = 0; const interval = setInterval(() => { if (width >= 100) { clearInterval(interval); } else { width += 1; progress.style.width = width + '%'; if (width >= 100) { progress.style.width = '100%'; } } }, 20); } function animateLoadingBarFull() { const progress = document.getElementById('progress'); progress.style.width = '0%'; let width = 0; const interval = setInterval(() => { if (width >= 100) { clearInterval(interval); } else { width += 2; progress.style.width = width + '%'; if (width >= 100) { progress.style.width = '100%'; } } }, 20); } function playSound(type) { // This would connect to actual sound effects in a real implementation // For this demo, we're just implementing the function without actual sounds console.log(`Playing ${type} sound`); } </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>3D Navigation Sidebar</title> <style> :root { --primary: #2d3748; --secondary: #4a5568; --accent: #6b46c1; --light: #f7fafc; --sidebar-width: 280px; --sidebar-collapsed-width: 80px; --transition-speed: 0.3s; --shadow-color: rgba(0, 0, 0, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } body { background-color: #f0f2f5; height: 100vh; overflow: hidden; display: flex; } .app-container { display: flex; width: 700px; height: 700px; position: relative; overflow: hidden; background: linear-gradient(135deg, #f5f7fa 0%, #e4e7eb 100%); border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05); } .sidebar { width: var(--sidebar-width); height: 100%; background: linear-gradient(180deg, var(--primary) 0%, var(--secondary) 100%); color: var(--light); position: relative; transition: all var(--transition-speed) cubic-bezier(0.4, 0, 0.2, 1); transform: translateZ(0); box-shadow: 5px 0 15px var(--shadow-color); z-index: 10; display: flex; flex-direction: column; } .sidebar.collapsed { width: var(--sidebar-collapsed-width); } .sidebar-header { padding: 25px 20px; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid rgba(255, 255, 255, 0.08); transform: translateZ(10px); position: relative; } .logo { display: flex; align-items: center; font-weight: 700; font-size: 20px; letter-spacing: 0.5px; transition: opacity var(--transition-speed); } .logo-icon { width: 32px; height: 32px; background: var(--accent); border-radius: 8px; display: flex; align-items: center; justify-content: center; margin-right: 12px; box-shadow: 0 4px 8px rgba(107, 70, 193, 0.3); transform: translateZ(5px); } .logo-text { transition: opacity var(--transition-speed), transform var(--transition-speed); } .sidebar.collapsed .logo-text { opacity: 0; transform: translateX(-20px); } .toggle-btn { background: none; border: none; color: rgba(255, 255, 255, 0.7); cursor: pointer; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: 8px; transition: all var(--transition-speed); } .toggle-btn:hover { background: rgba(255, 255, 255, 0.1); color: var(--light); } .toggle-btn i { font-size: 18px; transition: transform var(--transition-speed); } .sidebar.collapsed .toggle-btn i { transform: rotate(180deg); } .nav-section { margin-top: 20px; flex: 1; overflow-y: auto; transform: translateZ(5px); } .nav-section::-webkit-scrollbar { width: 6px; } .nav-section::-webkit-scrollbar-thumb { background-color: rgba(255, 255, 255, 0.1); border-radius: 3px; } .nav-section::-webkit-scrollbar-track { background-color: transparent; } .section-title { padding: 0 20px; margin-bottom: 10px; font-size: 12px; text-transform: uppercase; color: rgba(255, 255, 255, 0.4); letter-spacing: 1px; transition: opacity var(--transition-speed); } .sidebar.collapsed .section-title { opacity: 0; } .nav-item { position: relative; transition: all var(--transition-speed); margin: 4px 8px; border-radius: 8px; transform: translateZ(0); } .nav-item.active { background: rgba(255, 255, 255, 0.08); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); transform: translateZ(10px); } .nav-item:hover { background: rgba(255, 255, 255, 0.05); } .nav-link { display: flex; align-items: center; padding: 12px; color: rgba(255, 255, 255, 0.7); text-decoration: none; transition: all var(--transition-speed); position: relative; } .nav-link:hover, .nav-item.active .nav-link { color: var(--light); } .nav-icon { width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; margin-right: 12px; border-radius: 8px; transition: all var(--transition-speed); } .nav-item.active .nav-icon { background: var(--accent); box-shadow: 0 3px 6px rgba(107, 70, 193, 0.3); transform: translateZ(15px); } .nav-text { flex: 1; white-space: nowrap; transition: opacity var(--transition-speed), transform var(--transition-speed); font-weight: 500; } .sidebar.collapsed .nav-text { opacity: 0; transform: translateX(-10px); } .chevron { transition: transform var(--transition-speed); color: rgba(255, 255, 255, 0.5); margin-right: 8px; } .sidebar.collapsed .chevron { opacity: 0; } .nav-item.active .chevron { color: rgba(255, 255, 255, 0.9); } .nav-item.expanded .chevron { transform: rotate(90deg); } .subnav { padding-left: 48px; height: 0; overflow: hidden; transition: height var(--transition-speed); transform: translateZ(5px); } .nav-item.expanded .subnav { height: auto; } .subnav-item { margin: 6px 0; opacity: 0; transform: translateY(-10px); transition: all var(--transition-speed); } .nav-item.expanded .subnav-item { opacity: 1; transform: translateY(0); } .nav-item.expanded .subnav-item:nth-child(1) { transition-delay: 0.1s; } .nav-item.expanded .subnav-item:nth-child(2) { transition-delay: 0.15s; } .nav-item.expanded .subnav-item:nth-child(3) { transition-delay: 0.2s; } .subnav-link { display: block; color: rgba(255, 255, 255, 0.6); text-decoration: none; padding: 8px 0; font-size: 14px; transition: all var(--transition-speed); } .subnav-link:hover { color: var(--light); } .subnav-link.active { color: var(--accent); font-weight: 500; } .sidebar-footer { padding: 20px; display: flex; align-items: center; border-top: 1px solid rgba(255, 255, 255, 0.08); transform: translateZ(5px); } .user-profile { display: flex; align-items: center; width: 100%; } .avatar { width: 40px; height: 40px; border-radius: 10px; background: var(--accent); overflow: hidden; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); transition: all var(--transition-speed); position: relative; } .avatar img { width: 100%; height: 100%; object-fit: cover; } .user-info { margin-left: 12px; transition: opacity var(--transition-speed), transform var(--transition-speed); } .sidebar.collapsed .user-info { opacity: 0; transform: translateX(-10px); } .user-name { font-weight: 600; font-size: 14px; } .user-status { font-size: 12px; color: rgba(255, 255, 255, 0.5); display: flex; align-items: center; margin-top: 2px; } .status-dot { width: 8px; height: 8px; border-radius: 50%; background: #48bb78; margin-right: 6px; } .content { flex: 1; padding: 30px; overflow-y: auto; transform: translateZ(0); transition: all var(--transition-speed); } .content-header { margin-bottom: 30px; } .page-title { font-size: 28px; font-weight: 700; color: var(--primary); margin-bottom: 8px; } .breadcrumb { display: flex; align-items: center; color: var(--secondary); font-size: 14px; } .breadcrumb span { margin: 0 6px; color: #a0aec0; } .dashboard-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; } .card { background: white; border-radius: 12px; padding: 20px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); transition: all 0.3s; transform: translateZ(0); } .card:hover { transform: translateY(-5px) translateZ(5px); box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); } .card-label { font-size: 14px; color: #718096; margin-bottom: 10px; } .card-value { font-size: 24px; font-weight: 700; color: var(--primary); } .chart-container { background: white; border-radius: 12px; padding: 20px; margin-bottom: 20px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); } .chart-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .chart-title { font-size: 18px; font-weight: 600; color: var(--primary); } .chart-actions { display: flex; gap: 10px; } .chart-btn { background: #f7fafc; border: 1px solid #e2e8f0; border-radius: 6px; padding: 8px 12px; font-size: 14px; color: #4a5568; cursor: pointer; transition: all 0.2s; } .chart-btn:hover { background: #edf2f7; } .chart-btn.active { background: var(--accent); color: white; border-color: var(--accent); } .chart { width: 100%; height: 250px; position: relative; overflow: hidden; } .tooltip { position: absolute; background: rgba(0, 0, 0, 0.8); color: white; padding: 5px 10px; border-radius: 4px; font-size: 12px; pointer-events: none; opacity: 0; transition: opacity 0.2s; z-index: 100; } @media (max-width: 700px) { .sidebar { width: var(--sidebar-collapsed-width); position: absolute; z-index: 100; } .sidebar.expanded { width: var(--sidebar-width); } .sidebar.expanded .logo-text, .sidebar.expanded .section-title, .sidebar.expanded .nav-text, .sidebar.expanded .user-info, .sidebar.expanded .chevron { opacity: 1; transform: translateX(0); } .content { margin-left: var(--sidebar-collapsed-width); } .dashboard-grid { grid-template-columns: 1fr; } } /* Depth & 3D Effects */ .perspective-container { perspective: 1000px; width: 100%; height: 100%; } .depth-layer-1, .depth-layer-2, .depth-layer-3 { position: absolute; width: 100%; height: 100%; top: 0; left: 0; pointer-events: none; } .depth-layer-1 { background: linear-gradient(to right, rgba(0,0,0,0.03) 0%, transparent 5%); transform: translateZ(10px); } .depth-layer-2 { background: linear-gradient(to right, rgba(0,0,0,0.01) 0%, transparent 10%); transform: translateZ(20px); } .depth-layer-3 { background: linear-gradient(to bottom, rgba(255,255,255,0.05) 0%, transparent 15%); transform: translateZ(30px); } /* Animation keyframes */ @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes slideIn { from { transform: translateX(-20px); opacity: 0; } to { transform: translateX(0); opacity: 1; } } /* Utility classes */ .animate-pulse { animation: pulse 2s infinite; } .delay-1 { animation-delay: 0.1s; } .delay-2 { animation-delay: 0.2s; } .delay-3 { animation-delay: 0.3s; } .delay-4 { animation-delay: 0.4s; } .delay-5 { animation-delay: 0.5s; } </style> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css"> </head> <body> <div class="app-container"> <div class="perspective-container"> <aside class="sidebar"> <div class="depth-layer-1"></div> <div class="depth-layer-2"></div> <div class="depth-layer-3"></div> <div class="sidebar-header"> <div class="logo"> <div class="logo-icon"> <i class="bi bi-stack"></i> </div> <div class="logo-text">Atlas3D</div> </div> <button class="toggle-btn" id="toggle-sidebar"> <i class="bi bi-chevron-left"></i> </button> </div> <div class="nav-section"> <div class="section-title">Main</div> <div class="nav-item active"> <a href="#" class="nav-link"> <div class="nav-icon"> <i class="bi bi-grid-1x2"></i> </div> <div class="nav-text">Dashboard</div> </a> </div> <div class="nav-item"> <a href="#" class="nav-link"> <div class="nav-icon"> <i class="bi bi-kanban"></i> </div> <div class="nav-text">Projects</div> </a> </div> <div class="nav-item has-subnav"> <a href="#" class="nav-link"> <div class="nav-icon"> <i class="bi bi-bar-chart"></i> </div> <div class="nav-text">Analytics</div> <i class="bi bi-chevron-right chevron"></i> </a> <div class="subnav"> <div class="subnav-item"> <a href="#" class="subnav-link active">Performance</a> </div> <div class="subnav-item"> <a href="#" class="subnav-link">Engagement</a> </div> <div class="subnav-item"> <a href="#" class="subnav-link">Conversion</a> </div> </div> </div> <div class="section-title">Workspace</div> <div class="nav-item has-subnav"> <a href="#" class="nav-link"> <div class="nav-icon"> <i class="bi bi-people"></i> </div> <div class="nav-text">Team</div> <i class="bi bi-chevron-right chevron"></i> </a> <div class="subnav"> <div class="subnav-item"> <a href="#" class="subnav-link">Members</a> </div> <div class="subnav-item"> <a href="#" class="subnav-link">Permissions</a> </div> </div> </div> <div class="nav-item"> <a href="#" class="nav-link"> <div class="nav-icon"> <i class="bi bi-calendar3"></i> </div> <div class="nav-text">Calendar</div> </a> </div> <div class="nav-item"> <a href="#" class="nav-link"> <div class="nav-icon"> <i class="bi bi-chat-left-dots"></i> </div> <div class="nav-text">Messages</div> </a> </div> <div class="section-title">Settings</div> <div class="nav-item"> <a href="#" class="nav-link"> <div class="nav-icon"> <i class="bi bi-gear"></i> </div> <div class="nav-text">Preferences</div> </a> </div> <div class="nav-item"> <a href="#" class="nav-link"> <div class="nav-icon"> <i class="bi bi-shield-check"></i> </div> <div class="nav-text">Security</div> </a> </div> </div> <div class="sidebar-footer"> <div class="user-profile"> <div class="avatar"> <img src="https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=100&q=80" alt="User"> </div> <div class="user-info"> <div class="user-name">Alex Morgan</div> <div class="user-status"> <div class="status-dot"></div> Online </div> </div> </div> </div> </aside> <main class="content"> <div class="content-header"> <h1 class="page-title">Dashboard</h1> <div class="breadcrumb"> <a href="#">Home</a> <span>/</span> <a href="#">Dashboard</a> </div> </div> <div class="dashboard-grid"> <div class="card animate-pulse delay-1"> <div class="card-label">Projects</div> <div class="card-value">12</div> </div> <div class="card animate-pulse delay-2"> <div class="card-label">Active Tasks</div> <div class="card-value">36</div> </div> <div class="card animate-pulse delay-3"> <div class="card-label">Team Members</div> <div class="card-value">8</div> </div> </div> <div class="chart-container"> <div class="chart-header"> <div class="chart-title">Project Performance</div> <div class="chart-actions"> <button class="chart-btn active">Week</button> <button class="chart-btn">Month</button> <button class="chart-btn">Year</button> </div> </div> <div class="chart" id="performance-chart"></div> </div> </main> </div> </div> <script> // Toggle sidebar const sidebar = document.querySelector('.sidebar'); const toggleBtn = document.getElementById('toggle-sidebar'); toggleBtn.addEventListener('click', () => { sidebar.classList.toggle('collapsed'); }); // Handle subnavigation items const navItemsWithSubnav = document.querySelectorAll('.nav-item.has-subnav'); navItemsWithSubnav.forEach(item => { const navLink = item.querySelector('.nav-link'); const subnav = item.querySelector('.subnav'); // Set initial height of subnav for transition item.classList.contains('expanded') ? subnav.style.height = subnav.scrollHeight + 'px' : subnav.style.height = '0'; navLink.addEventListener('click', (e) => { e.preventDefault(); // Toggle expanded class item.classList.toggle('expanded'); // Animate height if (item.classList.contains('expanded')) { subnav.style.height = subnav.scrollHeight + 'px'; } else { subnav.style.height = '0'; } // Close other expanded items navItemsWithSubnav.forEach(otherItem => { if (otherItem !== item && otherItem.classList.contains('expanded')) { otherItem.classList.remove('expanded'); otherItem.querySelector('.subnav').style.height = '0'; } }); }); }); // Add subtle hover effect to nav items document.querySelectorAll('.nav-item').forEach(item => { item.addEventListener('mouseenter', () => { if (!item.classList.contains('active')) { item.style.transform = 'translateZ(5px)'; item.style.boxShadow = '0 2px 5px rgba(0, 0, 0, 0.1)'; } }); item.addEventListener('mouseleave', () => { if (!item.classList.contains('active')) { item.style.transform = 'translateZ(0)'; item.style.boxShadow = 'none'; } }); }); // Simulate performance chart const chart = document.getElementById('performance-chart'); const tooltip = document.createElement('div'); tooltip.className = 'tooltip'; chart.appendChild(tooltip); function createChart() { // Clear previous chart while (chart.firstChild !== tooltip) { chart.removeChild(chart.firstChild); } const data = [42, 65, 84, 78, 96, 88, 70]; const chartHeight = chart.offsetHeight - 30; const chartWidth = chart.offsetWidth - 40; const maxData = Math.max(...data); const barWidth = chartWidth / data.length - 10; // Create bars data.forEach((value, index) => { const barHeight = (value / maxData) * chartHeight; const bar = document.createElement('div'); bar.style.position = 'absolute'; bar.style.width = barWidth + 'px'; bar.style.height = barHeight + 'px'; bar.style.bottom = '20px'; bar.style.left = (index * (barWidth + 10) + 20) + 'px'; bar.style.backgroundColor = 'rgba(107, 70, 193, 0.7)'; bar.style.borderRadius = '6px'; bar.style.transition = 'height 1s cubic-bezier(0.34, 1.56, 0.64, 1), background-color 0.3s'; bar.style.boxShadow = '0 2px 8px rgba(107, 70, 193, 0.2)'; bar.style.transform = 'translateZ(5px)'; // Animate bars on load setTimeout(() => { bar.style.height = barHeight + 'px'; }, 100 * index); // Create tooltip interaction bar.addEventListener('mouseenter', (e) => { bar.style.backgroundColor = 'rgba(107, 70, 193, 1)'; tooltip.style.opacity = '1'; tooltip.innerText = 'Day ' + (index + 1) + ': ' + value + '%'; tooltip.style.left = bar.offsetLeft + barWidth/2 - tooltip.offsetWidth/2 + 'px'; tooltip.style.bottom = barHeight + 30 + 'px'; // Add a highlighting effect bar.style.transform = 'translateZ(15px) scale(1.05)'; bar.style.boxShadow = '0 4px 15px rgba(107, 70, 193, 0.4)'; }); bar.addEventListener('mousemove', (e) => { tooltip.style.left = bar.offsetLeft + barWidth/2 - tooltip.offsetWidth/2 + 'px'; }); bar.addEventListener('mouseleave', () => { bar.style.backgroundColor = 'rgba(107, 70, 193, 0.7)'; tooltip.style.opacity = '0'; bar.style.transform = 'translateZ(5px)'; bar.style.boxShadow = '0 2px 8px rgba(107, 70, 193, 0.2)'; }); chart.appendChild(bar); }); // Create labels for (let i = 0; i < data.length; i++) { const label = document.createElement('div'); label.style.position = 'absolute'; label.style.bottom = '5px'; label.style.left = (i * (barWidth + 10) + 20 + barWidth/2) + 'px'; label.style.transform = 'translateX(-50%)'; label.style.fontSize = '12px'; label.style.color = '#718096'; label.innerText = 'D' + (i + 1); chart.appendChild(label); } } // Initialize chart setTimeout(createChart, 500); // Handle chart buttons const chartButtons = document.querySelectorAll('.chart-btn'); chartButtons.forEach(btn => { btn.addEventListener('click', () => { chartButtons.forEach(b => b.classList.remove('active')); btn.classList.add('active'); // Simulate data change setTimeout(createChart, 300); }); }); // Responsive sidebar behavior function checkResponsive() { if (window.innerWidth <= 700) { sidebar.classList.add('collapsed'); // For mobile, we change the toggle behavior toggleBtn.addEventListener('click', (e) => { e.stopPropagation(); sidebar.classList.toggle('expanded'); }); // Close sidebar when clicking outside on mobile document.addEventListener('click', (e) => { if (!sidebar.contains(e.target) && sidebar.classList.contains('expanded')) { sidebar.classList.remove('expanded'); } }); } } // Check on load checkResponsive(); // Check on resize window.addEventListener('resize', checkResponsive); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>3D Animation Loader</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { width: 100%; height: 100vh; display: flex; justify-content: center; align-items: center; background-color: #0f0f1a; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; overflow: hidden; perspective: 1000px; } .loader-container { position: relative; width: 700px; height: 700px; display: flex; justify-content: center; align-items: center; flex-direction: column; } .scene { width: 250px; height: 250px; perspective: 1000px; transform-style: preserve-3d; position: relative; } .cube, .pyramid, .sphere { position: absolute; width: 100%; height: 100%; transform-style: preserve-3d; transform-origin: center center; } .cube { animation: rotateCube 8s infinite ease-in-out; } .pyramid { animation: rotatePyramid 7s infinite ease-in-out; opacity: 0; } .sphere { opacity: 0; animation: rotateSphere 6s infinite ease-in-out; } .face { position: absolute; width: 100px; height: 100px; background: rgba(255, 255, 255, 0.1); border: 2px solid; box-shadow: 0 0 20px rgba(255, 255, 255, 0.2); display: flex; justify-content: center; align-items: center; font-size: 20px; color: white; backface-visibility: visible; transform-origin: center center; transform-style: preserve-3d; } .cube .face { border-color: #0bbcda; } .cube .face:nth-child(1) { transform: translateZ(50px); background: linear-gradient(45deg, #0bbcda33, #0bbcda11); } .cube .face:nth-child(2) { transform: rotateY(180deg) translateZ(50px); background: linear-gradient(45deg, #0bbcda33, #0bbcda11); } .cube .face:nth-child(3) { transform: rotateY(90deg) translateZ(50px); background: linear-gradient(45deg, #3655b544, #3655b522); } .cube .face:nth-child(4) { transform: rotateY(-90deg) translateZ(50px); background: linear-gradient(45deg, #3655b544, #3655b522); } .cube .face:nth-child(5) { transform: rotateX(90deg) translateZ(50px); background: linear-gradient(45deg, #f9316c33, #f9316c11); } .cube .face:nth-child(6) { transform: rotateX(-90deg) translateZ(50px); background: linear-gradient(45deg, #f9316c33, #f9316c11); } .pyramid .face { border-color: #fe5c3b; width: 110px; height: 110px; clip-path: polygon(50% 0%, 0% 100%, 100% 100%); } .pyramid .face:nth-child(1) { transform: translateY(-30px) rotateX(30deg); background: linear-gradient(45deg, #fe5c3b44, #fe5c3b22); } .pyramid .face:nth-child(2) { transform: translateY(40px) rotateZ(120deg) rotateX(30deg); background: linear-gradient(45deg, #fe5c3b44, #fe5c3b22); } .pyramid .face:nth-child(3) { transform: translateY(40px) rotateZ(240deg) rotateX(30deg); background: linear-gradient(45deg, #ff9a0044, #ff9a0022); } .pyramid .face:nth-child(4) { transform: translateY(40px) rotateZ(360deg) rotateX(-150deg); background: linear-gradient(45deg, #ff9a0044, #ff9a0022); } .sphere-point { position: absolute; width: 15px; height: 15px; background: #7d41e9; border-radius: 50%; box-shadow: 0 0 15px 5px rgba(125, 65, 233, 0.6); transform-style: preserve-3d; } .progress-text { color: white; font-size: 24px; margin-top: 40px; font-weight: 600; letter-spacing: 1px; text-shadow: 0 0 10px rgba(255, 255, 255, 0.5); opacity: 0.8; } .status-text { color: #9cadc2; font-size: 16px; margin-top: 15px; max-width: 400px; text-align: center; line-height: 1.5; opacity: 0.8; } .progress-bar { width: 300px; height: 6px; background: rgba(255, 255, 255, 0.1); border-radius: 3px; margin-top: 20px; overflow: hidden; position: relative; } .progress-fill { height: 100%; width: 0%; background: linear-gradient(90deg, #0bbcda, #fe5c3b, #7d41e9); border-radius: 3px; box-shadow: 0 0 10px rgba(255, 255, 255, 0.5); transition: width 0.3s ease-out; } .glow { position: absolute; width: 100%; height: 100%; background: radial-gradient(circle, rgba(125, 65, 233, 0.2) 0%, rgba(15, 15, 26, 0) 70%); z-index: -1; opacity: 0; animation: pulseGlow 4s infinite ease-in-out; } @keyframes rotateCube { 0%, 20% { transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg); opacity: 1; } 25%, 45% { transform: rotateY(180deg) rotateX(180deg) rotateZ(90deg); opacity: 0; } 50%, 70% { transform: rotateY(360deg) rotateX(360deg) rotateZ(180deg); opacity: 0; } 75%, 95% { transform: rotateY(540deg) rotateX(540deg) rotateZ(270deg); opacity: 0; } 100% { transform: rotateY(720deg) rotateX(720deg) rotateZ(360deg); opacity: 1; } } @keyframes rotatePyramid { 0%, 20% { transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg); opacity: 0; } 25%, 45% { transform: rotateY(180deg) rotateX(180deg) rotateZ(90deg); opacity: 1; } 50%, 70% { transform: rotateY(360deg) rotateX(360deg) rotateZ(180deg); opacity: 0; } 75%, 95% { transform: rotateY(540deg) rotateX(540deg) rotateZ(270deg); opacity: 0; } 100% { transform: rotateY(720deg) rotateX(720deg) rotateZ(360deg); opacity: 0; } } @keyframes rotateSphere { 0%, 20% { transform: rotateY(0deg) rotateX(0deg) rotateZ(0deg); opacity: 0; } 25%, 45% { transform: rotateY(180deg) rotateX(180deg) rotateZ(90deg); opacity: 0; } 50%, 70% { transform: rotateY(360deg) rotateX(360deg) rotateZ(180deg); opacity: 1; } 75%, 95% { transform: rotateY(540deg) rotateX(540deg) rotateZ(270deg); opacity: 0; } 100% { transform: rotateY(720deg) rotateX(720deg) rotateZ(360deg); opacity: 0; } } @keyframes pulseGlow { 0%, 100% { opacity: 0.3; transform: scale(1); } 50% { opacity: 0.6; transform: scale(1.2); } } @media screen and (max-width: 700px) { .scene { width: 180px; height: 180px; } .face { width: 70px; height: 70px; } .cube .face:nth-child(1) { transform: translateZ(35px); } .cube .face:nth-child(2) { transform: rotateY(180deg) translateZ(35px); } .cube .face:nth-child(3) { transform: rotateY(90deg) translateZ(35px); } .cube .face:nth-child(4) { transform: rotateY(-90deg) translateZ(35px); } .cube .face:nth-child(5) { transform: rotateX(90deg) translateZ(35px); } .cube .face:nth-child(6) { transform: rotateX(-90deg) translateZ(35px); } .pyramid .face { width: 80px; height: 80px; } .progress-bar { width: 220px; } .progress-text { font-size: 20px; } .status-text { font-size: 14px; max-width: 280px; } } </style> </head> <body> <div class="loader-container"> <div class="glow"></div> <div class="scene"> <div class="cube"> <div class="face"></div> <div class="face"></div> <div class="face"></div> <div class="face"></div> <div class="face"></div> <div class="face"></div> </div> <div class="pyramid"> <div class="face"></div> <div class="face"></div> <div class="face"></div> <div class="face"></div> </div> <div class="sphere" id="sphere"></div> </div> <div class="progress-text" id="progress-percent">Loading assets: 0%</div> <div class="progress-bar"> <div class="progress-fill" id="progress-fill"></div> </div> <div class="status-text" id="status-text">Initializing 3D rendering engine</div> </div> <script> // Create the sphere with dynamic points function createSphere() { const sphere = document.getElementById('sphere'); const radius = 50; const points = 80; // Number of points in the sphere for (let i = 0; i < points; i++) { // Calculate positions using spherical coordinates const phi = Math.acos(-1 + (2 * i) / points); const theta = Math.sqrt(points * Math.PI) * phi; // Convert to Cartesian coordinates const x = radius * Math.cos(theta) * Math.sin(phi); const y = radius * Math.sin(theta) * Math.sin(phi); const z = radius * Math.cos(phi); const point = document.createElement('div'); point.className = 'sphere-point'; point.style.transform = `translate3d(${x + 45}px, ${y + 45}px, ${z}px)`; // Random size variation for depth effect const size = 5 + Math.random() * 10; point.style.width = `${size}px`; point.style.height = `${size}px`; // Different colors for visual interest const colors = ['#7d41e9', '#0bbcda', '#fe5c3b', '#ff9a00']; point.style.background = colors[Math.floor(Math.random() * colors.length)]; sphere.appendChild(point); } } // Simulate loading process function simulateLoading() { const progressFill = document.getElementById('progress-fill'); const progressText = document.getElementById('progress-percent'); const statusText = document.getElementById('status-text'); const loadingMessages = [ "Initializing 3D rendering engine", "Preparing geometry transformations", "Loading texture maps", "Calibrating depth buffers", "Optimizing shader pipelines", "Configuring animation sequences", "Finalizing multimedia components", "Synchronizing render pipeline" ]; let progress = 0; const loadingInterval = setInterval(() => { // Random increment between 1-5% each step const increment = Math.floor(Math.random() * 5) + 1; progress = Math.min(progress + increment, 100); // Update progress bar and text progressFill.style.width = `${progress}%`; progressText.innerText = `Loading assets: ${progress}%`; // Update status message every ~15% const messageIndex = Math.min(Math.floor(progress / 15), loadingMessages.length - 1); statusText.innerText = loadingMessages[messageIndex]; // Add interactive behavior when close to loaded if (progress >= 85) { statusText.innerText = "Almost there! Processing final components..."; } // Complete loading if (progress === 100) { clearInterval(loadingInterval); progressText.innerText = "Ready to Launch"; statusText.innerText = "3D multimedia platform successfully loaded. Press any key to begin your experience."; // Add hover pulse effect to indicate completion document.querySelector('.scene').style.cursor = 'pointer'; document.querySelector('.scene').addEventListener('mouseenter', () => { document.querySelector('.glow').style.animation = 'pulseGlow 1s infinite ease-in-out'; }); document.querySelector('.scene').addEventListener('mouseleave', () => { document.querySelector('.glow').style.animation = 'pulseGlow 4s infinite ease-in-out'; }); // Listen for user interaction document.addEventListener('click', () => { statusText.innerText = "Experience initialized! Enjoy the multimedia platform."; document.querySelector('.progress-fill').style.background = 'linear-gradient(90deg, #5cd65c, #4caf50)'; }); } }, 300); } // Initialize on load window.onload = function() { createSphere(); simulateLoading(); }; </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>3D Form Input Fields</title> <style> :root { --primary: #5468ff; --primary-light: #7b8aff; --dark: #2a325a; --light: #f5f7ff; --error: #ff5461; --success: #2ecc71; --shadow-color: rgba(84, 104, 255, 0.1); --input-bg: #ffffff; --input-border: #e1e5fa; --text-color: #33374d; --text-secondary: #6c7399; --transition: 0.25s cubic-bezier(0.4, 0, 0.2, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 100vh; background: var(--light); overflow-x: hidden; padding: 20px; } .container { width: 100%; max-width: 640px; padding: 40px; border-radius: 24px; background: var(--input-bg); box-shadow: 0 12px 32px rgba(42, 50, 90, 0.08), 0 2px 6px rgba(42, 50, 90, 0.04); } h1 { color: var(--dark); font-size: 28px; margin-bottom: 10px; position: relative; } h1::after { content: ""; position: absolute; left: 0; bottom: -10px; width: 60px; height: 4px; background: var(--primary); border-radius: 2px; } p.subtitle { color: var(--text-secondary); margin-bottom: 32px; font-size: 16px; line-height: 1.5; margin-top: 20px; } .form-group { position: relative; margin-bottom: 20px; } label { display: block; margin-bottom: 8px; font-weight: 500; color: var(--dark); transition: var(--transition); font-size: 14px; } .input-wrapper { position: relative; perspective: 1000px; } .input-3d { width: 100%; padding: 16px 18px; font-size: 16px; border: 1px solid var(--input-border); border-radius: 12px; background: var(--input-bg); color: var(--text-color); transition: var(--transition); transform-style: preserve-3d; transform: translateZ(0); box-shadow: 0 4px 8px var(--shadow-color), inset 0 -2px 0 rgba(0, 0, 0, 0.05); outline: none; } .input-3d:hover { transform: translateY(-2px) translateZ(4px); box-shadow: 0 8px 16px var(--shadow-color), inset 0 -2px 0 rgba(0, 0, 0, 0.05); } .input-3d:focus { border-color: var(--primary); transform: translateY(-4px) translateZ(8px); box-shadow: 0 12px 24px var(--shadow-color), 0 4px 8px rgba(84, 104, 255, 0.15), inset 0 -2px 0 rgba(0, 0, 0, 0.05); } .input-3d::placeholder { color: #b0b5cb; opacity: 0.7; } .input-icon { position: absolute; right: 18px; top: 50%; transform: translateY(-50%); color: var(--text-secondary); transition: var(--transition); pointer-events: none; } .form-group.error .input-3d { border-color: var(--error); box-shadow: 0 4px 8px rgba(255, 84, 97, 0.12), inset 0 -2px 0 rgba(255, 84, 97, 0.05); } .form-group.success .input-3d { border-color: var(--success); box-shadow: 0 4px 8px rgba(46, 204, 113, 0.12), inset 0 -2px 0 rgba(46, 204, 113, 0.05); } .error-message, .success-message { font-size: 13px; margin-top: 6px; display: none; animation: fadeIn 0.3s ease-in-out; } .error-message { color: var(--error); } .success-message { color: var(--success); } .form-group.error .error-message, .form-group.success .success-message { display: block; } .actions { margin-top: 40px; display: flex; gap: 16px; } .button { padding: 14px 32px; border: none; border-radius: 12px; font-weight: 600; font-size: 16px; cursor: pointer; transition: var(--transition); transform-style: preserve-3d; transform: translateZ(0); position: relative; overflow: hidden; } .button-primary { background: var(--primary); color: white; box-shadow: 0 4px 12px rgba(84, 104, 255, 0.3), inset 0 -2px 0 rgba(0, 0, 0, 0.1); } .button-primary:hover { background: var(--primary-light); transform: translateY(-2px) translateZ(4px); box-shadow: 0 8px 20px rgba(84, 104, 255, 0.35), inset 0 -2px 0 rgba(0, 0, 0, 0.1); } .button-primary:active { transform: translateY(0) translateZ(0); box-shadow: 0 4px 12px rgba(84, 104, 255, 0.2), inset 0 -1px 0 rgba(0, 0, 0, 0.1); } .button-secondary { background: transparent; color: var(--primary); border: 1px solid var(--primary); box-shadow: 0 4px 12px rgba(84, 104, 255, 0.08); } .button-secondary:hover { background: rgba(84, 104, 255, 0.05); transform: translateY(-2px) translateZ(4px); box-shadow: 0 8px 20px rgba(84, 104, 255, 0.12); } .button-secondary:active { transform: translateY(0) translateZ(0); box-shadow: 0 4px 12px rgba(84, 104, 255, 0.06); } .button .button-effect { position: absolute; top: 50%; left: 50%; width: 0; height: 0; background: radial-gradient(circle, rgba(255, 255, 255, 0.8) 0%, rgba(255, 255, 255, 0) 70%); border-radius: 50%; transform: translate(-50%, -50%); opacity: 0; } @keyframes ripple { 0% { width: 0; height: 0; opacity: 0.5; } 100% { width: 300px; height: 300px; opacity: 0; } } @keyframes fadeIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } @keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } } .field-highlight { position: absolute; width: 100%; height: 100%; border-radius: 12px; top: 0; left: 0; pointer-events: none; opacity: 0; z-index: -1; background: radial-gradient(circle at center, rgba(84, 104, 255, 0.1), transparent 70%); transition: opacity 0.4s ease; } .input-3d:focus + .field-highlight { opacity: 1; animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(0.95); opacity: 0.5; } 50% { transform: scale(1.05); opacity: 0.8; } 100% { transform: scale(0.95); opacity: 0.5; } } .pattern-bg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0.05; background: linear-gradient(45deg, var(--primary) 25%, transparent 25%, transparent 75%, var(--primary) 75%, var(--primary)), linear-gradient(45deg, var(--primary) 25%, transparent 25%, transparent 75%, var(--primary) 75%, var(--primary)); background-size: 40px 40px; background-position: 0 0, 20px 20px; pointer-events: none; z-index: -1; } .strength-meter { height: 4px; background: #edf0fd; border-radius: 2px; margin-top: 8px; overflow: hidden; position: relative; } .strength-meter-fill { height: 100%; width: 0; border-radius: 2px; transition: width 0.3s ease, background-color 0.3s ease; } .weak { background-color: var(--error); } .medium { background-color: #ffaa2c; } .strong { background-color: var(--success); } .password-toggle { position: absolute; right: 18px; top: 50%; transform: translateY(-50%); cursor: pointer; color: var(--text-secondary); background: none; border: none; padding: 4px; display: flex; align-items: center; justify-content: center; z-index: 2; } .password-toggle:hover { color: var(--primary); } .form-card { position: relative; background: white; border-radius: 24px; overflow: hidden; } .form-card-header { z-index: 1; position: relative; } /* Media Queries */ @media (max-width: 480px) { .container { padding: 24px; } h1 { font-size: 24px; } p.subtitle { font-size: 14px; margin-bottom: 24px; } .actions { flex-direction: column; margin-top: 30px; } .button { width: 100%; } } </style> </head> <body> <div class="pattern-bg"></div> <div class="container"> <div class="form-card"> <div class="form-card-header"> <h1>Project Workspace</h1> <p class="subtitle">Create your 3D workspace for the design project. All fields utilize tactile depth for a more immersive experience.</p> </div> <form id="project-form"> <div class="form-group"> <label for="project-name">Project Name</label> <div class="input-wrapper"> <input type="text" id="project-name" class="input-3d" placeholder="Enter your project title..." required> <div class="field-highlight"></div> <svg class="input-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M19.5 14.25V11.25C19.5 8.5 17.5 6.25 15 5.25C14.5 4 13.25 3 12 3C10.75 3 9.5 4 9 5.25C6.5 6.25 4.5 8.5 4.5 11.25V14.25C4.5 14.75 4.25 15.75 4 16.25L3 18.25C2.5 19.25 3 20.25 4 20.25H20C21 20.25 21.5 19.25 21 18.25L20 16.25C19.75 15.75 19.5 14.75 19.5 14.25Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round"/> </svg> <div class="error-message">Please enter a project name</div> <div class="success-message">Project name looks great!</div> </div> </div> <div class="form-group"> <label for="project-description">Project Description</label> <div class="input-wrapper"> <input type="text" id="project-description" class="input-3d" placeholder="Briefly describe your project goals..."> <div class="field-highlight"></div> <svg class="input-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8 2V5" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> <path d="M16 2V5" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> <path d="M3.5 9.09H20.5" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> <path d="M21 8.5V17C21 20 19.5 22 16 22H8C4.5 22 3 20 3 17V8.5C3 5.5 4.5 3.5 8 3.5H16C19.5 3.5 21 5.5 21 8.5Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> </svg> </div> </div> <div class="form-group"> <label for="project-email">Work Email</label> <div class="input-wrapper"> <input type="email" id="project-email" class="input-3d" placeholder="[email protected]"> <div class="field-highlight"></div> <svg class="input-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M17 20.5H7C4 20.5 2 19 2 15.5V8.5C2 5 4 3.5 7 3.5H17C20 3.5 22 5 22 8.5V15.5C22 19 20 20.5 17 20.5Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> <path d="M17 9L13.87 11.5C12.84 12.32 11.15 12.32 10.12 11.5L7 9" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> </svg> <div class="error-message">Please enter a valid email address</div> <div class="success-message">Email format is valid</div> </div> </div> <div class="form-group"> <label for="project-password">Project Password</label> <div class="input-wrapper"> <input type="password" id="project-password" class="input-3d" placeholder="Create a secure password..."> <div class="field-highlight"></div> <button type="button" class="password-toggle"> <svg id="eye-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M15.58 12C15.58 13.98 13.98 15.58 12 15.58C10.02 15.58 8.42001 13.98 8.42001 12C8.42001 10.02 10.02 8.42 12 8.42C13.98 8.42 15.58 10.02 15.58 12Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12 20.27C15.53 20.27 18.82 18.19 21.11 14.59C22.01 13.18 22.01 10.81 21.11 9.39997C18.82 5.79997 15.53 3.71997 12 3.71997C8.47 3.71997 5.18 5.79997 2.89 9.39997C1.99 10.81 1.99 13.18 2.89 14.59C5.18 18.19 8.47 20.27 12 20.27Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg> </button> <div class="error-message">Password must be at least 8 characters</div> <div class="success-message">Password strength is good</div> </div> <div class="strength-meter"> <div class="strength-meter-fill"></div> </div> </div> <div class="actions"> <button type="submit" class="button button-primary"> Create Workspace <span class="button-effect"></span> </button> <button type="button" class="button button-secondary"> Cancel <span class="button-effect"></span> </button> </div> </form> </div> </div> <script> // Form validation and interaction document.addEventListener('DOMContentLoaded', function() { const form = document.getElementById('project-form'); const projectName = document.getElementById('project-name'); const projectEmail = document.getElementById('project-email'); const projectPassword = document.getElementById('project-password'); const passwordToggle = document.querySelector('.password-toggle'); const strengthMeter = document.querySelector('.strength-meter-fill'); const buttons = document.querySelectorAll('.button'); // Button ripple effect buttons.forEach(button => { button.addEventListener('click', function(e) { const effect = button.querySelector('.button-effect'); // Remove existing animation effect.style.animation = 'none'; // Trigger reflow void effect.offsetWidth; // Start new ripple effect.style.animation = 'ripple 0.8s'; }); }); // Password toggle passwordToggle.addEventListener('click', function() { const type = projectPassword.getAttribute('type') === 'password' ? 'text' : 'password'; projectPassword.setAttribute('type', type); // Toggle eye icon const eyeIcon = document.getElementById('eye-icon'); if (type === 'password') { eyeIcon.innerHTML = `<path d="M15.58 12C15.58 13.98 13.98 15.58 12 15.58C10.02 15.58 8.42001 13.98 8.42001 12C8.42001 10.02 10.02 8.42 12 8.42C13.98 8.42 15.58 10.02 15.58 12Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12 20.27C15.53 20.27 18.82 18.19 21.11 14.59C22.01 13.18 22.01 10.81 21.11 9.39997C18.82 5.79997 15.53 3.71997 12 3.71997C8.47 3.71997 5.18 5.79997 2.89 9.39997C1.99 10.81 1.99 13.18 2.89 14.59C5.18 18.19 8.47 20.27 12 20.27Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`; } else { eyeIcon.innerHTML = `<path d="M14.53 9.47L9.47 14.53C8.82 13.88 8.42 12.99 8.42 12C8.42 10.02 10.02 8.42 12 8.42C12.99 8.42 13.88 8.82 14.53 9.47Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M17.82 5.76998C16.07 4.44998 14.07 3.72998 12 3.72998C8.47 3.72998 5.18 5.80998 2.89 9.40998C1.99 10.82 1.99 13.19 2.89 14.6C3.68 15.84 4.6 16.91 5.6 17.77" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M8.42 19.53C9.56 20.01 10.77 20.27 12 20.27C15.53 20.27 18.82 18.19 21.11 14.59C22.01 13.18 22.01 10.81 21.11 9.4C20.78 8.88 20.42 8.39 20.05 7.93" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M15.51 12.7C15.25 14.11 14.1 15.26 12.69 15.52" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M9.47 14.53L2 22" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M22 2L14.53 9.47" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`; } }); // Project name validation projectName.addEventListener('blur', function() { const formGroup = this.closest('.form-group'); if (this.value.trim() === '') { formGroup.classList.add('error'); formGroup.classList.remove('success'); } else { formGroup.classList.remove('error'); formGroup.classList.add('success'); } }); // Email validation projectEmail.addEventListener('blur', function() { const formGroup = this.closest('.form-group'); const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(this.value) && this.value.trim() !== '') { formGroup.classList.add('error'); formGroup.classList.remove('success'); } else if (this.value.trim() !== '') { formGroup.classList.remove('error'); formGroup.classList.add('success'); } else { formGroup.classList.remove('error'); formGroup.classList.remove('success'); } }); // Password strength validation projectPassword.addEventListener('input', function() { const value = this.value; const formGroup = this.closest('.form-group'); let strength = 0; // Clear previous states formGroup.classList.remove('error', 'success'); if (value.length >= 8) { strength += 25; } if (value.match(/[A-Z]/)) { strength += 25; } if (value.match(/[0-9]/)) { strength += 25; } if (value.match(/[^A-Za-z0-9]/)) { strength += 25; } strengthMeter.style.width = strength + '%'; if (strength < 50) { strengthMeter.className = 'strength-meter-fill weak'; if (value.length > 0) { formGroup.classList.add('error'); } } else if (strength < 75) { strengthMeter.className = 'strength-meter-fill medium'; formGroup.classList.remove('error'); } else { strengthMeter.className = 'strength-meter-fill strong'; formGroup.classList.add('success'); } }); // Form submission form.addEventListener('submit', function(e) { e.preventDefault(); // Simple validation let isValid = true; if (projectName.value.trim() === '') { projectName.closest('.form-group').classList.add('error'); isValid = false; } const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (projectEmail.value.trim() !== '' && !emailRegex.test(projectEmail.value)) { projectEmail.closest('.form-group').classList.add('error'); isValid = false; } if (projectPassword.value.length < 8 && projectPassword.value.trim() !== '') { projectPassword.closest('.form-group').classList.add('error'); isValid = false; } // Show success animation if valid if (isValid) { // Simulate successful submission with animation document.querySelectorAll('.input-3d').forEach(input => { input.style.transition = 'transform 0.5s ease, box-shadow 0.5s ease'; input.style.transform = 'translateY(-2px) translateZ(4px)'; setTimeout(() => { input.style.transform = 'translateY(0) translateZ(0)'; // Reset form after animation setTimeout(() => { form.reset(); document.querySelectorAll('.form-group').forEach(group => { group.classList.remove('error', 'success'); }); strengthMeter.style.width = '0'; strengthMeter.className = 'strength-meter-fill'; }, 500); }, 500); }); } }); // Add floating animation to inputs on focus document.querySelectorAll('.input-3d').forEach(input => { input.addEventListener('focus', function() { this.style.animation = 'float 3s ease-in-out infinite'; }); input.addEventListener('blur', function() { this.style.animation = 'none'; }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>3D News Cards</title> <style> @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } :root { --primary-color: #2563eb; --accent-color: #8b5cf6; --dark-color: #1e293b; --light-color: #f8fafc; --card-shadow: 0 10px 30px rgba(0, 0, 0, 0.08); --card-hover-shadow: 0 20px 40px rgba(0, 0, 0, 0.15); --transition-speed: 0.35s; --transition-ease: cubic-bezier(0.33, 1, 0.68, 1); } body { font-family: 'Inter', sans-serif; background-color: #f1f5f9; background-image: radial-gradient(#e2e8f0 1px, transparent 1px); background-size: 20px 20px; color: var(--dark-color); overflow-x: hidden; display: flex; flex-direction: column; justify-content: center; align-items: center; min-height: 100vh; padding: 1rem; perspective: 1000px; } .container { width: 100%; max-width: 700px; margin: 0 auto; } header { text-align: center; margin-bottom: 2rem; transform-style: preserve-3d; animation: headerFadeIn 0.8s var(--transition-ease) forwards; opacity: 0; } @keyframes headerFadeIn { from { opacity: 0; transform: translateY(-30px); } to { opacity: 1; transform: translateY(0); } } h1 { font-size: 2.5rem; font-weight: 700; margin-bottom: 0.5rem; background: linear-gradient(135deg, var(--primary-color), var(--accent-color)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; letter-spacing: -0.02em; } p.lead { font-size: 1rem; color: #64748b; max-width: 600px; margin: 0 auto; line-height: 1.6; } .cards-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1.5rem; perspective: 1000px; } .card { background: white; border-radius: 16px; overflow: hidden; position: relative; box-shadow: var(--card-shadow); transform-style: preserve-3d; transform: translateZ(0) rotateX(0) rotateY(0); transition: all var(--transition-speed) var(--transition-ease); cursor: pointer; opacity: 0; animation: cardFadeIn 0.8s var(--transition-ease) forwards; } @keyframes cardFadeIn { from { opacity: 0; transform: translateZ(-50px); } to { opacity: 1; transform: translateZ(0); } } .card:nth-child(1) { animation-delay: 0.1s; } .card:nth-child(2) { animation-delay: 0.2s; } .card:nth-child(3) { animation-delay: 0.3s; } .card:nth-child(4) { animation-delay: 0.4s; } .card:hover { transform: translateZ(30px) scale(1.03); box-shadow: var(--card-hover-shadow); z-index: 10; } .card-image { position: relative; overflow: hidden; height: 180px; } .card-image img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s var(--transition-ease); } .card:hover .card-image img { transform: scale(1.05); } .card-tag { position: absolute; top: 16px; right: 16px; background: rgba(255, 255, 255, 0.9); border-radius: 20px; padding: 0.4rem 0.8rem; font-size: 0.75rem; font-weight: 600; color: var(--primary-color); box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); backdrop-filter: blur(5px); z-index: 2; } .card-content { padding: 1.5rem; position: relative; z-index: 2; background: white; transition: transform var(--transition-speed) var(--transition-ease); } .card:hover .card-content { transform: translateY(-6px); } .card-date { display: block; font-size: 0.8rem; color: #94a3b8; margin-bottom: 0.5rem; } .card h2 { font-size: 1.25rem; font-weight: 700; margin-bottom: 0.75rem; line-height: 1.4; color: var(--dark-color); transition: color 0.3s ease; } .card:hover h2 { background: linear-gradient(135deg, var(--primary-color), var(--accent-color)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .card-excerpt { font-size: 0.9rem; line-height: 1.6; color: #64748b; margin-bottom: 1.5rem; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; } .card-details { height: 0; opacity: 0; overflow: hidden; transition: all var(--transition-speed) var(--transition-ease); font-size: 0.9rem; color: #64748b; line-height: 1.6; } .card:hover .card-details { height: auto; opacity: 1; margin-top: 1rem; } .card-meta { display: flex; align-items: center; justify-content: space-between; font-size: 0.8rem; color: #94a3b8; margin-top: auto; } .card-meta-item { display: flex; align-items: center; gap: 0.3rem; } .card-meta-item svg { width: 16px; height: 16px; fill: #94a3b8; } .card-meta-item span { line-height: 1; } .card-action { position: absolute; bottom: -40px; left: 0; right: 0; background: linear-gradient(135deg, var(--primary-color), var(--accent-color)); color: white; display: flex; align-items: center; justify-content: center; padding: 0.75rem; font-weight: 600; font-size: 0.9rem; transition: transform var(--transition-speed) var(--transition-ease); transform: translateY(0); gap: 0.5rem; } .card:hover .card-action { transform: translateY(-40px); } .card-action svg { width: 18px; height: 18px; fill: white; transition: transform 0.3s ease; } .card:hover .card-action svg { animation: bounceRight 0.8s infinite; } @keyframes bounceRight { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(5px); } } .news-categories { display: flex; flex-wrap: wrap; gap: 0.8rem; margin-bottom: 2rem; justify-content: center; opacity: 0; animation: categoryFadeIn 0.8s var(--transition-ease) 0.3s forwards; } @keyframes categoryFadeIn { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } } .category-btn { background: white; border: none; padding: 0.6rem 1.2rem; border-radius: 30px; font-size: 0.85rem; font-weight: 500; color: #64748b; cursor: pointer; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); transition: all 0.3s ease; position: relative; overflow: hidden; } .category-btn::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient( 90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0) 100% ); transition: all 0.4s ease; } .category-btn:hover::before { left: 100%; } .category-btn:hover { background: linear-gradient(135deg, var(--primary-color), var(--accent-color)); color: white; transform: translateY(-3px); box-shadow: 0 5px 15px rgba(37, 99, 235, 0.2); } .category-btn.active { background: linear-gradient(135deg, var(--primary-color), var(--accent-color)); color: white; box-shadow: 0 4px 15px rgba(37, 99, 235, 0.25); } @media (max-width: 768px) { h1 { font-size: 2rem; } .news-categories { gap: 0.5rem; } .category-btn { padding: 0.5rem 1rem; font-size: 0.8rem; } } @media (max-width: 640px) { .cards-container { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); } h1 { font-size: 1.8rem; } .news-categories { justify-content: flex-start; overflow-x: auto; padding-bottom: 0.5rem; flex-wrap: nowrap; width: 100%; } .category-btn { white-space: nowrap; } } /* Custom animation for 3D depth effect */ .depth-animation { animation: depthPulse 3s infinite alternate ease-in-out; } @keyframes depthPulse { 0% { transform: translateZ(0px); } 100% { transform: translateZ(10px); } } .logo { display: flex; align-items: center; justify-content: center; margin-bottom: 1rem; } .logo svg { width: 40px; height: 40px; fill: url(#logo-gradient); } /* Notification badge */ .notification-badge { position: absolute; top: -5px; right: -5px; background: #ef4444; color: white; border-radius: 50%; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; font-size: 0.7rem; font-weight: 600; transform: scale(0); transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); } .card:nth-child(1) .notification-badge { transform: scale(1); } </style> </head> <body> <div class="container"> <header> <div class="logo"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <defs> <linearGradient id="logo-gradient" x1="0%" y1="0%" x2="100%" y2="100%"> <stop offset="0%" stop-color="#2563eb" /> <stop offset="100%" stop-color="#8b5cf6" /> </linearGradient> </defs> <path d="M12,22.5C6.2,22.5,1.5,17.8,1.5,12S6.2,1.5,12,1.5S22.5,6.2,22.5,12S17.8,22.5,12,22.5z M12,3C7,3,3,7,3,12s4,9,9,9s9-4,9-9S17,3,12,3z M16.25,14.25L7.75,9.75V17h1.5v-4.13l5.69,3.38L16.25,14.25z M16.25,10.75v3.5L9.25,10L16.25,10.75z"/> </svg> </div> <h1 class="depth-animation">Orbital News</h1> <p class="lead">Dive into today's stories with our immersive 3D news experience</p> </header> <div class="news-categories"> <button class="category-btn active">Top Stories</button> <button class="category-btn">Technology</button> <button class="category-btn">Science</button> <button class="category-btn">Climate</button> <button class="category-btn">Business</button> <button class="category-btn">Culture</button> </div> <div class="cards-container"> <div class="card"> <div class="notification-badge">1</div> <div class="card-image"> <img src="https://images.unsplash.com/photo-1581090464777-f3220bbe1b8b?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80" alt="AI semiconductor development" /> <div class="card-tag">Breaking</div> </div> <div class="card-content"> <span class="card-date">May 24, 2023 • 11 min read</span> <h2>Quantum Computing Breakthrough Enables New AI Applications</h2> <p class="card-excerpt">Scientists have achieved stable qubits at room temperature, potentially revolutionizing artificial intelligence capabilities and computational power.</p> <div class="card-details"> <p>The development emerged from a collaboration between MIT, Stanford, and CERN researchers, who discovered a novel way to maintain quantum coherence using synthetic diamond substrates with nitrogen vacancies.</p> </div> <div class="card-meta"> <div class="card-meta-item"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/> </svg> <span>Dr. Emma Chen</span> </div> <div class="card-meta-item"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-1-13h2v6h-2zm0 8h2v2h-2z"/> </svg> <span>3.4K views</span> </div> </div> </div> <div class="card-action"> Read Article <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8-8-8z"/> </svg> </div> </div> <div class="card"> <div class="card-image"> <img src="https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80" alt="Urban architecture" /> <div class="card-tag">Featured</div> </div> <div class="card-content"> <span class="card-date">May 23, 2023 • 8 min read</span> <h2>Smart Cities: The Urban Revolution Nobody Saw Coming</h2> <p class="card-excerpt">How intelligent infrastructure and data-driven urban planning are transforming metropolitan areas around the globe.</p> <div class="card-details"> <p>Singapore's recent deployment of autonomous public transportation networks has decreased traffic congestion by 37% while cutting carbon emissions by nearly a quarter in just six months.</p> </div> <div class="card-meta"> <div class="card-meta-item"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/> </svg> <span>James Wilson</span> </div> <div class="card-meta-item"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-1-13h2v6h-2zm0 8h2v2h-2z"/> </svg> <span>2.7K views</span> </div> </div> </div> <div class="card-action"> Read Article <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8-8-8z"/> </svg> </div> </div> <div class="card"> <div class="card-image"> <img src="https://images.unsplash.com/photo-1495020689067-958852a7765e?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80" alt="Mediterranean diet foods" /> <div class="card-tag">Health</div> </div> <div class="card-content"> <span class="card-date">May 22, 2023 • 6 min read</span> <h2>Mediterranean Diet Linked to Extended Cognitive Health</h2> <p class="card-excerpt">New longitudinal study confirms olive oil, nuts, and fish consumption correlates with preserved brain function well into the ninth decade.</p> <div class="card-details"> <p>The 30-year study tracked over 8,000 participants across multiple Mediterranean countries, finding that those who adhered most strictly to traditional diets showed 68% lower rates of neurodegenerative conditions.</p> </div> <div class="card-meta"> <div class="card-meta-item"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/> </svg> <span>Dr. Sophia Patel</span> </div> <div class="card-meta-item"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-1-13h2v6h-2zm0 8h2v2h-2z"/> </svg> <span>5.1K views</span> </div> </div> </div> <div class="card-action"> Read Article <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8-8-8z"/> </svg> </div> </div> <div class="card"> <div class="card-image"> <img src="https://images.unsplash.com/photo-1511108690759-009324a90311?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80" alt="Renewable energy wind farm" /> <div class="card-tag">Climate</div> </div> <div class="card-content"> <span class="card-date">May 21, 2023 • 9 min read</span> <h2>Carbon Capture Technology Exceeds Efficiency Targets</h2> <p class="card-excerpt">Revolutionary new materials developed at Oxford achieve 300% better CO2 absorption rates than previous generation technology.</p> <div class="card-details"> <p>The breakthrough involves metal-organic frameworks (MOFs) with unprecedented surface area, allowing industrial facilities to capture up to 95% of emissions while consuming 40% less energy than earlier systems.</p> </div> <div class="card-meta"> <div class="card-meta-item"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/> </svg> <span>Alex Mercer</span> </div> <div class="card-meta-item"> <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-1-13h2v6h-2zm0 8h2v2h-2z"/> </svg> <span>1.8K views</span> </div> </div> </div> <div class="card-action"> Read Article <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8-8-8z"/> </svg> </div> </div> </div> </div> <script> // Handle card 3D rotation effect document.querySelectorAll('.card').forEach(card => { card.addEventListener('mousemove', (e) => { const cardRect = card.getBoundingClientRect(); const cardCenterX = cardRect.left + cardRect.width / 2; const cardCenterY = cardRect.top + cardRect.height / 2; // Calculate distance from center as percentage const percentX = (e.clientX - cardCenterX) / (cardRect.width / 2); const percentY = (e.clientY - cardCenterY) / (cardRect.height / 2); // Limit the rotation angle const rotateX = percentY * -8; // Inverted for correct rotation const rotateY = percentX * 8; card.style.transform = `translateZ(30px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`; }); card.addEventListener('mouseleave', () => { card.style.transform = 'translateZ(0) rotateX(0) rotateY(0)'; }); }); // Handle category button clicks document.querySelectorAll('.category-btn').forEach(button => { button.addEventListener('click', function() { // Remove active class from all buttons document.querySelectorAll('.category-btn').forEach(btn => { btn.classList.remove('active'); }); // Add active class to clicked button this.classList.add('active'); // Simulate content change with animation const cards = document.querySelectorAll('.card'); cards.forEach((card, index) => { card.style.opacity = '0'; card.style.transform = 'translateZ(-50px)'; setTimeout(() => { card.style.opacity = '1'; card.style.transform = 'translateZ(0)'; }, 300 + index * 100); }); }); }); // Animation for cards on load document.addEventListener('DOMContentLoaded', () => { const cards = document.querySelectorAll('.card'); cards.forEach((card, index) => { setTimeout(() => { card.style.opacity = '1'; card.style.transform = 'translateZ(0)'; }, 500 + index * 100); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>3D Globe Explorer</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', 'Segoe UI', sans-serif; } body { background: #0e0e10; color: #f5f5f7; overflow: hidden; height: 100vh; width: 100%; display: flex; justify-content: center; align-items: center; } .globe-container { position: relative; width: 700px; height: 700px; display: flex; flex-direction: column; justify-content: center; align-items: center; overflow: hidden; } #globe { width: 100%; height: 100%; position: relative; cursor: grab; } #globe:active { cursor: grabbing; } .controls { position: absolute; bottom: 20px; display: flex; gap: 15px; z-index: 1000; background: rgba(22, 22, 26, 0.8); padding: 10px 20px; border-radius: 30px; backdrop-filter: blur(10px); box-shadow: 0 4px 30px rgba(0, 0, 0, 0.2); transition: all 0.3s ease; } .controls:hover { background: rgba(22, 22, 26, 0.9); } .btn { background: none; border: none; color: #f5f5f7; font-size: 18px; cursor: pointer; width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; transition: all 0.2s ease; } .btn:hover { background: rgba(255, 255, 255, 0.1); } .slider { -webkit-appearance: none; width: 100px; height: 5px; border-radius: 5px; background: #2d2d35; outline: none; transition: all 0.3s; margin: auto 0; } .slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 15px; height: 15px; border-radius: 50%; background: #4fbdff; cursor: pointer; transition: all 0.2s; } .slider::-webkit-slider-thumb:hover { transform: scale(1.2); background: #6dc8ff; } .location-info { position: absolute; top: 20px; left: 20px; background: rgba(22, 22, 26, 0.8); padding: 15px 20px; border-radius: 12px; backdrop-filter: blur(10px); box-shadow: 0 4px 30px rgba(0, 0, 0, 0.2); max-width: 280px; opacity: 0; transform: translateY(-10px); transition: all 0.3s ease; z-index: 1000; } .location-info.active { opacity: 1; transform: translateY(0); } .location-info h3 { margin-bottom: 8px; font-size: 18px; font-weight: 600; color: #fff; } .location-info p { margin-bottom: 5px; font-size: 14px; line-height: 1.4; color: rgba(255, 255, 255, 0.8); } .location-info .close { position: absolute; top: 12px; right: 12px; background: none; border: none; color: #f5f5f7; font-size: 18px; cursor: pointer; opacity: 0.7; transition: opacity 0.2s; } .location-info .close:hover { opacity: 1; } .loading { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: #0e0e10; display: flex; justify-content: center; align-items: center; flex-direction: column; z-index: 2000; transition: opacity 0.5s ease; } .loading h2 { margin-top: 20px; font-size: 22px; color: #4fbdff; } .spinner { width: 50px; height: 50px; border: 5px solid rgba(255, 255, 255, 0.1); border-radius: 50%; border-top-color: #4fbdff; animation: spin 1s ease-in-out infinite; } @keyframes spin { to { transform: rotate(360deg); } } .marker { position: absolute; width: 12px; height: 12px; background: #4fbdff; border-radius: 50%; transform: translate(-50%, -50%); cursor: pointer; transition: all 0.2s ease; box-shadow: 0 0 0 2px rgba(79, 189, 255, 0.3), 0 0 0 0 rgba(79, 189, 255, 0.5); animation: pulse 2s infinite; } .marker:hover { transform: translate(-50%, -50%) scale(1.4); background: #fff; animation: none; box-shadow: 0 0 20px 5px rgba(79, 189, 255, 0.5); } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(79, 189, 255, 0.5); } 70% { box-shadow: 0 0 0 10px rgba(79, 189, 255, 0); } 100% { box-shadow: 0 0 0 0 rgba(79, 189, 255, 0); } } .category-filter { position: absolute; top: 20px; right: 20px; background: rgba(22, 22, 26, 0.8); padding: 12px 15px; border-radius: 12px; backdrop-filter: blur(10px); box-shadow: 0 4px 30px rgba(0, 0, 0, 0.2); z-index: 1000; display: flex; flex-direction: column; gap: 8px; } .category-filter h4 { font-size: 14px; margin-bottom: 5px; color: rgba(255, 255, 255, 0.9); } .category-item { display: flex; align-items: center; gap: 8px; cursor: pointer; padding: 4px 0; } .category-color { width: 12px; height: 12px; border-radius: 50%; } .category-name { font-size: 13px; color: rgba(255, 255, 255, 0.8); transition: color 0.2s; } .category-item:hover .category-name { color: #fff; } .category-item.active .category-name { color: #4fbdff; font-weight: 500; } .attribution { position: absolute; bottom: 15px; right: 15px; font-size: 10px; color: rgba(255, 255, 255, 0.5); z-index: 900; } .welcome-tooltip { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(22, 22, 26, 0.95); padding: 20px; border-radius: 12px; backdrop-filter: blur(10px); box-shadow: 0 10px 50px rgba(0, 0, 0, 0.3); width: 320px; z-index: 1500; text-align: center; animation: fadeInUp 0.5s forwards; } @keyframes fadeInUp { from { opacity: 0; transform: translate(-50%, -40%); } to { opacity: 1; transform: translate(-50%, -50%); } } .welcome-tooltip h3 { margin-bottom: 10px; font-size: 20px; color: #4fbdff; } .welcome-tooltip p { margin-bottom: 15px; font-size: 14px; line-height: 1.5; color: rgba(255, 255, 255, 0.8); } .welcome-tooltip button { background: #4fbdff; color: #111; border: none; padding: 8px 16px; border-radius: 6px; font-weight: 500; cursor: pointer; transition: all 0.2s ease; } .welcome-tooltip button:hover { background: #6dc8ff; transform: translateY(-2px); } @media (max-width: 700px) { .globe-container { width: 100%; height: 100%; } .controls { bottom: 15px; padding: 8px 15px; } .location-info { max-width: 220px; } .category-filter { top: 15px; right: 15px; padding: 10px; } } </style> </head> <body> <div class="globe-container"> <div id="globe"></div> <div class="loading"> <div class="spinner"></div> <h2>Loading GeoExplore...</h2> </div> <div class="welcome-tooltip"> <h3>Welcome to GeoExplore</h3> <p>Discover cultural landmarks, natural wonders, and urban hotspots across our interactive 3D globe. Rotate, zoom, and click on markers to learn more about each location.</p> <button id="start-exploring">Start Exploring</button> </div> <div class="location-info"> <button class="close">×</button> <h3 id="location-name">Location Name</h3> <p id="location-desc">Description goes here</p> <p id="location-stats">Statistics</p> </div> <div class="category-filter"> <h4>Filter Locations</h4> <div class="category-item active" data-category="all"> <div class="category-color" style="background: #ffffff;"></div> <span class="category-name">All Locations</span> </div> <div class="category-item" data-category="natural"> <div class="category-color" style="background: #4CAF50;"></div> <span class="category-name">Natural Wonders</span> </div> <div class="category-item" data-category="cultural"> <div class="category-color" style="background: #FF9800;"></div> <span class="category-name">Cultural Landmarks</span> </div> <div class="category-item" data-category="urban"> <div class="category-color" style="background: #9C27B0;"></div> <span class="category-name">Urban Hotspots</span> </div> </div> <div class="controls"> <button class="btn" id="zoom-in">+</button> <input type="range" min="0" max="100" value="50" class="slider" id="zoom-slider"> <button class="btn" id="zoom-out">−</button> <button class="btn" id="rotate">⟳</button> </div> <div class="attribution">Data visualization powered by GeoExplore © 2023</div> </div> <script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js"></script> <script> document.addEventListener('DOMContentLoaded', function() { // Global variables let scene, camera, renderer, globe, controls; let rotating = false; let currentFilter = 'all'; const markers = []; const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(); // Location data with categories const locations = [ { name: "Machu Picchu", lat: -13.1631, lon: -72.5450, description: "Ancient Incan citadel set high in the Andes Mountains, built in the 15th century and later abandoned.", stats: "Elevation: 2,430m | Annual visitors: 1.5M | UNESCO site since 1983", category: "cultural" }, { name: "Great Barrier Reef", lat: -18.2871, lon: 147.6992, description: "World's largest coral reef system composed of over 2,900 individual reefs and 900 islands stretching for 2,300 kilometers.", stats: "Area: 344,400 km² | Marine species: 9,000+ | Coral types: 400+", category: "natural" }, { name: "Tokyo", lat: 35.6762, lon: 139.6503, description: "Japan's busy capital that mixes ultramodern and traditional elements, from neon-lit skyscrapers to historic temples.", stats: "Population: 37M (metro) | Area: 2,194 km² | Founded: 1457", category: "urban" }, { name: "Serengeti National Park", lat: -2.3333, lon: 34.8333, description: "Tanzania's oldest and most popular national park, known for its annual migration of over 1.5 million wildebeest.", stats: "Area: 14,750 km² | Species: 500+ birds, 70+ mammals | Established: 1951", category: "natural" }, { name: "Pyramids of Giza", lat: 29.9792, lon: 31.1342, description: "Ancient Egyptian necropolis featuring the Great Pyramid, the only surviving structure of the Seven Wonders of the Ancient World.", stats: "Age: 4,500+ years | Great Pyramid height: 138m | Stones used: 2.3M", category: "cultural" }, { name: "New York City", lat: 40.7128, lon: -74.0060, description: "Global financial center and cultural capital of the world, home to iconic landmarks like the Empire State Building and Statue of Liberty.", stats: "Population: 8.4M | Boroughs: 5 | Founded: 1624", category: "urban" }, { name: "Antarctica", lat: -75.2500, lon: 0.0000, description: "Earth's southernmost continent, containing the geographic South Pole. Nearly twice the size of Australia, it's the coldest, driest, and windiest continent.", stats: "Area: 14M km² | Avg. temp: -57°C | Ice thickness: 1.9km avg.", category: "natural" }, { name: "Angkor Wat", lat: 13.4125, lon: 103.8667, description: "Cambodia's iconic temple complex and the largest religious monument in the world, built in the 12th century.", stats: "Area: 162.6 hectares | Construction: Early 12th century | Style: Khmer architecture", category: "cultural" }, { name: "São Paulo", lat: -23.5505, lon: -46.6333, description: "Brazil's vibrant financial center and one of the world's most populous cities with diverse architectural styles.", stats: "Population: 12.3M | Founded: 1554 | Skyscrapers: 6,000+", category: "urban" } ]; // Initialize the globe function init() { // Create scene scene = new THREE.Scene(); scene.background = new THREE.Color(0x0e0e10); // Create camera camera = new THREE.PerspectiveCamera(75, 700 / 700, 0.1, 1000); camera.position.z = 2; // Create renderer renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(700, 700); renderer.setPixelRatio(window.devicePixelRatio); document.getElementById('globe').appendChild(renderer.domElement); // Create Earth globe const geometry = new THREE.SphereGeometry(1, 64, 64); // Load Earth texture with a detailed map const textureLoader = new THREE.TextureLoader(); const earthTexture = textureLoader.load('https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/textures/planets/earth_atmos_4k.jpg', function() { setTimeout(() => { document.querySelector('.loading').style.opacity = 0; setTimeout(() => { document.querySelector('.loading').style.display = 'none'; }, 500); }, 1000); }); const bumpMap = textureLoader.load('https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/textures/planets/earth_normal_2k.jpg'); const specMap = textureLoader.load('https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/textures/planets/earth_specular_2k.jpg'); const material = new THREE.MeshPhongMaterial({ map: earthTexture, bumpMap: bumpMap, bumpScale: 0.05, specularMap: specMap, specular: new THREE.Color(0x333333), shininess: 15 }); globe = new THREE.Mesh(geometry, material); scene.add(globe); // Add ambient light const ambientLight = new THREE.AmbientLight(0x404040, 0.8); scene.add(ambientLight); // Add directional light to create shadows const directionalLight = new THREE.DirectionalLight(0xffffff, 1); directionalLight.position.set(5, 3, 5); scene.add(directionalLight); // Add subtle blue atmosphere const atmosphereGeometry = new THREE.SphereGeometry(1.01, 64, 64); const atmosphereMaterial = new THREE.MeshPhongMaterial({ color: 0x4ca6ff, transparent: true, opacity: 0.15, side: THREE.BackSide }); const atmosphere = new THREE.Mesh(atmosphereGeometry, atmosphereMaterial); scene.add(atmosphere); // Create controls controls = new THREE.OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.1; controls.rotateSpeed = 0.5; controls.minDistance = 1.2; controls.maxDistance = 4; controls.enablePan = false; // Create location markers createMarkers(); // Add event listeners document.getElementById('zoom-in').addEventListener('click', () => { zoomGlobe(-0.5); }); document.getElementById('zoom-out').addEventListener('click', () => { zoomGlobe(0.5); }); document.getElementById('zoom-slider').addEventListener('input', (e) => { const value = e.target.value; const distance = 4 - (value / 100) * 2.8; camera.position.setLength(distance); }); document.getElementById('rotate').addEventListener('click', () => { rotating = !rotating; document.getElementById('rotate').style.background = rotating ? 'rgba(79, 189, 255, 0.3)' : 'transparent'; }); document.querySelector('.location-info .close').addEventListener('click', () => { document.querySelector('.location-info').classList.remove('active'); }); renderer.domElement.addEventListener('click', onGlobeClick); // Category filter events document.querySelectorAll('.category-item').forEach(item => { item.addEventListener('click', function() { const category = this.getAttribute('data-category'); currentFilter = category; // Update active state document.querySelectorAll('.category-item').forEach(el => { el.classList.remove('active'); }); this.classList.add('active'); // Filter markers filterMarkers(category); }); }); document.getElementById('start-exploring').addEventListener('click', function() { document.querySelector('.welcome-tooltip').style.display = 'none'; }); // Handle resize window.addEventListener('resize', onWindowResize); // Start animation loop animate(); } function createMarkers() { // Remove existing DOM markers document.querySelectorAll('.marker').forEach(el => el.remove()); locations.forEach(location => { // Convert lat/lon to 3D position const position = latLonToVector3(location.lat, location.lon); // Create DOM marker const marker = document.createElement('div'); marker.className = 'marker'; marker.dataset.name = location.name; marker.dataset.category = location.category; // Set marker color based on category if (location.category === 'natural') { marker.style.background = '#4CAF50'; } else if (location.category === 'cultural') { marker.style.background = '#FF9800'; } else if (location.category === 'urban') { marker.style.background = '#9C27B0'; } document.getElementById('globe').appendChild(marker); // Store marker data markers.push({ element: marker, position: position, locationData: location }); }); } function filterMarkers(category) { markers.forEach(marker => { if (category === 'all' || marker.locationData.category === category) { marker.element.style.display = 'block'; } else { marker.element.style.display = 'none'; } }); } function updateMarkerPositions() { markers.forEach(marker => { // Apply rotation to the marker's position const position = marker.position.clone(); position.applyQuaternion(globe.quaternion); // Check if the point is on the visible side of the globe const dot = position.clone().normalize().dot(camera.position.clone().normalize()); if (dot > 0) { // Convert 3D position to screen coordinates const screenPosition = position.clone().project(camera); // Convert to DOM coordinates const x = (screenPosition.x * 0.5 + 0.5) * renderer.domElement.clientWidth; const y = (-screenPosition.y * 0.5 + 0.5) * renderer.domElement.clientHeight; // Scale based on distance from camera to make farther markers smaller const distance = camera.position.distanceTo(position); const scale = Math.max(0.5, 2 - distance * 0.5); // Update marker position and scale marker.element.style.transform = `translate(-50%, -50%) scale(${scale})`; marker.element.style.left = `${x}px`; marker.element.style.top = `${y}px`; marker.element.style.opacity = ((dot - 0.2) * 5) / 4; } else { // Hide the marker if it's on the back side marker.element.style.opacity = 0; } }); } function latLonToVector3(lat, lon) { const phi = (90 - lat) * (Math.PI / 180); const theta = (lon + 180) * (Math.PI / 180); const x = -Math.sin(phi) * Math.cos(theta); const z = Math.sin(phi) * Math.sin(theta); const y = Math.cos(phi); return new THREE.Vector3(x, y, z); } function onGlobeClick(event) { // Get normalized mouse coordinates mouse.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1; mouse.y = -(event.clientY / renderer.domElement.clientHeight) * 2 + 1; // Check if a marker was clicked const clicked = document.elementFromPoint(event.clientX, event.clientY); if (clicked && clicked.classList.contains('marker')) { const locationName = clicked.dataset.name; const location = locations.find(loc => loc.name === locationName); if (location) { document.getElementById('location-name').textContent = location.name; document.getElementById('location-desc').textContent = location.description; document.getElementById('location-stats').textContent = location.stats; document.querySelector('.location-info').classList.add('active'); } return; } // If no marker was clicked, check if globe was clicked raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObject(globe); if (intersects.length > 0) { // Get the clicked point on the globe const point = intersects[0].point.clone().normalize(); // Convert to lat/lon const lat = 90 - (Math.acos(point.y) * 180 / Math.PI); const lon = ((Math.atan2(point.z, point.x) * 180 / Math.PI) + 270) % 360 - 180; // Close any open info windows document.querySelector('.location-info').classList.remove('active'); } } function zoomGlobe(delta) { const newPos = camera.position.clone(); newPos.multiplyScalar(1 + (delta * 0.1)); // Respect min/max distances if (newPos.length() >= controls.minDistance && newPos.length() <= controls.maxDistance) { camera.position.copy(newPos); // Update slider const sliderValue = 100 - ((camera.position.length() - 1.2) / 2.8 * 100); document.getElementById('zoom-slider').value = sliderValue; } } function onWindowResize() { const container = document.querySelector('.globe-container'); const width = container.clientWidth; const height = container.clientHeight; camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize(width, height); } function animate() { requestAnimationFrame(animate); // Auto-rotate if enabled if (rotating) { globe.rotation.y += 0.002; } // Update controls controls.update(); // Update marker positions updateMarkerPositions(); // Render scene renderer.render(scene, camera); } // Initialize the application init(); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { display: flex; justify-content: center; align-items: center; min-height: 700px; width: 100%; background: linear-gradient(135deg, #1a1f29, #2a3040); perspective: 1000px; overflow: hidden; } .ar-environment { position: relative; width: 100%; max-width: 600px; height: 500px; transform-style: preserve-3d; transition: transform 0.8s ease; } .grid { position: absolute; width: 100%; height: 100%; background-image: linear-gradient(rgba(50, 130, 230, 0.1) 1px, transparent 1px), linear-gradient(90deg, rgba(50, 130, 230, 0.1) 1px, transparent 1px); background-size: 30px 30px; transform: rotateX(60deg) translateZ(-100px); perspective: 500px; animation: grid-move 20s linear infinite; box-shadow: 0 0 100px rgba(50, 130, 230, 0.3); opacity: 0.5; } @keyframes grid-move { 0% { background-position: 0 0; } 100% { background-position: 0 100%; } } .container { position: relative; width: 100%; max-width: 500px; display: flex; flex-direction: column; align-items: center; justify-content: center; transform-style: preserve-3d; z-index: 10; } .title { color: #fff; font-size: 2.3rem; margin-bottom: 50px; text-align: center; text-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); transform: translateZ(60px); opacity: 0; animation: title-appear 1s ease-out forwards 0.5s; } @keyframes title-appear { to { opacity: 1; transform: translateZ(60px); } } .button-container { position: relative; perspective: 800px; transform-style: preserve-3d; width: 260px; height: 80px; margin: 20px 0; } .ar-button { position: relative; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; color: white; font-size: 1.3rem; font-weight: 600; letter-spacing: 1px; text-transform: uppercase; background: linear-gradient(135deg, #ff4d8c, #ff3366); border: none; border-radius: 15px; box-shadow: 0 15px 35px rgba(255, 51, 102, 0.5), 0 5px 15px rgba(0, 0, 0, 0.2), 0 -3px 5px rgba(255, 255, 255, 0.2) inset, 0 5px 10px rgba(0, 0, 0, 0.4) inset; cursor: pointer; transition: all 0.3s ease, transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); transform: translateZ(40px); transform-style: preserve-3d; overflow: hidden; user-select: none; } .ar-button::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(135deg, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0)); transform: translateZ(1px); pointer-events: none; opacity: 0.7; } .ar-button::after { content: ''; position: absolute; top: -50%; left: -50%; width: 200%; height: 200%; background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 0%, transparent 70%); opacity: 0; transform: translateZ(1px); transition: opacity 0.3s ease; pointer-events: none; } .ar-button:hover { transform: translateZ(50px) scale(1.05); box-shadow: 0 20px 40px rgba(255, 51, 102, 0.6), 0 10px 25px rgba(0, 0, 0, 0.3), 0 -3px 5px rgba(255, 255, 255, 0.3) inset, 0 5px 10px rgba(0, 0, 0, 0.5) inset; } .ar-button:active { transform: translateZ(20px) scale(0.95); box-shadow: 0 10px 20px rgba(255, 51, 102, 0.4), 0 5px 10px rgba(0, 0, 0, 0.2), 0 -2px 3px rgba(255, 255, 255, 0.2) inset, 0 3px 5px rgba(0, 0, 0, 0.3) inset; background: linear-gradient(135deg, #ff3366, #ff1a53); transition: all 0.1s ease; } .ar-button:hover::after { opacity: 1; } .button-shadow { position: absolute; width: 90%; height: 20px; bottom: -25px; left: 5%; background: radial-gradient(ellipse, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0) 70%); border-radius: 50%; transform: rotateX(90deg); filter: blur(5px); opacity: 0.7; transition: all 0.3s ease; } .ar-button:hover + .button-shadow { width: 95%; height: 25px; bottom: -30px; left: 2.5%; opacity: 0.9; } .ar-button:active + .button-shadow { width: 85%; height: 15px; bottom: -20px; left: 7.5%; opacity: 0.5; } .button-icon { margin-right: 10px; font-size: 1.4rem; transition: transform 0.3s ease; } .ar-button:hover .button-icon { transform: scale(1.2) rotate(10deg); } .feedback { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; overflow: hidden; z-index: 2; } .ripple { position: absolute; border-radius: 50%; background: rgba(255, 255, 255, 0.4); transform: scale(0); animation: ripple 0.8s ease-out; } @keyframes ripple { to { transform: scale(2.5); opacity: 0; } } .particles { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .particle { position: absolute; background: rgba(255, 255, 255, 0.8); border-radius: 50%; width: 5px; height: 5px; pointer-events: none; } .tooltip { position: absolute; top: -70px; left: 50%; transform: translateX(-50%) translateZ(40px) scale(0); background: rgba(0, 0, 0, 0.8); color: white; padding: 10px 15px; border-radius: 8px; font-size: 0.9rem; opacity: 0; transition: transform 0.3s ease, opacity 0.3s ease; pointer-events: none; white-space: nowrap; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); } .tooltip::after { content: ''; position: absolute; bottom: -8px; left: 50%; transform: translateX(-50%); border-width: 8px 8px 0; border-style: solid; border-color: rgba(0, 0, 0, 0.8) transparent transparent transparent; } .button-container:hover .tooltip { transform: translateX(-50%) translateZ(40px) scale(1); opacity: 1; } .status-text { margin-top: 50px; color: white; font-size: 1.1rem; text-align: center; opacity: 0; transform: translateY(20px); transition: opacity 0.5s ease, transform 0.5s ease; } .status-text.active { opacity: 1; transform: translateY(0); } @media (max-width: 600px) { .title { font-size: 1.8rem; margin-bottom: 30px; } .button-container { width: 220px; height: 70px; } .ar-button { font-size: 1.1rem; } } @media (max-width: 400px) { .title { font-size: 1.5rem; } .button-container { width: 200px; height: 60px; } .ar-button { font-size: 1rem; } } </style> </head> <body> <div class="ar-environment"> <div class="grid"></div> <div class="container"> <h1 class="title">Spatial AR Interface Control</h1> <div class="button-container" id="launch-button"> <div class="tooltip">Launches the neural interface scanner</div> <button class="ar-button" aria-label="Launch AR Experience"> <span class="button-icon">⚡</span> <span>Launch Neural Scan</span> </button> <div class="button-shadow"></div> <div class="feedback"></div> </div> <div class="button-container" id="calibrate-button"> <div class="tooltip">Calibrates spatial depth perception</div> <button class="ar-button" aria-label="Calibrate AR System"> <span class="button-icon">⚙️</span> <span>Calibrate Depth</span> </button> <div class="button-shadow"></div> <div class="feedback"></div> </div> <div class="status-text" id="status-text">System ready for augmented reality initialization</div> </div> </div> <div class="particles" id="particles-container"></div> <script> document.addEventListener('DOMContentLoaded', () => { const buttons = document.querySelectorAll('.ar-button'); const statusText = document.getElementById('status-text'); const particlesContainer = document.getElementById('particles-container'); const arEnvironment = document.querySelector('.ar-environment'); // Haptic feedback simulation function simulateHapticFeedback() { if (navigator.vibrate) { navigator.vibrate(30); } } // Add ripple effect and handle button press buttons.forEach(button => { button.addEventListener('mousedown', function(e) { simulateHapticFeedback(); // Create ripple effect const feedback = this.parentElement.querySelector('.feedback'); const rect = feedback.getBoundingClientRect(); const ripple = document.createElement('div'); ripple.className = 'ripple'; const x = e.clientX - rect.left; const y = e.clientY - rect.top; ripple.style.left = `${x}px`; ripple.style.top = `${y}px`; feedback.appendChild(ripple); // Remove ripple after animation completes setTimeout(() => { ripple.remove(); }, 800); // Create particles createParticles(e.clientX, e.clientY); // Update status text based on which button was pressed if (this.closest('#launch-button')) { statusText.textContent = "Neural scan initialized. Processing spatial environment..."; arEnvironment.style.transform = 'rotateY(5deg) rotateX(-3deg)'; } else if (this.closest('#calibrate-button')) { statusText.textContent = "Calibrating depth sensors. Please remain still..."; arEnvironment.style.transform = 'rotateY(-5deg) rotateX(3deg)'; } // Show status text statusText.classList.add('active'); }); }); // Create particles effect function createParticles(x, y) { for (let i = 0; i < 15; i++) { const particle = document.createElement('div'); particle.className = 'particle'; // Position particle near the cursor particle.style.left = `${x}px`; particle.style.top = `${y}px`; // Random size const size = Math.random() * 8 + 2; particle.style.width = `${size}px`; particle.style.height = `${size}px`; // Random color variations const hue = Math.random() * 30 + 340; // Red to pink range particle.style.backgroundColor = `hsla(${hue}, 100%, 70%, ${Math.random() * 0.7 + 0.3})`; // Random direction const angle = Math.random() * Math.PI * 2; const velocity = Math.random() * 5 + 3; const vx = Math.cos(angle) * velocity; const vy = Math.sin(angle) * velocity; // Add to container particlesContainer.appendChild(particle); // Animate and remove let posX = x; let posY = y; let opacity = 1; let size = parseInt(particle.style.width); function animateParticle() { if (opacity <= 0) { particle.remove(); return; } posX += vx; posY += vy; opacity -= 0.03; size *= 0.97; particle.style.left = `${posX}px`; particle.style.top = `${posY}px`; particle.style.opacity = opacity; particle.style.width = `${size}px`; particle.style.height = `${size}px`; requestAnimationFrame(animateParticle); } requestAnimationFrame(animateParticle); } } // 3D parallax effect on mouse movement document.addEventListener('mousemove', (e) => { const xAxis = (window.innerWidth / 2 - e.pageX) / 25; const yAxis = (window.innerHeight / 2 - e.pageY) / 25; arEnvironment.style.transform = `rotateY(${xAxis}deg) rotateX(${yAxis}deg)`; }); // Reset transformation when mouse leaves document.addEventListener('mouseleave', () => { arEnvironment.style.transform = 'rotateY(0) rotateX(0)'; }); // Show initial status after a delay setTimeout(() => { statusText.classList.add('active'); }, 1000); }); </script> </body> </html>