Spaces:
Running
Running
File size: 13,526 Bytes
7b46bf4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8" />
<!-- Viewport ottimizzato per mobile: blocco totale dello zoom e gestione notch -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
<title>AR Neural Link | Vertical Native</title>
<!-- Tailwind & Fonts -->
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&display=swap" rel="stylesheet">
<!-- AR Libraries -->
<script src="https://aframe.io/releases/1.4.2/aframe.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/mind-ar@1.2.2/dist/mindar-image.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/mind-ar@1.2.2/dist/mindar-image-aframe.prod.js"></script>
<style>
:root {
--neon-green: #00ff41;
--dark-bg: #050505;
--error-red: #ff0055;
}
/* Reset totale per comportamento "App Nativa" */
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background-color: transparent !important; /* Importante per vedere la camera */
font-family: 'Fira Code', monospace;
overflow: hidden; /* Blocca scroll elastico su iOS */
position: fixed; /* Blocca il body in posizione */
}
/* --- ENGINE GRAFICO (Camera e Canvas) --- */
/* 1. Video Webcam: Forziamo il riempimento verticale */
video {
position: absolute !important;
top: 0; left: 0; right: 0; bottom: 0;
width: 100% !important;
height: 100% !important;
object-fit: cover !important; /* Questo è il segreto per il full screen 9:16 */
z-index: -2 !important;
}
/* 2. Canvas AR: Sovrapposto perfettamente */
.a-canvas {
width: 100% !important;
height: 100% !important;
position: absolute !important;
top: 0; left: 0;
z-index: -1 !important;
}
/* FX: Scanlines (Ottimizzate per mobile) */
.scanlines {
background: linear-gradient(to bottom, rgba(255,255,255,0), rgba(255,255,255,0) 50%, rgba(0,0,0,0.2) 50%, rgba(0,0,0,0.2));
background-size: 100% 4px;
position: fixed; inset: 0; pointer-events: none;
z-index: 10;
opacity: 0.4;
}
/* UI Elements */
.tech-border {
border: 1px solid var(--neon-green);
box-shadow: 0 0 15px rgba(0, 255, 65, 0.15);
background: rgba(0,0,0,0.85);
backdrop-filter: blur(8px);
}
.a-enter-vr-button { display: none !important; }
/* --- LOADER STYLE --- */
#custom-loader {
position: fixed; inset: 0; z-index: 9999;
background: #000;
display: flex; flex-direction: column; align-items: center; justify-content: center;
transition: opacity 0.5s ease-out;
padding: 20px;
}
.glitch-text { animation: glitch 2s infinite; }
@keyframes glitch {
0% { transform: translate(0); }
20% { transform: translate(-2px, 2px); }
40% { transform: translate(-2px, -2px); }
60% { transform: translate(2px, 2px); }
80% { transform: translate(2px, -2px); }
100% { transform: translate(0); }
}
.loader-track {
width: 100%; max-width: 280px; height: 6px;
background: #111; margin-top: 20px;
overflow: hidden; border-radius: 4px;
}
.loader-fill {
height: 100%; background: var(--neon-green); width: 0%;
transition: width 0.3s;
box-shadow: 0 0 10px var(--neon-green);
}
/* Safe area per iPhone nuovi */
.safe-area-y {
padding-top: env(safe-area-inset-top, 20px);
padding-bottom: env(safe-area-inset-bottom, 20px);
}
</style>
</head>
<body>
<!-- 1. LOADER -->
<div id="custom-loader">
<div class="text-[#00ff41] text-5xl font-black tracking-tighter glitch-text mb-4">
LINK<br>START
</div>
<div class="text-white/50 text-xs font-mono uppercase tracking-[0.2em] mb-2">Initializing AR Core...</div>
<div class="loader-track"><div class="loader-fill" id="progress-bar"></div></div>
<div id="loading-percent" class="text-[#00ff41] font-mono text-xl mt-2 font-bold">0%</div>
</div>
<!-- 2. FX -->
<div class="scanlines"></div>
<!-- 3. UI LAYER (Vertical Native) -->
<div id="ui-layer" class="fixed inset-0 z-[50] flex flex-col justify-between safe-area-y pointer-events-none">
<!-- TOP HEADER -->
<div class="w-full px-6 py-4 flex justify-between items-center bg-gradient-to-b from-black/80 to-transparent pointer-events-auto">
<div class="flex flex-col">
<span class="text-[10px] text-white/60 font-mono tracking-widest">SYSTEM</span>
<span id="sys-status" class="text-[#00ff41] font-bold text-lg tracking-wider animate-pulse">SCANNING</span>
</div>
<a href="./index.html" class="w-10 h-10 flex items-center justify-center border border-[#00ff41]/50 rounded-full bg-black/40 backdrop-blur-md active:scale-95 transition-transform">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#00ff41" stroke-width="2"><path d="M18 6L6 18M6 6l12 12"/></svg>
</a>
</div>
<!-- MIRINO (Adattato per Verticale) -->
<div id="aim-overlay" class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex flex-col items-center justify-center transition-opacity duration-300">
<!-- Frame Rettangolare Verticale (9:16 approx) -->
<div class="relative w-[65vw] h-[100vw] max-w-[300px] max-h-[500px] border border-white/20 rounded-xl">
<!-- Angoli Tech -->
<div class="absolute -top-1 -left-1 w-6 h-6 border-t-4 border-l-4 border-[#00ff41]"></div>
<div class="absolute -top-1 -right-1 w-6 h-6 border-t-4 border-r-4 border-[#00ff41]"></div>
<div class="absolute -bottom-1 -left-1 w-6 h-6 border-b-4 border-l-4 border-[#00ff41]"></div>
<div class="absolute -bottom-1 -right-1 w-6 h-6 border-b-4 border-r-4 border-[#00ff41]"></div>
<!-- Mirino centrale -->
<div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-full flex items-center justify-center">
<div class="w-12 h-[1px] bg-[#00ff41]/50"></div>
<div class="h-12 w-[1px] bg-[#00ff41]/50 absolute"></div>
</div>
</div>
<div class="mt-4 bg-black/60 backdrop-blur px-4 py-2 rounded border border-[#00ff41]/30">
<p class="text-[#00ff41] text-xs font-bold tracking-widest uppercase">Inquadra il Marker</p>
</div>
</div>
<!-- BOTTOM CONTROLS -->
<div class="w-full px-6 pb-8 pointer-events-auto flex flex-col items-center bg-gradient-to-t from-black/90 to-transparent">
<!-- Pulsante Audio Enorme (Pollice friendly) -->
<button id="audio-btn" class="w-full max-w-sm py-5 bg-[#00ff41]/10 border border-[#00ff41] text-[#00ff41] font-bold text-lg uppercase tracking-[0.2em] rounded active:bg-[#00ff41] active:text-black transition-all mb-4 flex items-center justify-center gap-3 backdrop-blur-md">
<span>🔊</span>
<span id="audio-text">Attiva Audio</span>
</button>
<div class="text-[10px] text-white/40 font-mono">NEURAL_LINK v2.4.0 // VERTICAL_MODE</div>
</div>
</div>
<!-- 4. AR SCENE (VERTICAL SETUP) -->
<!-- Nota: missTolerance aumentato per mantenere il tracking più stabile mentre ci si muove -->
<a-scene
mindar-image="imageTargetSrc: img/targets.mind; filterMinCF:0.0001; filterBeta: 0.001; uiLoading: no; uiScanning: no; missTolerance: 10; warmupTolerance: 5"
color-space="sRGB"
renderer="colorManagement: true, physicallyCorrectLights, highRefreshRate: true"
vr-mode-ui="enabled: false"
device-orientation-permission-ui="enabled: false">
<a-assets>
<video id="vid" src="./img/video.mp4" preload="auto" loop muted playsinline webkit-playsinline crossorigin="anonymous"></video>
</a-assets>
<a-camera position="0 0 0" look-controls="enabled: false"></a-camera>
<a-entity id="example-target" mindar-image-target="targetIndex: 0">
<!--
GEOMETRIA VERTICALE (9:16)
Width: 1 (Largo quanto il target fisico)
Height: 1.777 (Proporzione 16:9 in verticale, cioè 1 * 16 / 9)
Questo forza il video ad apparire come uno schermo smartphone verticale fluttuante.
-->
<a-entity id="myVid"
geometry="primitive: plane; width: 1; height: 1.777"
material="src: #vid; shader: flat; transparent: true; opacity: 1"
position="0 0 0">
</a-entity>
<!-- Cornice Cyberpunk Verticale -->
<!-- Top Bar -->
<a-plane position="0 0.9 0" width="1.05" height="0.02" color="#00ff41" material="shader: flat"></a-plane>
<!-- Bottom Bar -->
<a-plane position="0 -0.9 0" width="1.05" height="0.02" color="#00ff41" material="shader: flat"></a-plane>
<!-- Left Bar -->
<a-plane position="-0.52 0 0" width="0.02" height="1.8" color="#00ff41" material="shader: flat"></a-plane>
<!-- Right Bar -->
<a-plane position="0.52 0 0" width="0.02" height="1.8" color="#00ff41" material="shader: flat"></a-plane>
<!-- Elementi decorativi agli angoli -->
<a-plane position="-0.52 0.9 0" width="0.1" height="0.02" color="white" material="shader: flat"></a-plane>
<a-plane position="0.52 -0.9 0" width="0.1" height="0.02" color="white" material="shader: flat"></a-plane>
</a-entity>
</a-scene>
<!-- 5. LOGIC -->
<script>
const video = document.querySelector("#vid");
const target = document.querySelector("#example-target");
const statusText = document.querySelector("#sys-status");
const aimOverlay = document.querySelector("#aim-overlay");
const audioBtn = document.querySelector("#audio-btn");
const audioText = document.querySelector("#audio-text");
const loader = document.querySelector("#custom-loader");
const loadingPercent = document.querySelector("#loading-percent");
const progressBar = document.querySelector("#progress-bar");
const scene = document.querySelector("a-scene");
let isAudioEnabled = false;
let loadProgress = 0;
// Simulazione caricamento rapido
const loadInterval = setInterval(() => {
loadProgress += 2;
if(loadProgress > 100) loadProgress = 100;
loadingPercent.innerText = loadProgress + "%";
progressBar.style.width = loadProgress + "%";
if(loadProgress >= 100) clearInterval(loadInterval);
}, 30);
// AR PRONTA
scene.addEventListener("arReady", () => {
console.log("AR System Ready");
// Chiudi loader
setTimeout(() => {
loader.style.opacity = "0";
setTimeout(() => loader.style.display = "none", 500);
}, 500);
});
// ERROR HANDLING
scene.addEventListener("arError", (ev) => {
alert("Errore fotocamera: controlla i permessi!");
});
// TARGET FOUND
target.addEventListener("targetFound", () => {
console.log("Found");
video.play();
statusText.innerText = "LOCKED";
statusText.style.color = "#fff";
statusText.classList.remove("animate-pulse");
aimOverlay.style.opacity = "0";
});
// TARGET LOST
target.addEventListener("targetLost", () => {
console.log("Lost");
video.pause();
statusText.innerText = "SEARCHING";
statusText.style.color = "#00ff41";
statusText.classList.add("animate-pulse");
aimOverlay.style.opacity = "1";
});
// AUDIO TOGGLE
audioBtn.addEventListener('click', () => {
if (!isAudioEnabled) {
video.muted = false;
isAudioEnabled = true;
audioText.innerText = "AUDIO ON";
audioBtn.classList.add("bg-[#00ff41]", "text-black");
audioBtn.classList.remove("bg-[#00ff41]/10", "text-[#00ff41]");
// Feedback aptico (vibrazione) se supportato
if(navigator.vibrate) navigator.vibrate(50);
setTimeout(() => {
audioBtn.style.opacity = "0";
audioBtn.style.pointerEvents = "none";
}, 1500);
}
});
</script>
</body>
</html> |