713 lines
26 KiB
HTML
713 lines
26 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>UI Innovation: GravityNav - Physics-Based Navigation</title>
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
line-height: 1.6;
|
|
color: #333;
|
|
background: radial-gradient(ellipse at center, #0f0f23 0%, #040410 100%);
|
|
min-height: 100vh;
|
|
padding: 20px;
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
header {
|
|
text-align: center;
|
|
margin-bottom: 40px;
|
|
background: rgba(255, 255, 255, 0.95);
|
|
padding: 30px;
|
|
border-radius: 15px;
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
h1 {
|
|
color: #2d2d5a;
|
|
margin-bottom: 20px;
|
|
font-size: 2.5em;
|
|
}
|
|
|
|
.innovation-meta {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 40px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.innovation-meta p {
|
|
background: #e8e8f5;
|
|
padding: 10px 20px;
|
|
border-radius: 8px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
main {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
section {
|
|
background: rgba(255, 255, 255, 0.95);
|
|
margin-bottom: 30px;
|
|
padding: 30px;
|
|
border-radius: 15px;
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
h2 {
|
|
color: #2d2d5a;
|
|
margin-bottom: 25px;
|
|
font-size: 1.8em;
|
|
}
|
|
|
|
h3 {
|
|
color: #3a3a6b;
|
|
margin-bottom: 15px;
|
|
font-size: 1.3em;
|
|
}
|
|
|
|
.demo-container {
|
|
background: radial-gradient(ellipse at center, #1a1a3a 0%, #0a0a1a 100%);
|
|
color: white;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.gravitynav-container {
|
|
position: relative;
|
|
width: 100%;
|
|
height: 400px;
|
|
background: transparent;
|
|
border-radius: 15px;
|
|
overflow: hidden;
|
|
cursor: crosshair;
|
|
}
|
|
|
|
.star-field {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.star {
|
|
position: absolute;
|
|
background: white;
|
|
border-radius: 50%;
|
|
opacity: 0.7;
|
|
animation: twinkle 3s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes twinkle {
|
|
0%, 100% { opacity: 0.3; }
|
|
50% { opacity: 0.9; }
|
|
}
|
|
|
|
.nav-planet {
|
|
position: absolute;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
user-select: none;
|
|
box-shadow: 0 0 20px rgba(255, 255, 255, 0.3);
|
|
text-shadow: 0 0 10px rgba(255, 255, 255, 0.8);
|
|
transform-origin: center;
|
|
}
|
|
|
|
.nav-planet:hover {
|
|
box-shadow: 0 0 30px rgba(255, 255, 255, 0.6);
|
|
z-index: 10;
|
|
}
|
|
|
|
.nav-planet:focus {
|
|
outline: 3px solid #ffff00;
|
|
outline-offset: 5px;
|
|
box-shadow: 0 0 40px rgba(255, 255, 0, 0.8);
|
|
}
|
|
|
|
.nav-planet.active {
|
|
box-shadow: 0 0 50px rgba(255, 215, 0, 1);
|
|
z-index: 20;
|
|
}
|
|
|
|
.planet-home {
|
|
background: radial-gradient(circle at 30% 30%, #ff6b6b, #d63031);
|
|
color: white;
|
|
}
|
|
|
|
.planet-about {
|
|
background: radial-gradient(circle at 30% 30%, #4ecdc4, #00b894);
|
|
color: white;
|
|
}
|
|
|
|
.planet-projects {
|
|
background: radial-gradient(circle at 30% 30%, #45b7d1, #0984e3);
|
|
color: white;
|
|
}
|
|
|
|
.planet-contact {
|
|
background: radial-gradient(circle at 30% 30%, #f39c12, #e17055);
|
|
color: white;
|
|
}
|
|
|
|
.planet-blog {
|
|
background: radial-gradient(circle at 30% 30%, #a29bfe, #6c5ce7);
|
|
color: white;
|
|
}
|
|
|
|
.gravitational-field {
|
|
position: absolute;
|
|
border-radius: 50%;
|
|
border: 2px solid rgba(255, 255, 255, 0.1);
|
|
pointer-events: none;
|
|
opacity: 0;
|
|
transition: opacity 0.3s ease;
|
|
}
|
|
|
|
.content-panel {
|
|
margin-top: 30px;
|
|
padding: 30px;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
border-radius: 15px;
|
|
backdrop-filter: blur(10px);
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
min-height: 200px;
|
|
transition: all 0.5s ease;
|
|
}
|
|
|
|
.content-section {
|
|
display: none;
|
|
animation: fadeIn 0.5s ease;
|
|
}
|
|
|
|
.content-section.active {
|
|
display: block;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; transform: translateY(20px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
.navigation-hint {
|
|
text-align: center;
|
|
margin-top: 20px;
|
|
font-size: 14px;
|
|
color: rgba(255, 255, 255, 0.7);
|
|
font-style: italic;
|
|
}
|
|
|
|
.comparison-grid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 30px;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.traditional, .innovative {
|
|
padding: 20px;
|
|
border-radius: 10px;
|
|
border: 2px solid #ddd;
|
|
}
|
|
|
|
.traditional {
|
|
background: #f9f9f9;
|
|
}
|
|
|
|
.innovative {
|
|
background: #f0f0f8;
|
|
border-color: #6c5ce7;
|
|
}
|
|
|
|
.traditional-nav {
|
|
display: flex;
|
|
background: #e9ecef;
|
|
border-radius: 5px;
|
|
overflow: hidden;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.traditional-nav button {
|
|
flex: 1;
|
|
padding: 12px 16px;
|
|
border: none;
|
|
background: #e9ecef;
|
|
cursor: pointer;
|
|
transition: background 0.2s ease;
|
|
}
|
|
|
|
.traditional-nav button:hover {
|
|
background: #dee2e6;
|
|
}
|
|
|
|
.traditional-nav button.active {
|
|
background: #6c5ce7;
|
|
color: white;
|
|
}
|
|
|
|
.doc-section {
|
|
margin-bottom: 25px;
|
|
padding: 20px;
|
|
background: #f8f9fa;
|
|
border-radius: 8px;
|
|
border-left: 4px solid #6c5ce7;
|
|
}
|
|
|
|
.physics-controls {
|
|
position: absolute;
|
|
top: 20px;
|
|
right: 20px;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
padding: 15px;
|
|
border-radius: 10px;
|
|
backdrop-filter: blur(10px);
|
|
}
|
|
|
|
.physics-controls label {
|
|
display: block;
|
|
font-size: 12px;
|
|
margin-bottom: 5px;
|
|
color: rgba(255, 255, 255, 0.8);
|
|
}
|
|
|
|
.physics-controls input[type="range"] {
|
|
width: 80px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.comparison-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.innovation-meta {
|
|
flex-direction: column;
|
|
gap: 15px;
|
|
}
|
|
|
|
.gravitynav-container {
|
|
height: 300px;
|
|
}
|
|
|
|
.physics-controls {
|
|
position: relative;
|
|
top: 0;
|
|
right: 0;
|
|
margin-top: 20px;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<h1>UI Innovation: GravityNav - Physics-Based Navigation</h1>
|
|
<div class="innovation-meta">
|
|
<p><strong>Replaces:</strong> Traditional Tab/Menu Navigation</p>
|
|
<p><strong>Innovation:</strong> Celestial physics simulation for navigation</p>
|
|
</div>
|
|
</header>
|
|
|
|
<main>
|
|
<section class="demo-container">
|
|
<h2>Interactive Demo</h2>
|
|
<div class="innovation-component">
|
|
<div class="gravitynav-container" id="gravityContainer" role="navigation" aria-label="Physics-based navigation">
|
|
<div class="star-field" id="starField"></div>
|
|
|
|
<div class="nav-planet planet-home"
|
|
data-content="home"
|
|
tabindex="0"
|
|
role="button"
|
|
aria-label="Home navigation">
|
|
Home
|
|
</div>
|
|
|
|
<div class="nav-planet planet-about"
|
|
data-content="about"
|
|
tabindex="0"
|
|
role="button"
|
|
aria-label="About navigation">
|
|
About
|
|
</div>
|
|
|
|
<div class="nav-planet planet-projects"
|
|
data-content="projects"
|
|
tabindex="0"
|
|
role="button"
|
|
aria-label="Projects navigation">
|
|
Projects
|
|
</div>
|
|
|
|
<div class="nav-planet planet-contact"
|
|
data-content="contact"
|
|
tabindex="0"
|
|
role="button"
|
|
aria-label="Contact navigation">
|
|
Contact
|
|
</div>
|
|
|
|
<div class="nav-planet planet-blog"
|
|
data-content="blog"
|
|
tabindex="0"
|
|
role="button"
|
|
aria-label="Blog navigation">
|
|
Blog
|
|
</div>
|
|
|
|
<div class="physics-controls" id="physicsControls">
|
|
<label for="gravitySlider">Gravity:</label>
|
|
<input type="range" id="gravitySlider" min="0.1" max="2" step="0.1" value="1">
|
|
|
|
<label for="dampingSlider">Damping:</label>
|
|
<input type="range" id="dampingSlider" min="0.8" max="0.99" step="0.01" value="0.95">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="content-panel" id="contentPanel" aria-live="polite">
|
|
<div class="content-section active" data-content="home">
|
|
<h3>🏠 Welcome Home</h3>
|
|
<p>This is the home page content. The GravityNav system allows you to navigate through different sections using physics-based interactions. Click on any planet to see gravitational effects in action!</p>
|
|
</div>
|
|
|
|
<div class="content-section" data-content="about">
|
|
<h3>👤 About</h3>
|
|
<p>Learn about the innovative navigation paradigm. Each navigation element behaves like a celestial body with its own gravitational field. Mouse interactions create attractive forces that pull planets toward your cursor.</p>
|
|
</div>
|
|
|
|
<div class="content-section" data-content="projects">
|
|
<h3>🚀 Projects</h3>
|
|
<p>Explore various projects and implementations. The physics simulation runs at 60fps and responds to real-time user interactions. Each planet maintains momentum and responds to gravitational influences.</p>
|
|
</div>
|
|
|
|
<div class="content-section" data-content="contact">
|
|
<h3>📬 Contact</h3>
|
|
<p>Get in touch through various channels. The system maintains accessibility through keyboard navigation while providing an engaging visual experience that transforms traditional navigation paradigms.</p>
|
|
</div>
|
|
|
|
<div class="content-section" data-content="blog">
|
|
<h3>📝 Blog</h3>
|
|
<p>Read latest articles and insights. The adaptive physics system responds to user preferences, allowing customization of gravitational strength and system damping for different interaction styles.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="navigation-hint">
|
|
Move your mouse around to create gravitational fields! Click planets to navigate. Use keyboard (Tab/Enter) for accessibility.
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="comparison">
|
|
<h2>Traditional vs Innovation</h2>
|
|
<div class="comparison-grid">
|
|
<div class="traditional">
|
|
<h3>Traditional Tab Navigation</h3>
|
|
<p>Standard horizontal or vertical tab layout with static positioning.</p>
|
|
<div class="traditional-nav">
|
|
<button class="active">Home</button>
|
|
<button>About</button>
|
|
<button>Projects</button>
|
|
<button>Contact</button>
|
|
<button>Blog</button>
|
|
</div>
|
|
<p style="margin-top: 15px; font-size: 14px; color: #666;">
|
|
✓ Predictable layout<br>
|
|
✓ Fast recognition<br>
|
|
✗ Static visual feedback<br>
|
|
✗ Limited engagement<br>
|
|
✗ No spatial relationships
|
|
</p>
|
|
</div>
|
|
<div class="innovative">
|
|
<h3>GravityNav System</h3>
|
|
<p>Physics-based navigation with gravitational interactions and celestial metaphors.</p>
|
|
<p style="margin-top: 15px; font-size: 14px; color: #2d2d5a;">
|
|
✓ Engaging physics simulation<br>
|
|
✓ Natural spatial relationships<br>
|
|
✓ Real-time visual feedback<br>
|
|
✓ Memorable interaction model<br>
|
|
✓ Customizable behavior<br>
|
|
✓ Full accessibility support
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="documentation">
|
|
<h2>Design Documentation</h2>
|
|
<div class="doc-section">
|
|
<h3>Interaction Model</h3>
|
|
<p>Users interact through mouse movement creating gravitational fields that attract navigation planets. Clicking selects a navigation item and triggers content updates. Planets respond with realistic physics including momentum, attraction, and damping. Keyboard navigation maintains traditional accessibility patterns.</p>
|
|
</div>
|
|
<div class="doc-section">
|
|
<h3>Technical Implementation</h3>
|
|
<p>Built using requestAnimationFrame for 60fps physics simulation. Vector mathematics calculate gravitational forces between mouse position and planets. CSS transforms provide smooth hardware-accelerated animations. Physics controls allow real-time parameter adjustment for gravity strength and system damping.</p>
|
|
</div>
|
|
<div class="doc-section">
|
|
<h3>Accessibility Features</h3>
|
|
<p>Maintains full keyboard navigation with Tab cycling and Enter activation. ARIA labels and roles ensure screen reader compatibility. Content changes are announced via aria-live regions. Focus indicators provide clear visual feedback. All physics interactions have keyboard equivalents.</p>
|
|
</div>
|
|
<div class="doc-section">
|
|
<h3>Evolution Opportunities</h3>
|
|
<p>Future enhancements could include orbital mechanics for sub-navigation, collision detection between planets, 3D space navigation, voice-controlled gravitational fields, collaborative navigation where multiple users influence the same space, and adaptive AI that learns user navigation patterns.</p>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<script>
|
|
class GravityNav {
|
|
constructor(container) {
|
|
this.container = container;
|
|
this.planets = Array.from(container.querySelectorAll('.nav-planet'));
|
|
this.starField = container.querySelector('#starField');
|
|
this.contentPanel = container.querySelector('#contentPanel');
|
|
this.gravitySlider = container.querySelector('#gravitySlider');
|
|
this.dampingSlider = container.querySelector('#dampingSlider');
|
|
|
|
this.mouse = { x: 0, y: 0 };
|
|
this.gravity = 1;
|
|
this.damping = 0.95;
|
|
this.animationId = null;
|
|
|
|
this.planetData = this.planets.map(planet => ({
|
|
element: planet,
|
|
x: 0, y: 0,
|
|
vx: 0, vy: 0,
|
|
mass: 50,
|
|
radius: 40,
|
|
restX: 0, restY: 0,
|
|
active: false
|
|
}));
|
|
|
|
this.initializePositions();
|
|
this.createStarField();
|
|
this.initializeEvents();
|
|
this.startPhysicsLoop();
|
|
this.setActiveContent('home');
|
|
}
|
|
|
|
initializePositions() {
|
|
const containerRect = this.container.getBoundingClientRect();
|
|
const centerX = containerRect.width / 2;
|
|
const centerY = containerRect.height / 2;
|
|
const radius = Math.min(containerRect.width, containerRect.height) * 0.3;
|
|
|
|
this.planetData.forEach((planet, index) => {
|
|
const angle = (index / this.planetData.length) * Math.PI * 2;
|
|
const x = centerX + Math.cos(angle) * radius;
|
|
const y = centerY + Math.sin(angle) * radius;
|
|
|
|
planet.x = planet.restX = x;
|
|
planet.y = planet.restY = y;
|
|
planet.radius = 30 + Math.random() * 20;
|
|
|
|
this.updatePlanetPosition(planet);
|
|
});
|
|
}
|
|
|
|
createStarField() {
|
|
const starCount = 50;
|
|
for (let i = 0; i < starCount; i++) {
|
|
const star = document.createElement('div');
|
|
star.className = 'star';
|
|
|
|
const size = Math.random() * 2 + 1;
|
|
star.style.width = size + 'px';
|
|
star.style.height = size + 'px';
|
|
star.style.left = Math.random() * 100 + '%';
|
|
star.style.top = Math.random() * 100 + '%';
|
|
star.style.animationDelay = Math.random() * 3 + 's';
|
|
|
|
this.starField.appendChild(star);
|
|
}
|
|
}
|
|
|
|
initializeEvents() {
|
|
// Mouse tracking
|
|
this.container.addEventListener('mousemove', (e) => {
|
|
const rect = this.container.getBoundingClientRect();
|
|
this.mouse.x = e.clientX - rect.left;
|
|
this.mouse.y = e.clientY - rect.top;
|
|
});
|
|
|
|
this.container.addEventListener('mouseleave', () => {
|
|
this.mouse.x = -1000;
|
|
this.mouse.y = -1000;
|
|
});
|
|
|
|
// Planet interactions
|
|
this.planets.forEach(planet => {
|
|
planet.addEventListener('click', () => this.selectPlanet(planet));
|
|
planet.addEventListener('keydown', (e) => {
|
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
e.preventDefault();
|
|
this.selectPlanet(planet);
|
|
}
|
|
});
|
|
});
|
|
|
|
// Physics controls
|
|
this.gravitySlider.addEventListener('input', (e) => {
|
|
this.gravity = parseFloat(e.target.value);
|
|
});
|
|
|
|
this.dampingSlider.addEventListener('input', (e) => {
|
|
this.damping = parseFloat(e.target.value);
|
|
});
|
|
|
|
// Window resize
|
|
window.addEventListener('resize', () => {
|
|
this.initializePositions();
|
|
});
|
|
}
|
|
|
|
selectPlanet(planetElement) {
|
|
const contentType = planetElement.dataset.content;
|
|
this.setActiveContent(contentType);
|
|
|
|
// Update planet states
|
|
this.planets.forEach(p => p.classList.remove('active'));
|
|
planetElement.classList.add('active');
|
|
|
|
// Update planet data
|
|
this.planetData.forEach(planet => {
|
|
planet.active = planet.element === planetElement;
|
|
if (planet.active) {
|
|
planet.mass = 80;
|
|
planet.radius = 50;
|
|
} else {
|
|
planet.mass = 50;
|
|
planet.radius = 30 + Math.random() * 20;
|
|
}
|
|
});
|
|
}
|
|
|
|
setActiveContent(contentType) {
|
|
const contentSections = this.contentPanel.querySelectorAll('.content-section');
|
|
contentSections.forEach(section => {
|
|
section.classList.remove('active');
|
|
if (section.dataset.content === contentType) {
|
|
section.classList.add('active');
|
|
}
|
|
});
|
|
}
|
|
|
|
updatePhysics() {
|
|
this.planetData.forEach(planet => {
|
|
// Calculate gravitational force from mouse
|
|
const dx = this.mouse.x - planet.x;
|
|
const dy = this.mouse.y - planet.y;
|
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
|
|
if (distance > 0 && distance < 200) {
|
|
const force = (this.gravity * planet.mass) / (distance * distance);
|
|
const fx = (dx / distance) * force;
|
|
const fy = (dy / distance) * force;
|
|
|
|
planet.vx += fx * 0.01;
|
|
planet.vy += fy * 0.01;
|
|
}
|
|
|
|
// Spring force back to rest position
|
|
const restDx = planet.restX - planet.x;
|
|
const restDy = planet.restY - planet.y;
|
|
const springForce = 0.02;
|
|
|
|
planet.vx += restDx * springForce;
|
|
planet.vy += restDy * springForce;
|
|
|
|
// Apply damping
|
|
planet.vx *= this.damping;
|
|
planet.vy *= this.damping;
|
|
|
|
// Update position
|
|
planet.x += planet.vx;
|
|
planet.y += planet.vy;
|
|
|
|
// Planet-to-planet interactions
|
|
this.planetData.forEach(other => {
|
|
if (other !== planet) {
|
|
const pdx = other.x - planet.x;
|
|
const pdy = other.y - planet.y;
|
|
const pdist = Math.sqrt(pdx * pdx + pdy * pdy);
|
|
|
|
if (pdist > 0 && pdist < 100) {
|
|
const repulsion = 50 / (pdist * pdist);
|
|
planet.vx -= (pdx / pdist) * repulsion * 0.001;
|
|
planet.vy -= (pdy / pdist) * repulsion * 0.001;
|
|
}
|
|
}
|
|
});
|
|
|
|
this.updatePlanetPosition(planet);
|
|
});
|
|
}
|
|
|
|
updatePlanetPosition(planet) {
|
|
const element = planet.element;
|
|
const size = planet.radius;
|
|
|
|
element.style.width = size + 'px';
|
|
element.style.height = size + 'px';
|
|
element.style.left = (planet.x - size/2) + 'px';
|
|
element.style.top = (planet.y - size/2) + 'px';
|
|
element.style.fontSize = (size * 0.25) + 'px';
|
|
|
|
if (planet.active) {
|
|
element.style.transform = 'scale(1.2)';
|
|
} else {
|
|
element.style.transform = 'scale(1)';
|
|
}
|
|
}
|
|
|
|
startPhysicsLoop() {
|
|
const animate = () => {
|
|
this.updatePhysics();
|
|
this.animationId = requestAnimationFrame(animate);
|
|
};
|
|
animate();
|
|
}
|
|
|
|
destroy() {
|
|
if (this.animationId) {
|
|
cancelAnimationFrame(this.animationId);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize GravityNav when page loads
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const container = document.querySelector('#gravityContainer');
|
|
const gravityNav = new GravityNav(container);
|
|
|
|
// Make it available globally
|
|
window.gravityNav = gravityNav;
|
|
|
|
// Traditional nav demo functionality
|
|
const traditionalButtons = document.querySelectorAll('.traditional-nav button');
|
|
traditionalButtons.forEach((button, index) => {
|
|
button.addEventListener('click', () => {
|
|
traditionalButtons.forEach(b => b.classList.remove('active'));
|
|
button.classList.add('active');
|
|
});
|
|
});
|
|
|
|
console.log('GravityNav initialized. Move your mouse around the navigation area!');
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |