ar-project / index.html
Ffury's picture
Build a web-based AR navigation app using 8th Wall. Users open a link on their phone, scan their space (home, store, etc.), and select a destination (like “Kitchen”). The app uses markerless AR to detect surfaces and track movement, then overlays real-time AR arrows or paths to guide users to their chosen spot. Features: simple UI for destination selection, live AR navigation, no markers or app download needed, and responsive mobile design. Use JavaScript (optionally with Three.js or A-Frame). Store room points locally. Optional: save/load layouts, add voice/text directions, and usage analytics. End result: a shareable link for instant, intuitive indoor AR navigation. - Follow Up Deployment
1574181 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Indoor AR Navigator</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.8thwall.com/web/xr/xr8.js"></script>
<script src="https://cdn.8thwall.com/web/xr/threejs/xr8.threejs.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
body {
font-family: 'Poppins', sans-serif;
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
overflow: hidden;
height: 100vh;
color: #f1f5f9;
}
.overlay {
position: absolute;
z-index: 10;
pointer-events: none;
}
.interactive {
pointer-events: auto;
}
.ar-view {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.pulse {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { transform: scale(1); opacity: 0.7; }
50% { transform: scale(1.05); opacity: 1; }
100% { transform: scale(1); opacity: 0.7; }
}
.slide-in {
animation: slideIn 0.3s forwards;
}
@keyframes slideIn {
from { transform: translateY(100%); }
to { transform: translateY(0); }
}
.slide-out {
animation: slideOut 0.3s forwards;
}
@keyframes slideOut {
from { transform: translateY(0); }
to { transform: translateY(100%); }
}
.fade-in {
animation: fadeIn 0.5s forwards;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.room-card {
transition: all 0.3s ease;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
border: 1px solid rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
background: rgba(15, 23, 42, 0.6);
}
.room-card:hover {
transform: translateY(-5px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.1);
border-color: rgba(99, 102, 241, 0.5);
}
.icon-container {
transition: all 0.3s ease;
}
.room-card:hover .icon-container {
transform: scale(1.1);
box-shadow: 0 0 20px rgba(99, 102, 241, 0.3);
}
.progress-bar {
height: 6px;
border-radius: 3px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #6366f1, #8b5cf6);
transition: width 0.5s ease;
}
.glow {
box-shadow: 0 0 15px rgba(99, 102, 241, 0.5);
}
.nav-step {
position: relative;
padding-left: 2rem;
}
.nav-step:before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #6366f1;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 0.75rem;
font-weight: bold;
}
.nav-step-1:before { content: '1'; }
.nav-step-2:before { content: '2'; }
.nav-step-3:before { content: '3'; }
.nav-step.active:before {
background-color: #10b981;
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.3);
}
.nav-step.completed:before {
background-color: #8b5cf6;
}
.nav-step.completed:after {
content: '✓';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 0.75rem;
font-weight: bold;
z-index: 2;
}
.nav-step-line {
position: absolute;
left: 10px;
top: 50%;
height: 100%;
width: 2px;
background-color: #334155;
transform: translateY(-50%);
}
.nav-step:last-child .nav-step-line {
display: none;
}
.ar-marker {
position: absolute;
width: 30px;
height: 30px;
border-radius: 50%;
background: radial-gradient(circle, #6366f1 0%, #4f46e5 70%, transparent 100%);
box-shadow: 0 0 15px rgba(99, 102, 241, 0.7);
animation: markerPulse 1.5s infinite;
}
@keyframes markerPulse {
0% { transform: scale(1); opacity: 0.8; }
50% { transform: scale(1.2); opacity: 1; }
100% { transform: scale(1); opacity: 0.8; }
}
.dashboard-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
.nav-path {
position: relative;
height: 4px;
background: rgba(255, 255, 255, 0.1);
border-radius: 2px;
overflow: hidden;
}
.nav-path-fill {
position: absolute;
height: 100%;
background: linear-gradient(90deg, #6366f1, #8b5cf6);
width: 65%;
}
.nav-path-dot {
position: absolute;
width: 12px;
height: 12px;
border-radius: 50%;
background: #8b5cf6;
top: 50%;
transform: translateY(-50%);
box-shadow: 0 0 10px rgba(139, 92, 246, 0.7);
}
.nav-path-dot.start { left: 0; }
.nav-path-dot.end { right: 0; }
.nav-path-dot.current { left: 65%; }
.glass-panel {
background: rgba(15, 23, 42, 0.7);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
}
.ar-controls {
position: absolute;
bottom: 100px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 20px;
z-index: 20;
}
.ar-control-btn {
width: 60px;
height: 60px;
border-radius: 50%;
background: rgba(15, 23, 42, 0.7);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 1.5rem;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
transition: all 0.2s ease;
}
.ar-control-btn:hover {
transform: scale(1.1);
background: rgba(30, 41, 59, 0.8);
box-shadow: 0 0 20px rgba(99, 102, 241, 0.5);
}
.notification-badge {
position: absolute;
top: -5px;
right: -5px;
width: 20px;
height: 20px;
border-radius: 50%;
background: #ef4444;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.7rem;
font-weight: bold;
}
.ar-marker-label {
position: absolute;
background: rgba(15, 23, 42, 0.8);
padding: 6px 12px;
border-radius: 20px;
font-size: 0.8rem;
white-space: nowrap;
transform: translateX(-50%);
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.scanning-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(15, 23, 42, 0.9);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 30;
}
.scanning-animation {
width: 200px;
height: 200px;
border-radius: 50%;
border: 4px solid transparent;
border-top-color: #6366f1;
animation: scanningSpin 2s linear infinite;
position: relative;
}
.scanning-animation:before {
content: '';
position: absolute;
top: 10px;
left: 10px;
right: 10px;
bottom: 10px;
border-radius: 50%;
border: 4px solid transparent;
border-top-color: #8b5cf6;
animation: scanningSpin 1.5s linear infinite reverse;
}
@keyframes scanningSpin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.ar-object {
position: absolute;
width: 50px;
height: 50px;
background: rgba(99, 102, 241, 0.3);
border: 2px solid #6366f1;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
color: white;
box-shadow: 0 0 20px rgba(99, 102, 241, 0.5);
animation: objectFloat 3s ease-in-out infinite;
}
@keyframes objectFloat {
0% { transform: translateY(0); }
50% { transform: translateY(-10px); }
100% { transform: translateY(0); }
}
</style>
</head>
<body class="relative">
<!-- Top Navigation Bar -->
<header class="w-full py-4 px-6 flex justify-between items-center z-20 relative">
<div class="flex items-center">
<div class="w-10 h-10 rounded-full bg-indigo-600 flex items-center justify-center mr-3">
<i class="fas fa-map-marker-alt text-white"></i>
</div>
<h1 class="text-2xl font-bold bg-gradient-to-r from-indigo-400 to-purple-500 bg-clip-text text-transparent">IndoorAR Navigator</h1>
</div>
<div class="flex items-center space-x-4">
<button class="relative">
<i class="fas fa-bell text-xl text-indigo-300"></i>
<span class="notification-badge">3</span>
</button>
<div class="flex items-center">
<div class="w-10 h-10 rounded-full bg-gradient-to-r from-indigo-500 to-purple-600 flex items-center justify-center mr-2">
<span class="text-white font-semibold">JS</span>
</div>
<span class="font-medium">John Smith</span>
</div>
</div>
</header>
<!-- Main Content Area -->
<main class="container mx-auto px-4 py-6 relative z-10">
<!-- Dashboard View -->
<div id="dashboardView">
<div class="flex justify-between items-center mb-8">
<div>
<h2 class="text-3xl font-bold mb-2">Welcome to TechHub Office</h2>
<p class="text-indigo-300">Navigate to any room with augmented reality</p>
</div>
<div class="relative">
<div class="flex items-center bg-slate-800 rounded-full px-4 py-2">
<i class="fas fa-search text-indigo-400 mr-2"></i>
<input type="text" placeholder="Search rooms..." class="bg-transparent outline-none text-white placeholder-indigo-300">
</div>
</div>
</div>
<div class="glass-panel p-6 mb-8">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-semibold">Navigation Progress</h3>
<span class="text-indigo-400">65% complete</span>
</div>
<div class="nav-path mb-6">
<div class="nav-path-fill"></div>
<div class="nav-path-dot start"></div>
<div class="nav-path-dot current"></div>
<div class="nav-path-dot end"></div>
</div>
<div class="grid grid-cols-3 gap-4">
<div class="text-center">
<p class="text-sm text-slate-400">Start Point</p>
<p class="font-semibold">Reception</p>
</div>
<div class="text-center">
<p class="text-sm text-slate-400">Current Location</p>
<p class="font-semibold">Hallway B</p>
</div>
<div class="text-center">
<p class="text-sm text-slate-400">Destination</p>
<p class="font-semibold">Conference Room</p>
</div>
</div>
</div>
<h3 class="text-xl font-semibold mb-4">Available Rooms</h3>
<div class="dashboard-grid">
<!-- Room Card 1 -->
<div class="room-card rounded-2xl p-5 cursor-pointer">
<div class="flex items-start">
<div class="icon-container w-14 h-14 rounded-xl bg-gradient-to-br from-indigo-600 to-purple-600 flex items-center justify-center mr-4">
<i class="fas fa-users text-white text-xl"></i>
</div>
<div>
<h4 class="font-bold text-lg">Conference Room</h4>
<p class="text-slate-400 text-sm">Capacity: 12 people</p>
<div class="flex items-center mt-2">
<i class="fas fa-location-arrow text-indigo-400 mr-2"></i>
<span class="text-sm">120m • Floor 2</span>
</div>
</div>
</div>
<div class="mt-4 flex justify-end">
<button class="bg-gradient-to-r from-indigo-500 to-purple-500 text-white px-4 py-2 rounded-full text-sm font-medium hover:opacity-90 transition">Navigate</button>
</div>
</div>
<!-- Room Card 2 -->
<div class="room-card rounded-2xl p-5 cursor-pointer">
<div class="flex items-start">
<div class="icon-container w-14 h-14 rounded-xl bg-gradient-to-br from-cyan-600 to-blue-600 flex items-center justify-center mr-4">
<i class="fas fa-laptop-code text-white text-xl"></i>
</div>
<div>
<h4 class="font-bold text-lg">Developer Zone</h4>
<p class="text-slate-400 text-sm">Quiet workspace</p>
<div class="flex items-center mt-2">
<i class="fas fa-location-arrow text-indigo-400 mr-2"></i>
<span class="text-sm">85m • Floor 1</span>
</div>
</div>
</div>
<div class="mt-4 flex justify-end">
<button class="bg-gradient-to-r from-indigo-500 to-purple-500 text-white px-4 py-2 rounded-full text-sm font-medium hover:opacity-90 transition">Navigate</button>
</div>
</div>
<!-- Room Card 3 -->
<div class="room-card rounded-2xl p-5 cursor-pointer">
<div class="flex items-start">
<div class="icon-container w-14 h-14 rounded-xl bg-gradient-to-br from-green-600 to-emerald-600 flex items-center justify-center mr-4">
<i class="fas fa-utensils text-white text-xl"></i>
</div>
<div>
<h4 class="font-bold text-lg">Cafeteria</h4>
<p class="text-slate-400 text-sm">Open until 6 PM</p>
<div class="flex items-center mt-2">
<i class="fas fa-location-arrow text-indigo-400 mr-2"></i>
<span class="text-sm">45m • Floor 1</span>
</div>
</div>
</div>
<div class="mt-4 flex justify-end">
<button class="bg-gradient-to-r from-indigo-500 to-purple-500 text-white px-4 py-2 rounded-full text-sm font-medium hover:opacity-90 transition">Navigate</button>
</div>
</div>
<!-- Room Card 4 -->
<div class="room-card rounded-2xl p-5 cursor-pointer">
<div class="flex items-start">
<div class="icon-container w-14 h-14 rounded-xl bg-gradient-to-br from-amber-600 to-orange-600 flex items-center justify-center mr-4">
<i class="fas fa-dumbbell text-white text-xl"></i>
</div>
<div>
<h4 class="font-bold text-lg">Fitness Center</h4>
<p class="text-slate-400 text-sm">Open 24/7</p>
<div class="flex items-center mt-2">
<i class="fas fa-location-arrow text-indigo-400 mr-2"></i>
<span class="text-sm">200m • Floor 3</span>
</div>
</div>
</div>
<div class="mt-4 flex justify-end">
<button class="bg-gradient-to-r from-indigo-500 to-purple-500 text-white px-4 py-2 rounded-full text-sm font-medium hover:opacity-90 transition">Navigate</button>
</div>
</div>
</div>
</div>
<!-- AR View (initially hidden) -->
<div id="arView" class="hidden">
<div class="ar-view" id="arScene">
<!-- AR content will be rendered here by Three.js -->
<!-- Example AR markers -->
<div class="ar-marker" style="top: 40%; left: 30%;"></div>
<div class="ar-marker" style="top: 60%; left: 50%;"></div>
<div class="ar-marker" style="top: 35%; left: 70%;"></div>
<!-- Destination marker -->
<div class="ar-marker" style="top: 50%; left: 65%; background: radial-gradient(circle, #10b981 0%, #059669 70%, transparent 100%); box-shadow: 0 0 15px rgba(16, 185, 129, 0.7);">
<div class="ar-marker-label" style="top: -30px; left: 50%;">Conference Room</div>
</div>
<!-- AR objects -->
<div class="ar-object" style="top: 20%; left: 20%;">
<i class="fas fa-door-open"></i>
</div>
<div class="ar-object" style="top: 70%; left: 40%;">
<i class="fas fa-elevator"></i>
</div>
</div>
<!-- AR Controls -->
<div class="ar-controls">
<button class="ar-control-btn">
<i class="fas fa-expand"></i>
</button>
<button class="ar-control-btn bg-gradient-to-r from-indigo-500 to-purple-500">
<i class="fas fa-location-arrow"></i>
</button>
<button class="ar-control-btn">
<i class="fas fa-cog"></i>
</button>
</div>
<!-- Navigation Panel -->
<div class="glass-panel absolute bottom-6 left-6 right-6 p-5">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold">Navigation to Conference Room</h3>
<div class="flex items-center">
<span class="text-indigo-400 mr-2">120m</span>
<div class="w-3 h-3 rounded-full bg-green-500 animate-pulse"></div>
</div>
</div>
<div class="mb-4">
<div class="flex items-center mb-2">
<i class="fas fa-arrow-right text-indigo-400 mr-2"></i>
<span>Continue straight for 50m</span>
</div>
<div class="flex items-center mb-2">
<i class="fas fa-stairs text-indigo-400 mr-2"></i>
<span>Take stairs to floor 2</span>
</div>
<div class="flex items-center">
<i class="fas fa-door-open text-indigo-400 mr-2"></i>
<span>Turn right at meeting room</span>
</div>
</div>
<div class="flex justify-between">
<button class="px-4 py-2 rounded-lg bg-slate-700 hover:bg-slate-600 transition">Cancel Navigation</button>
<button class="px-4 py-2 rounded-lg bg-gradient-to-r from-indigo-500 to-purple-500 hover:opacity-90 transition">End Navigation</button>
</div>
</div>
</div>
</main>
<!-- Bottom Navigation -->
<nav class="fixed bottom-0 left-0 right-0 bg-slate-800 border-t border-slate-700 z-20">
<div class="flex justify-around py-3">
<button class="flex flex-col items-center text-indigo-400">
<i class="fas fa-home text-xl mb-1"></i>
<span class="text-xs">Home</span>
</button>
<button class="flex flex-col items-center text-indigo-400">
<i class="fas fa-map-marked-alt text-xl mb-1"></i>
<span class="text-xs">Map</span>
</button>
<button id="arToggle" class="flex flex-col items-center text-white">
<div class="w-14 h-14 rounded-full bg-gradient-to-r from-indigo-500 to-purple-500 flex items-center justify-center -mt-8 mb-1 shadow-lg">
<i class="fas fa-camera text-xl"></i>
</div>
<span class="text-xs">AR Mode</span>
</button>
<button class="flex flex-col items-center text-indigo-400">
<i class="fas fa-history text-xl mb-1"></i>
<span class="text-xs">History</span>
</button>
<button class="flex flex-col items-center text-indigo-400">
<i class="fas fa-cog text-xl mb-1"></i>
<span class="text-xs">Settings</span>
</button>
</div>
</nav>
<!-- Scanning Overlay -->
<div id="scanningOverlay" class="scanning-overlay hidden">
<div class="scanning-animation mb-8"></div>
<h2 class="text-2xl font-bold mb-2">Scanning Environment</h2>
<p class="text-slate-400 mb-6">Slowly move your device around to detect surfaces</p>
<button id="cancelScan" class="px-6 py-3 rounded-full bg-slate-700 hover:bg-slate-600 transition">Cancel</button>
</div>
<script>
// Toggle between dashboard and AR view
const arToggle = document.getElementById('arToggle');
const dashboardView = document.getElementById('dashboardView');
const arView = document.getElementById('arView');
const scanningOverlay = document.getElementById('scanningOverlay');
arToggle.addEventListener('click', () => {
dashboardView.classList.add('hidden');
arView.classList.remove('hidden');
scanningOverlay.classList.remove('hidden');
// Simulate scanning completion after 3 seconds
setTimeout(() => {
scanningOverlay.classList.add('hidden');
}, 3000);
});
// Cancel scanning
document.getElementById('cancelScan').addEventListener('click', () => {
scanningOverlay.classList.add('hidden');
dashboardView.classList.remove('hidden');
arView.classList.add('hidden');
});
// Simulate room navigation
document.querySelectorAll('.room-card button').forEach(button => {
button.addEventListener('click', () => {
dashboardView.classList.add('hidden');
arView.classList.remove('hidden');
scanningOverlay.classList.remove('hidden');
// Simulate scanning completion after 3 seconds
setTimeout(() => {
scanningOverlay.classList.add('hidden');
}, 3000);
});
});
// Simulate AR initialization
window.addEventListener('load', () => {
// This would normally initialize the AR scene
console.log('AR components loaded');
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Ffury/ar-project" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>