1+ <!DOCTYPE html>
2+ < html lang ="en ">
3+
4+ < head >
5+ < meta charset ="UTF-8 ">
6+ < meta name ="viewport " content ="width=device-width, initial-scale=1.0 ">
7+ <!-- <title>Spin Sound</title> -->
8+ </ head >
9+
10+ < body >
11+ < button id ="butt " onclick ="onStart() " style ="width: 100px; height: 100px; "> Start</ button >
12+ <!-- <h2>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</h2> -->
13+ <!-- <span id="dbg">123</span> -->
14+ < br >
15+ < br >
16+ < video controls src ="vid.mp4 " id ="vid " width ="300 "> </ video >
17+ < script >
18+ function onStart ( ) {
19+ document . getElementById ( 'butt' ) . remove ( ) ;
20+ document . getElementById ( 'vid' ) . remove ( )
21+ document . body . innerHTML += `
22+ <div>Spin phone for sound</div>
23+ `
24+ }
25+ let lastAngle = 0 ;
26+ let totalRotation = 0 ;
27+ let lastTime = performance . now ( ) ;
28+ const audio = new Audio ( 'sound.mp3' ) ;
29+
30+ const startGyro = ( ) => {
31+ window . addEventListener ( "deviceorientation" , ( event ) => {
32+ let currentAngle = event . alpha ;
33+ let currentTime = performance . now ( ) ;
34+ let deltaTime = ( currentTime - lastTime ) / 1000 ;
35+
36+ // Prevent processing if too much time has passed
37+ if ( deltaTime > 0.1 ) {
38+ lastTime = currentTime ;
39+ return ;
40+ }
41+
42+ let deltaAngle = currentAngle - lastAngle ;
43+
44+ // Normalize angle differences to be within [-180, 180]
45+ if ( deltaAngle > 180 ) deltaAngle -= 360 ;
46+ if ( deltaAngle < - 180 ) deltaAngle += 360 ;
47+
48+ totalRotation += deltaAngle ;
49+
50+ // Debug output
51+ //document.getElementById("dbg").innerText = `dbg: cur/${currentAngle.toFixed(2)} tot/${totalRotation.toFixed(2)} del/${(deltaAngle / deltaTime).toFixed(2)}`;
52+
53+ // Reset rotation if the movement is too small
54+ if ( Math . abs ( deltaAngle ) < 4 ) {
55+ totalRotation = 0 ;
56+ return ;
57+ }
58+
59+ // Trigger sound if total rotation exceeds threshold
60+ if ( Math . abs ( totalRotation ) >= 300 ) {
61+ if ( Math . abs ( deltaAngle ) < 10 ) {
62+ totalRotation = 0 ;
63+ return ;
64+ }
65+ audio . play ( ) ;
66+ totalRotation = 0 ;
67+
68+ // Optionally add an on-screen message (commented out)
69+ // let element = document.createElement("h3");
70+ // element.innerText = `<spin! ${deltaAngle}>`;
71+ // document.body.appendChild(element);
72+ // setTimeout(() => { element.remove(); }, 10000);
73+ }
74+
75+ lastAngle = currentAngle ;
76+ lastTime = currentTime ;
77+ } ) ;
78+ } ;
79+
80+ const requestGyroPermission = ( ) => {
81+ if ( typeof DeviceOrientationEvent . requestPermission === 'function' ) {
82+ DeviceOrientationEvent . requestPermission ( ) . then ( ( state ) => {
83+ if ( state === 'granted' ) {
84+ startGyro ( ) ;
85+ } else {
86+ console . warn ( 'Permission denied for gyroscope.' ) ;
87+ //document.getElementById("dbg").innerText = 'Gyroscope permission denied.';
88+ }
89+ } ) . catch ( ( error ) => {
90+ console . error ( 'Error requesting permission:' , error ) ;
91+ //document.getElementById("dbg").innerText = 'Error requesting permission.';
92+ } ) ;
93+ } else {
94+ startGyro ( ) ; // Android or older iOS versions
95+ }
96+ } ;
97+
98+ // Call this inside a user interaction event like a button click
99+ document . getElementById ( "butt" ) . addEventListener ( "click" , requestGyroPermission ) ;
100+
101+ </ script >
102+ </ body >
103+
104+ </ html >
0 commit comments