PHP Code Editor
<!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Rubik Vision 3D - Ultimate Fix</title> <script src="https://cdn.tailwindcss.com"></script> <!-- Multi-Layer CDN Loading --> <script id="three-script" src="https://cdn.jsdelivr.net"></script> <style> #video-container { position: relative; width: 100%; max-width: 400px; margin: auto; display: none; } .scan-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 4px solid #3b82f6; pointer-events: none; z-index: 10; } #canvas3d { width: 100%; height: 350px; background: #000; border-radius: 1.5rem; display: none; overflow: hidden; border: 1px solid rgba(255,255,255,0.1); } .capture-thumb { width: 60px; height: 60px; object-fit: cover; border-radius: 8px; border: 2px solid #3b82f6; flex-shrink: 0; } .scrollbar-hide::-webkit-scrollbar { display: none; } #debug-log { max-height: 50px; transition: max-height 0.3s ease; } #debug-log.expanded { max-height: 300px; } </style> </head> <body class="bg-black text-white min-h-screen flex flex-col items-center p-4 font-sans uppercase"> <div class="w-full max-w-md space-y-4 pb-24"> <header class="text-center py-4"> <h1 class="text-3xl font-black italic text-blue-500 tracking-tighter flex justify-center items-center gap-2"> <svg xmlns="http://www.w3.org" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-8 h-8 text-white"> <path stroke-linecap="round" stroke-linejoin="round" d="M21 7.5l-9-5.25L3 7.5m18 0l-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9" /> </svg> Rubik<span class="text-white not-italic text-2xl">Vision</span> </h1> <p id="status-text" class="text-gray-500 text-[10px] mt-1 tracking-[0.3em] font-bold">Engine Stable R128</p> </header> <div id="main-card" class="bg-gray-900 border border-white/10 p-4 rounded-[2.5rem] shadow-2xl relative"> <!-- View 1: Start --> <div id="start-view" class="py-12 text-center space-y-6"> <div class="flex justify-center"> <div class="p-6 bg-blue-600 rounded-3xl shadow-xl shadow-blue-500/30"> <svg xmlns="http://www.w3.org" viewBox="0 0 24 24" fill="currentColor" class="w-12 h-12 text-white"> <path d="M12 9a3.75 3.75 0 100 7.5A3.75 3.75 0 0012 9z" /> <path fill-rule="evenodd" d="M9.344 3.071a49.52 49.52 0 015.312 0c.967.052 1.83.585 2.332 1.39l.821 1.317c.24.383.645.643 1.11.71.716.102 1.432.21 2.146.321a2.75 2.75 0 012.435 2.722v10.719a2.75 2.75 0 01-2.75 2.75H3.25a2.75 2.75 0 01-2.75-2.75V9.53a2.75 2.75 0 012.435-2.722 48.574 48.574 0 012.146-.321c.465-.067.87-.327 1.11-.71l.821-1.317a2.75 2.75 0 012.332-1.39zM12 16.5a4.5 4.5 0 100-9 4.5 4.5 0 000 9z" clip-rule="evenodd" /> </svg> </div> </div> <div id="lib-status" class="text-[10px] text-yellow-500 font-mono italic">Checking Engine...</div> <button id="btn-start" onclick="startScanning()" class="bg-blue-600 hover:bg-blue-500 text-white font-black py-4 px-12 rounded-2xl tracking-widest transition-all opacity-50 cursor-not-allowed" disabled> Aktifkan Kamera </button> </div> <!-- View 2: Scanner --> <div id="video-container" class="rounded-2xl overflow-hidden aspect-square bg-black border border-white/10"> <video id="webcam" autoplay playsinline class="w-full h-full object-cover"></video> <div class="scan-overlay grid grid-cols-3 grid-rows-3 opacity-60"> <?php for($i=0; $i<9; $i++) echo '<div class="border border-white/20"></div>'; ?> </div> <canvas id="temp-canvas" class="hidden"></canvas> </div> <!-- View 3: 3D Visualization --> <div id="canvas3d" class="relative"></div> <!-- Scanner Controls --> <div id="scan-controls" class="hidden mt-6 space-y-4"> <div class="flex justify-between items-end border-b border-white/10 pb-2"> <div> <p class="text-[10px] text-gray-500 font-bold tracking-tighter">Current Side</p> <h2 id="side-label" class="text-xl font-bold text-blue-400 italic">Up (Atas)</h2> </div> <div id="step-counter" class="text-xs font-mono text-white font-black px-2 py-1 bg-blue-600 rounded">STEP 1/6</div> </div> <button onclick="captureSide()" class="w-full bg-white text-black font-black py-4 rounded-2xl active:scale-95 transition-transform flex items-center justify-center gap-3"> TANGKAP SISI </button> </div> </div> <!-- History Gallery --> <div id="gallery-container" class="hidden w-full bg-gray-900/50 p-4 rounded-3xl border border-white/10"> <div id="gallery" class="flex gap-3 overflow-x-auto pb-2 scrollbar-hide"></div> </div> <!-- System Debug Log --> <div id="debug-log" class="w-full bg-gray-950 border border-white/20 rounded-xl overflow-hidden shadow-2xl"> <div class="bg-gray-800 px-3 py-2 flex justify-between items-center cursor-pointer" onclick="toggleDebug()"> <span class="text-[10px] font-mono font-bold text-green-400 tracking-widest flex items-center gap-2"> <span class="w-1.5 h-1.5 bg-green-500 rounded-full animate-pulse"></span> SYSTEM LOG </span> <div class="flex gap-2"> <button onclick="copyLog(event)" class="text-[9px] bg-gray-700 px-2 py-0.5 rounded text-white">COPY</button> <span id="debug-toggle-icon" class="text-[10px]">▼</span> </div> </div> <div id="log-content" class="p-3 text-[9px] font-mono text-gray-400 h-[200px] overflow-y-auto space-y-1"></div> </div> <button id="btn-reset" onclick="location.reload()" class="hidden w-full text-gray-600 hover:text-white py-2 text-xs font-bold tracking-widest border border-gray-800 rounded-lg">RESTART APP</button> </div> <script> const sides = ['Up (Atas)', 'Right (Kanan)', 'Front (Depan)', 'Down (Bawah)', 'Left (Kiri)', 'Back (Belakang)']; let currentSideIndex = 0; let stream = null; let logs = []; function addLog(msg, type = 'INFO') { const time = new Date().toLocaleTimeString('id-ID'); const logMsg = `[${time}] [${type}] ${msg}`; logs.push(logMsg); const content = document.getElementById('log-content'); const entry = document.createElement('div'); entry.className = type === 'ERR' ? 'text-red-500' : (type === 'SUCCESS' ? 'text-blue-400' : 'text-gray-500'); entry.innerText = logMsg; content.prepend(entry); } // --- Library Loader Fix --- function checkLibrary() { if (typeof THREE !== 'undefined') { addLog("THREE.js Engine Loaded!", "SUCCESS"); document.getElementById('lib-status').innerText = "ENGINE READY ✓"; document.getElementById('lib-status').className = "text-[10px] text-blue-500 font-bold"; const btn = document.getElementById('btn-start'); btn.disabled = false; btn.classList.remove('opacity-50', 'cursor-not-allowed'); return true; } return false; } window.onload = () => { addLog("Inisialisasi sistem..."); if (!checkLibrary()) { addLog("CDN gagal. Mencoba memuat cadangan...", "ERR"); const fallback = document.createElement('script'); fallback.src = "https://cdnjs.cloudflare.com"; fallback.onload = checkLibrary; document.head.appendChild(fallback); } }; function toggleDebug() { document.getElementById('debug-log').classList.toggle('expanded'); } function copyLog(e) { e.stopPropagation(); navigator.clipboard.writeText(logs.join('\n')); alert('Log disalin!'); } async function startScanning() { addLog("Membuka jalinan kamera..."); try { stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' } }); document.getElementById('webcam').srcObject = stream; document.getElementById('start-view').style.display = 'none'; document.getElementById('video-container').style.display = 'block'; document.getElementById('scan-controls').classList.remove('hidden'); document.getElementById('gallery-container').classList.remove('hidden'); document.getElementById('btn-reset').classList.remove('hidden'); addLog("Kamera Aktif.", "SUCCESS"); } catch (err) { addLog("Izin kamera ditolak: " + err.message, "ERR"); } } function captureSide() { const video = document.getElementById('webcam'); const canvas = document.getElementById('temp-canvas'); const ctx = canvas.getContext('2d'); canvas.width = video.videoWidth; canvas.height = video.videoHeight; ctx.drawImage(video, 0, 0); const thumbWrap = document.createElement('div'); thumbWrap.className = "flex-shrink-0 text-center"; thumbWrap.innerHTML = `<img src="${canvas.toDataURL('image/jpeg', 0.5)}" class="capture-thumb mb-1"><span class="text-[8px] text-gray-500 font-bold">${sides[currentSideIndex].split(' ')}</span>`; document.getElementById('gallery').appendChild(thumbWrap); addLog(`Capture: ${sides[currentSideIndex]}`, "SUCCESS"); currentSideIndex++; if(currentSideIndex < 6) { document.getElementById('side-label').innerText = sides[currentSideIndex]; document.getElementById('step-counter').innerText = `STEP ${currentSideIndex + 1}/6`; } else { addLog("Scan Selesai. Mematikan kamera..."); if (stream) stream.getTracks().forEach(t => t.stop()); document.getElementById('video-container').style.display = 'none'; document.getElementById('scan-controls').classList.add('hidden'); document.getElementById('canvas3d').style.display = 'block'; setTimeout(init3D, 800); } } function init3D() { addLog("Memulai Engine Visual 3D..."); const container = document.getElementById('canvas3d'); if (typeof THREE === 'undefined') { addLog("CRITICAL: THREE IS UNDEFINED!", "ERR"); return; } try { const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, container.clientWidth / 350, 0.1, 1000); const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); renderer.setSize(container.clientWidth, 350); renderer.setPixelRatio(window.devicePixelRatio); container.innerHTML = ''; container.appendChild(renderer.domElement); const rubikGroup = new THREE.Group(); const mats = [0xB90000, 0xFF5800, 0xFFFFFF, 0xFFD500, 0x009B48, 0x0046AD].map(c => new THREE.MeshBasicMaterial({color: c})); for(let x = -1; x <= 1; x++) { for(let y = -1; y <= 1; y++) { for(let z = -1; z <= 1; z++) { const core = new THREE.Mesh(new THREE.BoxGeometry(1.02, 1.02, 1.02), new THREE.MeshBasicMaterial({color: 0x000000})); core.position.set(x, y, z); rubikGroup.add(core); const part = new THREE.Mesh(new THREE.BoxGeometry(0.94, 0.94, 0.94), mats); part.position.set(x, y, z); rubikGroup.add(part); } } } scene.add(rubikGroup); camera.position.set(4, 4, 4); camera.lookAt(0, 0, 0); function animate() { requestAnimationFrame(animate); rubikGroup.rotation.y += 0.01; rubikGroup.rotation.x += 0.005; renderer.render(scene, camera); } animate(); addLog("3D Render Success!", "SUCCESS"); } catch (err) { addLog("Render Error: " + err.message, "ERR"); } } </script> </body> </html>
Run Code
<!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Rubik Vision 3D - Ultimate Fix</title> <script src="https://cdn.tailwindcss.com"></script> <!-- Multi-Layer CDN Loading --> <script id="three-script" src="https://cdn.jsdelivr.net"></script> <style> #video-container { position: relative; width: 100%; max-width: 400px; margin: auto; display: none; } .scan-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 4px solid #3b82f6; pointer-events: none; z-index: 10; } #canvas3d { width: 100%; height: 350px; background: #000; border-radius: 1.5rem; display: none; overflow: hidden; border: 1px solid rgba(255,255,255,0.1); } .capture-thumb { width: 60px; height: 60px; object-fit: cover; border-radius: 8px; border: 2px solid #3b82f6; flex-shrink: 0; } .scrollbar-hide::-webkit-scrollbar { display: none; } #debug-log { max-height: 50px; transition: max-height 0.3s ease; } #debug-log.expanded { max-height: 300px; } </style> </head> <body class="bg-black text-white min-h-screen flex flex-col items-center p-4 font-sans uppercase"> <div class="w-full max-w-md space-y-4 pb-24"> <header class="text-center py-4"> <h1 class="text-3xl font-black italic text-blue-500 tracking-tighter flex justify-center items-center gap-2"> <svg xmlns="http://www.w3.org" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-8 h-8 text-white"> <path stroke-linecap="round" stroke-linejoin="round" d="M21 7.5l-9-5.25L3 7.5m18 0l-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9" /> </svg> Rubik<span class="text-white not-italic text-2xl">Vision</span> </h1> <p id="status-text" class="text-gray-500 text-[10px] mt-1 tracking-[0.3em] font-bold">Engine Stable R128</p> </header> <div id="main-card" class="bg-gray-900 border border-white/10 p-4 rounded-[2.5rem] shadow-2xl relative"> <!-- View 1: Start --> <div id="start-view" class="py-12 text-center space-y-6"> <div class="flex justify-center"> <div class="p-6 bg-blue-600 rounded-3xl shadow-xl shadow-blue-500/30"> <svg xmlns="http://www.w3.org" viewBox="0 0 24 24" fill="currentColor" class="w-12 h-12 text-white"> <path d="M12 9a3.75 3.75 0 100 7.5A3.75 3.75 0 0012 9z" /> <path fill-rule="evenodd" d="M9.344 3.071a49.52 49.52 0 015.312 0c.967.052 1.83.585 2.332 1.39l.821 1.317c.24.383.645.643 1.11.71.716.102 1.432.21 2.146.321a2.75 2.75 0 012.435 2.722v10.719a2.75 2.75 0 01-2.75 2.75H3.25a2.75 2.75 0 01-2.75-2.75V9.53a2.75 2.75 0 012.435-2.722 48.574 48.574 0 012.146-.321c.465-.067.87-.327 1.11-.71l.821-1.317a2.75 2.75 0 012.332-1.39zM12 16.5a4.5 4.5 0 100-9 4.5 4.5 0 000 9z" clip-rule="evenodd" /> </svg> </div> </div> <div id="lib-status" class="text-[10px] text-yellow-500 font-mono italic">Checking Engine...</div> <button id="btn-start" onclick="startScanning()" class="bg-blue-600 hover:bg-blue-500 text-white font-black py-4 px-12 rounded-2xl tracking-widest transition-all opacity-50 cursor-not-allowed" disabled> Aktifkan Kamera </button> </div> <!-- View 2: Scanner --> <div id="video-container" class="rounded-2xl overflow-hidden aspect-square bg-black border border-white/10"> <video id="webcam" autoplay playsinline class="w-full h-full object-cover"></video> <div class="scan-overlay grid grid-cols-3 grid-rows-3 opacity-60"> <?php for($i=0; $i<9; $i++) echo '<div class="border border-white/20"></div>'; ?> </div> <canvas id="temp-canvas" class="hidden"></canvas> </div> <!-- View 3: 3D Visualization --> <div id="canvas3d" class="relative"></div> <!-- Scanner Controls --> <div id="scan-controls" class="hidden mt-6 space-y-4"> <div class="flex justify-between items-end border-b border-white/10 pb-2"> <div> <p class="text-[10px] text-gray-500 font-bold tracking-tighter">Current Side</p> <h2 id="side-label" class="text-xl font-bold text-blue-400 italic">Up (Atas)</h2> </div> <div id="step-counter" class="text-xs font-mono text-white font-black px-2 py-1 bg-blue-600 rounded">STEP 1/6</div> </div> <button onclick="captureSide()" class="w-full bg-white text-black font-black py-4 rounded-2xl active:scale-95 transition-transform flex items-center justify-center gap-3"> TANGKAP SISI </button> </div> </div> <!-- History Gallery --> <div id="gallery-container" class="hidden w-full bg-gray-900/50 p-4 rounded-3xl border border-white/10"> <div id="gallery" class="flex gap-3 overflow-x-auto pb-2 scrollbar-hide"></div> </div> <!-- System Debug Log --> <div id="debug-log" class="w-full bg-gray-950 border border-white/20 rounded-xl overflow-hidden shadow-2xl"> <div class="bg-gray-800 px-3 py-2 flex justify-between items-center cursor-pointer" onclick="toggleDebug()"> <span class="text-[10px] font-mono font-bold text-green-400 tracking-widest flex items-center gap-2"> <span class="w-1.5 h-1.5 bg-green-500 rounded-full animate-pulse"></span> SYSTEM LOG </span> <div class="flex gap-2"> <button onclick="copyLog(event)" class="text-[9px] bg-gray-700 px-2 py-0.5 rounded text-white">COPY</button> <span id="debug-toggle-icon" class="text-[10px]">▼</span> </div> </div> <div id="log-content" class="p-3 text-[9px] font-mono text-gray-400 h-[200px] overflow-y-auto space-y-1"></div> </div> <button id="btn-reset" onclick="location.reload()" class="hidden w-full text-gray-600 hover:text-white py-2 text-xs font-bold tracking-widest border border-gray-800 rounded-lg">RESTART APP</button> </div> <script> const sides = ['Up (Atas)', 'Right (Kanan)', 'Front (Depan)', 'Down (Bawah)', 'Left (Kiri)', 'Back (Belakang)']; let currentSideIndex = 0; let stream = null; let logs = []; function addLog(msg, type = 'INFO') { const time = new Date().toLocaleTimeString('id-ID'); const logMsg = `[${time}] [${type}] ${msg}`; logs.push(logMsg); const content = document.getElementById('log-content'); const entry = document.createElement('div'); entry.className = type === 'ERR' ? 'text-red-500' : (type === 'SUCCESS' ? 'text-blue-400' : 'text-gray-500'); entry.innerText = logMsg; content.prepend(entry); } // --- Library Loader Fix --- function checkLibrary() { if (typeof THREE !== 'undefined') { addLog("THREE.js Engine Loaded!", "SUCCESS"); document.getElementById('lib-status').innerText = "ENGINE READY ✓"; document.getElementById('lib-status').className = "text-[10px] text-blue-500 font-bold"; const btn = document.getElementById('btn-start'); btn.disabled = false; btn.classList.remove('opacity-50', 'cursor-not-allowed'); return true; } return false; } window.onload = () => { addLog("Inisialisasi sistem..."); if (!checkLibrary()) { addLog("CDN gagal. Mencoba memuat cadangan...", "ERR"); const fallback = document.createElement('script'); fallback.src = "https://cdnjs.cloudflare.com"; fallback.onload = checkLibrary; document.head.appendChild(fallback); } }; function toggleDebug() { document.getElementById('debug-log').classList.toggle('expanded'); } function copyLog(e) { e.stopPropagation(); navigator.clipboard.writeText(logs.join('\n')); alert('Log disalin!'); } async function startScanning() { addLog("Membuka jalinan kamera..."); try { stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' } }); document.getElementById('webcam').srcObject = stream; document.getElementById('start-view').style.display = 'none'; document.getElementById('video-container').style.display = 'block'; document.getElementById('scan-controls').classList.remove('hidden'); document.getElementById('gallery-container').classList.remove('hidden'); document.getElementById('btn-reset').classList.remove('hidden'); addLog("Kamera Aktif.", "SUCCESS"); } catch (err) { addLog("Izin kamera ditolak: " + err.message, "ERR"); } } function captureSide() { const video = document.getElementById('webcam'); const canvas = document.getElementById('temp-canvas'); const ctx = canvas.getContext('2d'); canvas.width = video.videoWidth; canvas.height = video.videoHeight; ctx.drawImage(video, 0, 0); const thumbWrap = document.createElement('div'); thumbWrap.className = "flex-shrink-0 text-center"; thumbWrap.innerHTML = `<img src="${canvas.toDataURL('image/jpeg', 0.5)}" class="capture-thumb mb-1"><span class="text-[8px] text-gray-500 font-bold">${sides[currentSideIndex].split(' ')}</span>`; document.getElementById('gallery').appendChild(thumbWrap); addLog(`Capture: ${sides[currentSideIndex]}`, "SUCCESS"); currentSideIndex++; if(currentSideIndex < 6) { document.getElementById('side-label').innerText = sides[currentSideIndex]; document.getElementById('step-counter').innerText = `STEP ${currentSideIndex + 1}/6`; } else { addLog("Scan Selesai. Mematikan kamera..."); if (stream) stream.getTracks().forEach(t => t.stop()); document.getElementById('video-container').style.display = 'none'; document.getElementById('scan-controls').classList.add('hidden'); document.getElementById('canvas3d').style.display = 'block'; setTimeout(init3D, 800); } } function init3D() { addLog("Memulai Engine Visual 3D..."); const container = document.getElementById('canvas3d'); if (typeof THREE === 'undefined') { addLog("CRITICAL: THREE IS UNDEFINED!", "ERR"); return; } try { const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, container.clientWidth / 350, 0.1, 1000); const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); renderer.setSize(container.clientWidth, 350); renderer.setPixelRatio(window.devicePixelRatio); container.innerHTML = ''; container.appendChild(renderer.domElement); const rubikGroup = new THREE.Group(); const mats = [0xB90000, 0xFF5800, 0xFFFFFF, 0xFFD500, 0x009B48, 0x0046AD].map(c => new THREE.MeshBasicMaterial({color: c})); for(let x = -1; x <= 1; x++) { for(let y = -1; y <= 1; y++) { for(let z = -1; z <= 1; z++) { const core = new THREE.Mesh(new THREE.BoxGeometry(1.02, 1.02, 1.02), new THREE.MeshBasicMaterial({color: 0x000000})); core.position.set(x, y, z); rubikGroup.add(core); const part = new THREE.Mesh(new THREE.BoxGeometry(0.94, 0.94, 0.94), mats); part.position.set(x, y, z); rubikGroup.add(part); } } } scene.add(rubikGroup); camera.position.set(4, 4, 4); camera.lookAt(0, 0, 0); function animate() { requestAnimationFrame(animate); rubikGroup.rotation.y += 0.01; rubikGroup.rotation.x += 0.005; renderer.render(scene, camera); } animate(); addLog("3D Render Success!", "SUCCESS"); } catch (err) { addLog("Render Error: " + err.message, "ERR"); } } </script> </body> </html>
Run Code New Tab
Result