Transaction

5e394e482936eafc5e6f7dd237ffac42e47bb8d3913eeb19be3c2abb46a6716d
Timestamp (utc)
2025-12-14 07:32:29
Fee Paid
0.00000141 BSV
(
0.00064442 BSV
-
0.00064301 BSV
)
Fee Rate
251.6 sat/KB
Version
1
Confirmations
6,669
Size Stats
560 B

2 Inputs

Total Input:
0.00064442 BSV
  • v© £üaÍïêjj&@Ú:‹ø'šÀ_ψ¬cordQ text/htmlMȍ<!DOCTYPE html> <html lang="ja"> <head> <title>DRiVE - Hand Tracking Ver.</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <style> body { margin: 0; background: #000; overscroll-behavior: none; cursor: crosshair; font-family: -apple-system, BlinkMacSystemFont, sans-serif; touch-action: none; user-select: none; position: relative; } canvas { display: block; touch-action: none; position: absolute; top: 0; left: 0; z-index: 1; cursor: crosshair; } /* 映像入力は非表示(計算のみに使用) */ #input_video { display: none; /* iOSでのレイアウト崩れ防止 */ position: absolute; top: 0; left: 0; width: 1px; height: 1px; opacity: 0; } /* カメラステータス表示 */ #camera-status { position: fixed; bottom: 60px; /* オーディオ情報とかぶらないように少し上に */ left: 50%; transform: translateX(-50%); color: rgba(0, 255, 255, 0.7); font-size: 12px; pointer-events: none; text-shadow: 0 0 5px rgba(0, 0, 0, 0.8); width: 90%; text-align: center; z-index: 202; } .sound-overlay { position: fixed; top: 20px; right: 20px; z-index: 200; opacity: 0.3; transition: opacity 0.3s ease; pointer-events: auto; } .sound-overlay:hover { opacity: 1 } .sound-info { font-size: 12px; cursor: pointer; padding: 10px 18px; border-radius: 8px; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); user-select: none; min-width: 80px; display: flex; align-items: center; justify-content: center; -webkit-tap-highlight-color: transparent; pointer-events: auto; position: relative; z-index: 201; } .sound-info.sound-on { color: rgba(255, 100, 255, 0.95); background: linear-gradient(135deg, rgba(255, 100, 255, 0.2) 0%, rgba(100, 255, 255, 0.15) 50%, rgba(255, 255, 100, 0.1) 100%); border: 1px solid rgba(255, 150, 255, 0.4); box-shadow: 0 2px 12px rgba(255, 100, 255, 0.3) } .sound-info.sound-on:hover { transform: translateY(-1px) } .sound-info.sound-on.compact { font-size: 0; padding: 10px; border-radius: 50%; min-width: 20px; width: 20px; height: 20px } .sound-info.sound-on.compact::after { content: '●'; font-size: 12px } .sound-info.sound-off { color: rgba(150, 150, 150, 0.8); background: linear-gradient(135deg, rgba(100, 100, 100, 0.1) 0%, rgba(120, 120, 120, 0.05) 100%); border: 1px solid rgba(100, 100, 100, 0.3); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2) } .sound-info.sound-off:hover { background: linear-gradient(135deg, rgba(100, 100, 100, 0.2) 0%, rgba(120, 120, 120, 0.15) 100%); transform: translateY(-1px) } .sound-info.loading { animation: pulse 1.5s ease-in-out infinite } .audio-info { position: fixed; bottom: 20px; left: 20px; color: rgba(255, 150, 255, 0.8); font-size: 12px; z-index: 100; backdrop-filter: blur(10px); background: rgba(20, 0, 40, 0.6); padding: 10px 15px; border-radius: 8px; border: 1px solid rgba(255, 100, 255, 0.3); opacity: 0; transition: opacity 0.3s ease; display: none !important } .audio-info.visible { opacity: 1 } @keyframes pulse { 0%, 100% { opacity: 0.6 } 50% { opacity: 1 } } @media (max-width:768px) { body, canvas { cursor: none; } .sound-overlay { top: 15px; right: 15px } .sound-info { font-size: 9px; padding: 6px 10px; min-width: 60px } .sound-info.sound-on.compact { width: 16px; height: 16px; padding: 6px } .sound-info.sound-on.compact::after { font-size: 10px } .audio-info { bottom: 15px; left: 15px; font-size: 11px } } </style> <!-- MediaPipe Dependencies --> <script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/@mediapipe/control_utils/control_utils.js" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/@mediapipe/hands/hands.js" crossorigin="anonymous"></script> </head> <body> <!-- iOS対応: playsinline, muted, autoplay を追加 --> <video id="input_video" playsinline webkit-playsinline muted autoplay></video> <div class="sound-overlay"> <div class="sound-info sound-off" id="sound-info">Sound: OFF</div> </div> <div id="camera-status">Initializing Hand Tracking...</div> <div class="audio-info" id="audio-info"> <div>BSV Ordinals Audio Reactive</div> <div>Frequency: <span id="dominant-freq">-</span> Hz</div> <div>Volume: <span id="volume-level">-</span>%</div> </div> <script src="https://ordfs.network/content/0d2c3eea58ecf14689372d0a72be5aa91ad1701c5d16c7c06ec88d200709ed7f_0"></script> <script src="https://ordfs.network/content/265aad29e9f6392db7eb74c63835c9d945dd644bf263d46ab747a5ae21883fbf_0"></script> <script src="https://ordfs.network/content/f052fc0e81a5f9209b0941e6975f22159fce8ddd2abc1c66b1ba9718793e3d81_0"></script> <script src="https://ordfs.network/content/ee7958cbce11bd78febb9c7860346d737671d9ca2292b881e62d7c2ca3dc8516_0"></script> <script src="https://ordfs.network/content/1917b05e87f2f254666b6724a909f84adfcc13e5b528dd4ee377de40162bb0df_0"></script> <script src="https://ordfs.network/content/a9a3e86aea42d09a50d81fd55696f75a15c5fc2fa0dd9306adbc3eb04e316b5b_0"></script> <script src="https://ordfs.network/content/88b397007487bbad40403924cc1f84fe078aa515b5539f93291e135c07f6ef44_0"></script> <script src="https://ordfs.network/content/1f2fa8750464cbe0a0a8da84244f0cf29b07064e84a5820eab1549b7c4524bcf_0"></script> <script src="https://ordfs.network/content/b4f4295b35f47ed58a8960d78146b6d14d39087626c8fdebb85884e45534708d_0"></script> <script> const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); // --- Hand Tracking System Class --- class HandController { constructor() { this.active = false; this.isTwoHands = false; this.center = { x: 0, y: 0 }; // -0.5 to 0.5 this.distance = 0; // Normalized distance between hands this.statusElement = document.getElementById('camera-status'); // モバイル判定 this.isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); this.init(); } init() { const videoElement = document.getElementById('input_video'); const hands = new Hands({locateFile: (file) => { return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`; }}); hands.setOptions({ maxNumHands: 2, // モバイル時は軽量モデル(0)、PC時は高精度モデル(1) modelComplexity: this.isMobile ? 0 : 1, minDetectionConfidence: 0.5, minTrackingConfidence: 0.5 }); hands.onResults(this.onResults.bind(this)); const camera = new Camera(videoElement, { onFrame: async () => { await hands.send({image: videoElement}); }, // モバイルパフォーマンスのために解像度を調整 width: this.isMobile ? 360 : 640, height: this.isMobile ? 270 : 480, // インカメラを強制 facingMode: 'user' }); camera.start() .then(() => { this.statusElement.innerText = this.isMobile ? "Camera Active. (Mobile Mode)" : "Camera Active. Show Hands!"; setTimeout(() => { this.statusElement.style.opacity = 0; }, 4000); }) .catch(e => { console.error(e); this.statusElement.innerText = "Camera Error. Check permissions."; this.statusElement.style.color = "red"; }); } onResults(results) { if (results.multiHandLandmarks && results.multiHandLandmarks.length > 0) { this.active = true; const landmarks = results.multiHandLandmarks; if (landmarks.length === 2) { this.isTwoHands = true; const h1 = landmarks[0][9]; // Middle finger MCP const h2 = landmarks[1][9]; // Center this.center.x = (h1.x + h2.x) / 2 - 0.5; this.center.y = (h1.y + h2.y) / 2 - 0.5; // Distance const dx = h1.x - h2.x; const dy = h1.y - h2.y; this.distance = Math.sqrt(dx*dx + dy*dy); } else { this.isTwoHands = false; const h1 = landmarks[0][9]; this.center.x = h1.x - 0.5; this.center.y = h1.y - 0.5; } } else { this.active = false; } } } class RevolutionaryAudioSystem { constructor() { this.audio = null; this.audioContext = null; this.analyser = null; this.isLoaded = false; this.isPlaying = false; this.isLoading = false; this.hasUserGesture = false; this.ordinalsUrl = 'https://ordfs.network/content/5a8af75b2b4d20e6d356c4d78c2c3b1e0e839d5563a6e7004f73fd3793470783_0'; this.rawData = {bass: 0, mid: 0, treble: 0, volume: 0, dominantFreq: 0}; this.revolutionaryData = {chaos: 0, rainbow: 0, explosion: 0, morphing: 0, individual: 0}; this.beatDetection = {lastBeat: 0, strength: 0, isActive: false}; this.explosionTrigger = false; this.initMobileSupport(); } initMobileSupport() { const gestureEvents = ['touchstart', 'touchend', 'click', 'keydown']; const handleFirstGesture = () => { this.hasUserGesture = true; gestureEvents.forEach(event => document.removeEventListener(event, handleFirstGesture, true) ); }; gestureEvents.forEach(event => document.addEventListener(event, handleFirstGesture, {capture: true, once: true}) ); } async initialize() { if (this.isLoaded || this.isLoading) return; this.isLoading = true; try { if (isMobile && !this.hasUserGesture) { throw new Error('User gesture required for mobile audio'); } this.audio = new Audio(); this.audio.crossOrigin = "anonymous"; this.audio.loop = true; this.audio.volume = 0.7; if (isMobile) { this.audio.preload = "metadata"; this.audio.playsInline = true; } else { this.audio.preload = "auto"; } await new Promise((resolve, reject) => { const timeoutId = setTimeout(() => reject(new Error('Audio timeout')), 15000); const resolveOnce = () => { clearTimeout(timeoutId); resolve(); }; this.audio.addEventListener('canplaythrough', resolveOnce, { once: true }); this.audio.addEventListener('error', (e) => { clearTimeout(timeoutId); reject(new Error('Audio error')); }, { once: true }); this.audio.src = this.ordinalsUrl; this.audio.load(); }); this.isLoaded = true; } catch (error) { console.error('Audio failed:', error); this.isLoaded = false; throw error; } finally { this.isLoading = false; } } setupAudioContext() { if (this.audioContext) return; try { this.audioContext = new (window.AudioContext || window.webkitAudioContext)(); const source = this.audioContext.createMediaElementSource(this.audio); this.analyser = this.audioContext.createAnalyser(); this.analyser.fftSize = isMobile ? 1024 : 2048; this.analyser.smoothingTimeConstant = 0.1; source.connect(this.analyser); this.analyser.connect(this.audioContext.destination); } catch (error) { console.error('AudioContext setup failed:', error); throw error; } } async play() { if (!this.isLoaded && !this.isLoading) await this.initialize(); if (this.audio && this.isLoaded && !this.isPlaying) { this.setupAudioContext(); if (this.audioContext && this.audioContext.state === 'suspended') { await this.audioContext.resume(); } await this.audio.play(); this.isPlaying = true; } } stop() { if (this.audio && this.isPlaying) { this.audio.pause(); this.audio.currentTime = 0; this.isPlaying = false; } } updateRevolutionaryData() { if (!this.analyser || !this.isPlaying) return; const bufferLength = this.analyser.frequencyBinCount; const frequencyData = new Uint8Array(bufferLength); this.analyser.getByteFrequencyData(frequencyData); const bassEnd = Math.floor(bufferLength * 0.1); const midEnd = Math.floor(bufferLength * 0.6); this.rawData.bass = this.getMaxLevel(frequencyData, 0, bassEnd) / 255; this.rawData.mid = this.getMaxLevel(frequencyData, bassEnd, midEnd) / 255; this.rawData.treble = this.getMaxLevel(frequencyData, midEnd, bufferLength) / 255; this.rawData.volume = this.getAverageLevel(frequencyData, 0, bufferLength) / 255; this.rawData.dominantFreq = this.getDominantFreq(frequencyData); this.revolutionaryData.chaos = Math.pow(this.rawData.bass * 0.08 + this.rawData.treble * 0.08, 1.5) * 0.4; this.revolutionaryData.rainbow = (this.rawData.mid * 0.1 + this.rawData.treble * 0.12) * 0.3; this.revolutionaryData.individual = this.rawData.volume * this.rawData.treble * 0.4; this.revolutionaryData.morphing = Math.pow(this.rawData.volume, 2) * 0.3; const now = Date.now(); const bassThreshold = 0.8; if (this.rawData.bass > bassThreshold && now - this.beatDetection.lastBeat > 200) { this.beatDetection.lastBeat = now; this.beatDetection.strength = this.rawData.bass; this.beatDetection.isActive = true; if (this.rawData.bass > 0.9) this.explosionTrigger = true; } if (now - this.beatDetection.lastBeat > 300) this.beatDetection.isActive = false; this.revolutionaryData.explosion = this.beatDetection.isActive ? this.beatDetection.strength * 3 : 0; } getAverageLevel(data, start, end) { let sum = 0; for (let i = start; i < end; i++) sum += data[i]; return sum / (end - start); } getMaxLevel(data, start, end) { let max = 0; for (let i = start; i < end; i++) max = Math.max(max, data[i]); return max; } getDominantFreq(data) { let maxIndex = 0, maxValue = 0; for (let i = 0; i < data.length; i++) { if (data[i] > maxValue) { maxValue = data[i]; maxIndex = i; } } return (maxIndex / data.length) * 22050; } } let camera, scene, renderer, particleGroup, particles, mouse = new THREE.Vector2(-100, -100), customCursor, composer, glitchPass, bloomPass; let isMouseDown = false, previousMouse = {x: 0, y: 0}, touches = [], lastPinchDistance = null, baseCameraZ = 2500; const audioSystem = new RevolutionaryAudioSystem(); const PARTICLE_COUNT = 90000; const particlesData = []; let revolutionaryTime = 0, explosionParticles = []; let explosionRipples = [], lastExplosionTime = 0; // Hand Controller Instance let handController; // Cyberpunk Cityscape Generation Function function generateCyberpunkCityPosition(index, total) { const gridSize = Math.floor(Math.sqrt(total)); const gridX = index % gridSize; const gridZ = Math.floor(index / gridSize); const spacing = isMobile ? 15 : 25; const x = (gridX - gridSize / 2) * spacing; const z = (gridZ - gridSize / 2) * spacing; // Generate building height with Perlin-like noise const noiseScale = 0.1; const heightNoise = perlinNoise(gridX * noiseScale, gridZ * noiseScale); let y = heightNoise * 400; // Add some random taller "skyscrapers" if (Math.random() < 0.01) { y += 300 + Math.random() * 300; } // Create canyons/streets if (gridX % 10 === 0 || gridZ % 10 === 0) { y *= 0.2; } return { x: x + (Math.random() - 0.5) * 5, y: y * (isMobile ? 0.5 : 1), z: z + (Math.random() - 0.5) * 5, gridX: gridX, gridZ: gridZ }; } // Simple 2D Perlin Noise function function perlinNoise(x, y) { const n = x + y * 57; const nn = (n << 13) ^ n; return (1.0 - ((nn * (nn * nn * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0); } function generateSprite() { const canvas = document.createElement('canvas'); canvas.width = canvas.height = 128; const ctx = canvas.getContext('2d'); const gradient = ctx.createRadialGradient(64, 64, 0, 64, 64, 64); gradient.addColorStop(0, 'rgba(255,255,255,1)'); gradient.addColorStop(0.3, 'rgba(255,200,255,0.8)'); gradient.addColorStop(0.6, 'rgba(200,255,255,0.4)'); gradient.addColorStop(1, 'rgba(0,0,0,0)'); ctx.fillStyle = gradient; ctx.fillRect(0, 0, 128, 128); return new THREE.CanvasTexture(canvas); } function init() { camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 5000); if (isMobile) { baseCameraZ = 1000; // 最もズームインした状態 } camera.position.z = baseCameraZ; scene = new THREE.Scene(); particleGroup = new THREE.Group(); scene.add(particleGroup); particleGroup.rotation.y = Math.PI; // Start from the opposite side const positions = new Float32Array(PARTICLE_COUNT * 3); const colors = new Float32Array(PARTICLE_COUNT * 3); const sizes = new Float32Array(PARTICLE_COUNT); for (let i = 0; i < PARTICLE_COUNT; i++) { // Generate cyberpunk city position const cityPos = generateCyberpunkCityPosition(i, PARTICLE_COUNT); const i3 = i * 3; positions[i3] = cityPos.x; positions[i3 + 1] = cityPos.y; positions[i3 + 2] = cityPos.z; // Initial color: cyberpunk gradient const baseHue = 0.6 + (cityPos.y / 800) * 0.2; // Height-based hue const baseColor = new THREE.Color().setHSL(baseHue, 0.9, 0.7); colors[i3] = baseColor.r; colors[i3 + 1] = baseColor.g; colors[i3 + 2] = baseColor.b; sizes[i] = 2 + Math.random() * 3; particlesData.push({ velocity: new THREE.Vector3((Math.random() - 0.5) * 0.6, (Math.random() - 0.5) * 0.6, (Math.random() - 0.5) * 0.6), explosionVelocity: new THREE.Vector3(0, 0, 0), originalPos: new THREE.Vector3(cityPos.x, cityPos.y, cityPos.z), isBeam: false, personalPhase: Math.random() * Math.PI * 2, personalFreq: 0.8 + Math.random() * 0.4, personalAmp: 0.5 + Math.random() * 1.5, audioSensitivity: Math.random() * 0.8 + 0.2, frequencyBand: Math.floor(Math.random() * 4), baseSize: 2 + Math.random() * 3, chaosMultiplier: 0.5 + Math.random() * 1.5, rainbowSensitivity: Math.random() * 0.9 + 0.1, audioReactivity: { bassWeight: Math.random() * 0.5 + 0.5, midWeight: Math.random() * 0.8 + 0.2, trebleWeight: Math.random() * 0.6 + 0.4, directionBias: Math.random() * Math.PI * 2, temperament: Math.random(), spiralTendency: Math.random(), pulseSync: Math.random() * 0.5 + 0.5, chaosThreshold: Math.random() * 0.3 + 0.4 } }); } const geometry = new THREE.BufferGeometry(); geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3)); geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1)); particles = new THREE.Points(geometry, new THREE.PointsMaterial({ size: 20, map: generateSprite(), vertexColors: true, sizeAttenuation: true, blending: THREE.AdditiveBlending, transparent: true, depthWrite: false })); particleGroup.add(particles); customCursor = new THREE.Mesh(new THREE.RingGeometry(2, 2.5, 32), new THREE.MeshBasicMaterial({color: 0xff00ff, side: THREE.DoubleSide, transparent: true, opacity: 0.8})); scene.add(customCursor); renderer = new THREE.WebGLRenderer({antialias: !isMobile}); renderer.setPixelRatio(Math.min(window.devicePixelRatio, isMobile ? 1.5 : 2)); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // Post-processing composer = new THREE.EffectComposer(renderer); composer.addPass(new THREE.RenderPass(scene, camera)); bloomPass = new THREE.UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85); composer.addPass(bloomPass); glitchPass = new THREE.GlitchPass(); composer.addPass(glitchPass); // Initialize Hand Controller handController = new HandController(); // イベントリスナー document.getElementById('sound-info').addEventListener('click', toggleSound); // タッチ・マウスイベント ['resize', 'mousemove', 'mousedown', 'mouseup', 'wheel', 'touchstart', 'touchmove', 'touchend'].forEach(event => { if (event === 'resize') window.addEventListener(event, onWindowResize); else document.addEventListener(event, { mousemove: onMouseMove, mousedown: onMouseDown, mouseup: onMouseUp, wheel: onMouseWheel, touchstart: onTouchStart, touchmove: onTouchMove, touchend: onTouchEnd }[event], event.startsWith('touch') ? {passive: false} : undefined); }); } async function toggleSound() { const soundInfo = document.getElementById('sound-info'); if (!soundInfo || audioSystem.isLoading) return; if (!audioSystem.isPlaying) { soundInfo.classList.add('loading'); soundInfo.textContent = 'Loading...'; try { await audioSystem.play(); soundInfo.classList.remove('sound-off', 'loading'); soundInfo.classList.add('sound-on'); soundInfo.textContent = 'Sound: ON'; setTimeout(() => soundInfo.classList.add('compact'), 1000); } catch (error) { console.error('Audio play failed:', error); soundInfo.classList.remove('loading'); soundInfo.classList.add('sound-off'); soundInfo.textContent = 'Sound: OFF'; } } else { audioSystem.stop(); soundInfo.classList.remove('sound-on', 'compact'); soundInfo.classList.add('sound-off'); soundInfo.textContent = 'Sound: OFF'; } } function animate() { requestAnimationFrame(animate); revolutionaryTime += 0.03; const dt = 0.016; audioSystem.updateRevolutionaryData(); // --- Beat Detection for Post-Processing --- const timeSinceBeat = Date.now() - audioSystem.beatDetection.lastBeat; const beatDecay = 150; // ms for the flash effect let beatIntensity = 0; if (audioSystem.isPlaying && timeSinceBeat < beatDecay) { // Creates a value from 1 down to 0 over the decay period beatIntensity = (1 - (timeSinceBeat / beatDecay)) * audioSystem.beatDetection.strength; } let handGlitchTrigger = false; // --- Hand Tracking Interaction & Logic --- if (handController && handController.active) { // 1. Rotation based on Hand Center // Map -0.5..0.5 to Rotation Angle const targetRotY = handController.center.x * 3 + Math.PI; // +PI to align with initial state const targetRotX = handController.center.y * 1.5; // Smooth Lerp particleGroup.rotation.y += (targetRotY - particleGroup.rotation.y) * 0.1; particleGroup.rotation.x += (targetRotX - particleGroup.rotation.x) * 0.1; // 2. Zoom based on Hand Distance // Distance usually ranges 0.05 (close) to 0.6 (far) if (handController.isTwoHands) { const d = Math.max(0.05, Math.min(0.6, handController.distance)); // Close hands = Far away (Zoom out), Open hands = Close up (Zoom in) // Map 0.05..0.6 to Z 4000..1000 const normalizedD = (d - 0.05) / 0.55; const targetZ = 4000 - (normalizedD * 3000); camera.position.z += (targetZ - camera.position.z) * 0.1; // 3. Hand Glitch Trigger (Clap) if (handController.distance < 0.1) { handGlitchTrigger = true; } } } if (audioSystem.isPlaying || handGlitchTrigger) { // --- Glitch Pass on Beat OR Hand Trigger --- if (beatIntensity > 0.3 || handGlitchTrigger) { glitchPass.enabled = true; } else { glitchPass.enabled = false; } // --- Bloom Pass Strength --- let bloomStrength = 1.5 + Math.min(audioSystem.rawData.volume * 2, 2.5); bloomStrength += beatIntensity * 3.0; if(handGlitchTrigger) bloomStrength += 2.0; bloomPass.strength = bloomStrength; } else { glitchPass.enabled = false; bloomPass.strength = 1.5; } const revData = audioSystem.revolutionaryData; // UI update if (audioSystem.isPlaying) { document.getElementById('dominant-freq').textContent = Math.round(audioSystem.rawData.dominantFreq); document.getElementById('volume-level').textContent = Math.round(audioSystem.rawData.volume * 100); if (audioSystem.explosionTrigger) { audioSystem.explosionTrigger = false; } } // 1. Enhanced Rotation Speed (Fallback when hands not active or additive) if (!handController.active && !isMouseDown) { let rotSpeed = 0.0005; if (audioSystem.isPlaying) { const audioIntensity = audioSystem.rawData.volume; const mid = audioSystem.rawData.mid; let speedIncrease = (audioIntensity * 0.006) + (mid * 0.01); rotSpeed += Math.min(speedIncrease, 0.04); } particleGroup.rotation.y += rotSpeed; } // 2. Sound-Reactive Zoom (Combined with Hand Zoom) if (!handController.active) { if (audioSystem.isPlaying) { const bass = audioSystem.rawData.bass; let targetZ = baseCameraZ; if (bass > 0.7) { targetZ += bass * 500; } camera.position.z += (targetZ - camera.position.z) * 0.05; } else { camera.position.z += (baseCameraZ - camera.position.z) * 0.05; } } // Clamp rotations particleGroup.rotation.x = THREE.MathUtils.clamp(particleGroup.rotation.x, -Math.PI / 2, Math.PI / 2); const positions = particles.geometry.attributes.position.array; const colors = particles.geometry.attributes.color.array; const sizes = particles.geometry.attributes.size.array; // --- Cyberpunk City Particle Animation - Dynamic Effects --- for (let i = 0; i < PARTICLE_COUNT; i++) { const i3 = i * 3; const data = particlesData[i]; const currentPos = new THREE.Vector3(positions[i3], positions[i3 + 1], positions[i3 + 2]); let targetPos = data.originalPos.clone(); if (audioSystem.isPlaying) { const audioIntensity = audioSystem.rawData.volume; const bass = audioSystem.rawData.bass; const mid = audioSystem.rawData.mid; const treble = audioSystem.rawData.treble; // 3. Enhanced Vertical Movement (Upwards-focused) if (bass > 0.6) { const verticalPulse = (Math.sin(revolutionaryTime * 10 + i * 0.1) + 1) / 2; // Map to 0-1 range targetPos.y += verticalPulse * bass * 120; // Increased multiplier } targetPos.y += audioIntensity * 20; // 2. Beam Lights if (treble > 0.8 && Math.random() < 0.001) { data.velocity.z += 50 + Math.random() * 50; // Shoot forward data.isBeam = true; } } // Physics const returnForce = targetPos.clone().sub(currentPos).multiplyScalar(0.05); data.velocity.add(returnForce).multiplyScalar(0.9); // Reset beam particles when they get too far if(currentPos.z > camera.position.z) { data.velocity.z = 0; positions[i3] = data.originalPos.x; positions[i3 + 1] = data.originalPos.y; positions[i3 + 2] = data.originalPos.z; data.isBeam = false; } positions[i3] += data.velocity.x; positions[i3 + 1] += data.velocity.y; positions[i3 + 2] += data.velocity.z; // Color and Size let finalColor; if (data.isBeam) { finalColor = new THREE.Color(0xccffff); // Bright cyan for beams } else if (audioSystem.isPlaying) { const audioIntensity = audioSystem.rawData.volume; let hue = 0.6 + (data.originalPos.y / 1000); let saturation = 0.9; let lightness = 0.5 + audioIntensity * 0.4; finalColor = new THREE.Color().setHSL(hue, saturation, Math.min(1.0, lightness)); } else { finalColor = new THREE.Color().setHSL(0.6, 0.9, 0.6); } colors[i3] = finalColor.r; colors[i3 + 1] = finalColor.g; colors[i3 + 2] = finalColor.b; let size = data.isBeam ? data.baseSize * 5 : data.baseSize; sizes[i] = Math.min(size, 25); } customCursor.position.set(mouse.x, mouse.y, 0); composer.render(); } function updateMousePosition(clientX, clientY) { const rect = renderer.domElement.getBoundingClientRect(); const x = clientX - rect.left; const y = clientY - rect.top; const vector = new THREE.Vector3((x / rect.width) * 2 - 1, -(y / rect.height) * 2 + 1, 0.5); vector.unproject(camera); const dir = vector.sub(camera.position).normalize(); const distance = -camera.position.z / dir.z; const pos = camera.position.clone().add(dir.multiplyScalar(distance)); mouse.x = pos.x; mouse.y = pos.y; } function handleRotation(clientX, clientY) { // HandControllerがアクティブな時はマウス回転を無効化 if (handController.active) return; const deltaX = clientX - previousMouse.x; const deltaY = clientY - previousMouse.y; let rotationSpeed = 0.005; if (audioSystem.isPlaying && audioSystem.rawData.mid > 0.4) { rotationSpeed *= (1 + audioSystem.rawData.mid * 4); } particleGroup.rotation.y += deltaX * rotationSpeed; particleGroup.rotation.x += deltaY * rotationSpeed; // Clamp vertical rotation to avoid flipping particleGroup.rotation.x = THREE.MathUtils.clamp(particleGroup.rotation.x, -Math.PI / 2, Math.PI / 2); previousMouse.x = clientX; previousMouse.y = clientY; } function handleZoom(delta, intensity) { // HandControllerがアクティブな時はズームを無効化 if (handController.active) return; baseCameraZ = THREE.MathUtils.clamp(baseCameraZ + delta * 2, 1000, 4000); } // イベントハンドラー function onMouseMove(event) { updateMousePosition(event.clientX, event.clientY); if (isMouseDown) handleRotation(event.clientX, event.clientY); } function onMouseDown(event) { isMouseDown = true; previousMouse.x = event.clientX; previousMouse.y = event.clientY; } function onMouseUp() { isMouseDown = false; } function onMouseWheel(event) { handleZoom(event.deltaY, Math.abs(event.deltaY) / 100); } function onTouchStart(event) { // Hand Tracking中はタッチ操作を制限(ボタン等は反応するように) if (event.target.classList.contains('sound-info')) return; event.preventDefault(); touches = Array.from(event.touches); if (touches.length === 1) { const touch = touches[0]; updateMousePosition(touch.clientX, touch.clientY); isMouseDown = true; previousMouse.x = touch.clientX; previousMouse.y = touch.clientY; } else if (touches.length === 2) { lastPinchDistance = Math.sqrt( Math.pow(touches[0].clientX - touches[1].clientX, 2) + Math.pow(touches[0].clientY - touches[1].clientY, 2) ); isMouseDown = false; } } function onTouchMove(event) { if (event.target.classList.contains('sound-info')) return; event.preventDefault(); touches = Array.from(event.touches); if (touches.length === 1) { const touch = touches[0]; updateMousePosition(touch.clientX, touch.clientY); if (isMouseDown) handleRotation(touch.clientX, touch.clientY); } else if (touches.length === 2) { const distance = Math.sqrt( Math.pow(touches[0].clientX - touches[1].clientX, 2) + Math.pow(touches[0].clientY - touches[1].clientY, 2) ); if (lastPinchDistance !== null) { handleZoom(-(distance - lastPinchDistance) * 3, 1); } lastPinchDistance = distance; } } function onTouchEnd(event) { if (event.target.classList.contains('sound-info')) return; event.preventDefault(); touches = Array.from(event.touches); if (touches.length === 0) { isMouseDown = false; lastPinchDistance = null; } else if (touches.length === 1) { updateMousePosition(touches[0].clientX, touches[0].clientY); lastPinchDistance = null; } } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); } // クリーンアップ window.addEventListener('beforeunload', () => audioSystem.stop()); window.addEventListener('DOMContentLoaded', () => { init(); animate(); const soundButton = document.getElementById('sound-info'); if (soundButton) { soundButton.addEventListener('click', toggleSound); soundButton.addEventListener('touchend', (e) => { e.preventDefault(); toggleSound(); }); } }); </script> </body> </html> </body> </html>hj"1PuQa7K62MiKCtssSLKy1kh56WWU7MtUR5SETapp3D OrditypeordnameDRiVE - Hand Tracking Ver -subTypecollectionItem royaltiesLX[{"type":"address","destination":"1AwjKNmoFkZJQbyAUSW85jvFoM8XWPDNcA","percentage":0.2}] subTypeDataL{"collectionId":"7646b921593742586f4b80745d493172495b6def14e8579f605d1161d55130b5_0","mintNumber":"5","rarityLabel":"Mythical"}|SIGMABSM"1CSc46zqPYZcjotCFpg276UpoANEeE9mG7A øA¿ã€‹P¦ÂÏÙô‚ð¶­d8Áá ØÊ¶gXCW ¶,L=zea£]í¢sþuã@kd`—é.F¨Õl0
    https://whatsonchain.com/tx/undefined

4 Outputs

Total Output:
0.00064301 BSV