p5-phone 1.6.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +299 -10
  2. package/dist/p5-phone.js +638 -60
  3. package/dist/p5-phone.min.js +2 -2
  4. package/examples/Phone Sensor Examples/microphone/01_mic_level/index.html +2 -2
  5. package/examples/Phone Sensor Examples/microphone/01_mic_level/sketch.js +3 -3
  6. package/examples/Phone Sensor Examples/microphone/02_speech_recognition/README.md +25 -29
  7. package/examples/Phone Sensor Examples/microphone/02_speech_recognition/index.html +2 -2
  8. package/examples/Phone Sensor Examples/microphone/02_speech_recognition/sketch.js +2 -2
  9. package/examples/Phone Sensor Examples/movement/01_orientation_basic/index.html +3 -2
  10. package/examples/Phone Sensor Examples/movement/01_orientation_basic/sketch.js +3 -3
  11. package/examples/Phone Sensor Examples/movement/02_rotational_velocity/index.html +3 -2
  12. package/examples/Phone Sensor Examples/movement/02_rotational_velocity/sketch.js +3 -3
  13. package/examples/Phone Sensor Examples/movement/03_acceleration/index.html +3 -2
  14. package/examples/Phone Sensor Examples/movement/03_acceleration/sketch.js +3 -3
  15. package/examples/Phone Sensor Examples/sound/01_dual_audio/index.html +2 -1
  16. package/examples/Phone Sensor Examples/sound/01_dual_audio/sketch.js +5 -5
  17. package/examples/Phone Sensor Examples/sound/02_volume_touches/index.html +2 -1
  18. package/examples/Phone Sensor Examples/sound/02_volume_touches/sketch.js +7 -7
  19. package/examples/Phone Sensor Examples/touch/01_touch_basic/index.html +2 -1
  20. package/examples/Phone Sensor Examples/touch/01_touch_basic/sketch.js +4 -4
  21. package/examples/Phone Sensor Examples/touch/02_touch_zones/index.html +2 -1
  22. package/examples/Phone Sensor Examples/touch/02_touch_zones/sketch.js +3 -3
  23. package/examples/Phone Sensor Examples/touch/03_touch_count/index.html +2 -1
  24. package/examples/Phone Sensor Examples/touch/03_touch_count/sketch.js +3 -3
  25. package/examples/Phone Sensor Examples/touch/04_touch_distance/index.html +2 -1
  26. package/examples/Phone Sensor Examples/touch/04_touch_distance/sketch.js +3 -3
  27. package/examples/Phone Sensor Examples/touch/05_touch_angle/index.html +2 -1
  28. package/examples/Phone Sensor Examples/touch/05_touch_angle/sketch.js +3 -3
  29. package/examples/Phone Sensor Examples/vibration/01_haptic_feedback/index.html +2 -1
  30. package/examples/Phone Sensor Examples/vibration/01_haptic_feedback/sketch.js +3 -3
  31. package/examples/Phone Sensor Examples - Minimal/microphone/01_mic_level/index.html +3 -3
  32. package/examples/Phone Sensor Examples - Minimal/movement/01_orientation_basic/index.html +2 -2
  33. package/examples/Phone Sensor Examples - Minimal/movement/02_rotational_velocity/index.html +2 -2
  34. package/examples/Phone Sensor Examples - Minimal/movement/03_acceleration/index.html +2 -2
  35. package/examples/Phone Sensor Examples - Minimal/sound/01_sound_basic/index.html +3 -3
  36. package/examples/Phone Sensor Examples - Minimal/sound/01_sound_basic/sketch.js +2 -2
  37. package/examples/Phone Sensor Examples - Minimal/sound/02_sound_amplitude/index.html +3 -3
  38. package/examples/Phone Sensor Examples - Minimal/sound/02_sound_amplitude/sketch.js +2 -2
  39. package/examples/Phone Sensor Examples - Minimal/touch/01_touch_basic/index.html +2 -2
  40. package/examples/Phone Sensor Examples - Minimal/touch/01_touch_basic/sketch.js +2 -2
  41. package/examples/Phone Sensor Examples - Minimal/touch/02_touch_zones/index.html +2 -2
  42. package/examples/Phone Sensor Examples - Minimal/touch/02_touch_zones/sketch.js +2 -2
  43. package/examples/Phone Sensor Examples - Minimal/touch/03_touch_count/index.html +2 -2
  44. package/examples/Phone Sensor Examples - Minimal/touch/03_touch_count/sketch.js +2 -2
  45. package/examples/Phone Sensor Examples - Minimal/touch/04_touch_distance/index.html +2 -2
  46. package/examples/Phone Sensor Examples - Minimal/touch/04_touch_distance/sketch.js +2 -2
  47. package/examples/Phone Sensor Examples - Minimal/touch/05_touch_angle/index.html +2 -2
  48. package/examples/Phone Sensor Examples - Minimal/touch/05_touch_angle/sketch.js +2 -2
  49. package/examples/Phone Sensor Examples - Minimal/vibration/01_haptic_feedback/index.html +2 -2
  50. package/examples/Phone Sensor Examples - Minimal/vibration/01_haptic_feedback/sketch.js +2 -2
  51. package/examples/Phone and Gif/collision/index.html +2 -2
  52. package/examples/Phone and Gif/collision/sketch.js +3 -3
  53. package/examples/Phone and Gif/fetch/index.html +2 -2
  54. package/examples/Phone and Gif/fetch/sketch.js +3 -3
  55. package/examples/Phone and Gif/fly/index.html +2 -2
  56. package/examples/Phone and Gif/roll/index.html +2 -2
  57. package/examples/Phone and Gif/roll/sketch.js +3 -3
  58. package/examples/UIStyles/banner-style/index.html +17 -0
  59. package/examples/UIStyles/banner-style/sketch.js +35 -0
  60. package/examples/UIStyles/canvas-style/index.html +17 -0
  61. package/examples/UIStyles/canvas-style/sketch.js +26 -0
  62. package/examples/UIStyles/custom-element/index.html +33 -0
  63. package/examples/UIStyles/custom-element/sketch.js +35 -0
  64. package/examples/UXcompare/button-vs-movement/index.html +3 -2
  65. package/examples/UXcompare/button-vs-orientation/index.html +3 -2
  66. package/examples/UXcompare/button-vs-shake/index.html +3 -2
  67. package/examples/UXcompare/gyroscope-demo/index.html +3 -2
  68. package/examples/UXcompare/microphone-demo/index.html +4 -3
  69. package/examples/UXcompare/slider-vs-angle/index.html +3 -2
  70. package/examples/UXcompare/slider-vs-angle/sketch.js +3 -3
  71. package/examples/UXcompare/slider-vs-distance/index.html +3 -2
  72. package/examples/UXcompare/slider-vs-distance/sketch.js +3 -3
  73. package/examples/UXcompare/slider-vs-microphone/index.html +4 -3
  74. package/examples/UXcompare/slider-vs-microphone/sketch.js +3 -3
  75. package/examples/UXcompare/slider-vs-touches/index.html +3 -2
  76. package/examples/UXcompare/slider-vs-touches/sketch.js +3 -3
  77. package/examples/UXcompare/sliders-vs-acceleration/index.html +3 -2
  78. package/examples/UXcompare/sliders-vs-acceleration/sketch.js +3 -3
  79. package/examples/UXcompare/sliders-vs-rotation/index.html +3 -2
  80. package/examples/UXcompare/sliders-vs-rotation/sketch.js +3 -3
  81. package/examples/blankTemplate/index.html +3 -2
  82. package/examples/blankTemplate/sketch.js +2 -2
  83. package/examples/homepage/index.html +42 -13
  84. package/examples/ml5/Gaze_detector_class/index.html +2 -1
  85. package/examples/ml5/PHONE_BodyPose_two_points/index.html +2 -1
  86. package/examples/ml5/PHONE_FaceMesh_two_points/index.html +2 -1
  87. package/examples/ml5/PHONE_HandPose_two_points/index.html +2 -1
  88. package/package.json +1 -1
  89. package/src/p5-phone.js +638 -60
package/README.md CHANGED
@@ -17,9 +17,11 @@ That's where this library comes in:
17
17
 
18
18
  This library simplifies access to the following p5.js mobile sensor and audio commands:
19
19
 
20
- **Touch Events:**
21
- - [`touchStarted()`](https://p5js.org/reference/p5/touchStarted/) - Called when a touch begins
22
- - [`touchEnded()`](https://p5js.org/reference/p5/touchEnded/) - Called when a touch ends
20
+ **Touch/Pointer Events:**
21
+ - [`mousePressed()`](https://p5js.org/reference/p5/mousePressed/) - Called when a press/touch begins (works for both mouse and touch in p5.js 1.x and 2.0)
22
+ - [`mouseReleased()`](https://p5js.org/reference/p5/mouseReleased/) - Called when a press/touch ends (works for both mouse and touch in p5.js 1.x and 2.0)
23
+ - [`touchStarted()`](https://p5js.org/reference/p5/touchStarted/) - Called when a touch begins (p5.js 1.x only)
24
+ - [`touchEnded()`](https://p5js.org/reference/p5/touchEnded/) - Called when a touch ends (p5.js 1.x only)
23
25
 
24
26
  **Device Motion & Orientation:**
25
27
  - [`rotationX`](https://p5js.org/reference/p5/rotationX/) - Device tilt forward/backward
@@ -45,10 +47,31 @@ This library simplifies access to the following p5.js mobile sensor and audio co
45
47
  - Safari 13+
46
48
  - Firefox 75+
47
49
 
50
+ ## p5.js Version Compatibility
51
+
52
+ p5-phone supports both **p5.js 1.x** and **p5.js 2.0+**.
53
+
54
+ | Feature | p5.js 1.x | p5.js 2.0+ |
55
+ |---------|-----------|------------|
56
+ | Permission UI (Tap/Button/Canvas/Banner/Custom) | ✅ | ✅ |
57
+ | Motion sensors (rotationX/Y/Z, accelerationX/Y/Z) | ✅ | ✅ |
58
+ | Microphone / Speech / Sound | ✅ | ✅ |
59
+ | Camera (PhoneCamera) | ✅ | ✅ |
60
+ | Vibration | ✅ | ✅ |
61
+ | Debug console | ✅ | ✅ |
62
+ | lockGestures() | ✅ | ✅ |
63
+ | `touchStarted()` / `touchEnded()` | ✅ | ❌ Use `mousePressed()` / `mouseReleased()` |
64
+ | `p5.registerAddon()` | ❌ | ✅ (auto-detected) |
65
+
66
+ **Key change in p5.js 2.0:** Touch-specific callbacks (`touchStarted`, `touchMoved`, `touchEnded`) are no longer dispatched. The unified Pointer API routes all input (mouse + touch) through `mousePressed()`, `mouseDragged()`, and `mouseReleased()`. These mouse callbacks work in **both** p5.js 1.x and 2.0, so use them for forward-compatible code.
67
+
68
+ p5-phone automatically detects the p5.js version and adjusts its internal touch override behavior accordingly. No configuration needed.
69
+
48
70
  ## Table of Contents
49
71
 
50
72
  - [Link for Interactive Examples](#link-for-interactive-examples)
51
73
  - [Browser Compatibility](#browser-compatibility)
74
+ - [p5.js Version Compatibility](#p5js-version-compatibility)
52
75
  - [CDN (Recommended)](#cdn-recommended)
53
76
  - [Basic Setup](#basic-setup)
54
77
  - [Index HTML](#index-html)
@@ -60,17 +83,27 @@ This library simplifies access to the following p5.js mobile sensor and audio co
60
83
  - [Motion Sensor Activation](#motion-sensor-activation)
61
84
  - [Microphone Activation](#microphone-activation)
62
85
  - [Sound Output Activation](#sound-output-activation)
86
+ - [Speech Recognition Activation](#speech-recognition-activation)
87
+ - [Combined Activation](#combined-activation)
63
88
  - [Vibration Motor (Android Only)](#vibration-motor-android-only)
89
+ - [PhoneCamera (ML5 Integration)](#phonecamera-ml5-integration)
64
90
  - [Debug System](#debug-system)
91
+ - [Permission UI Styles](#permission-ui-styles)
92
+ - [Tap (Full-Screen Overlay)](#tap-full-screen-overlay)
93
+ - [Button (Centered Button)](#button-centered-button)
94
+ - [Canvas (First Touch)](#canvas-first-touch)
95
+ - [Banner (Top/Bottom Bar)](#banner-topbottom-bar)
96
+ - [Custom Element Binding](#custom-element-binding)
97
+ - [Troubleshooting / FAQ](#troubleshooting--faq)
65
98
 
66
99
  ### CDN (Recommended)
67
100
 
68
101
  ```html
69
102
  <!-- Minified version (recommended) -->
70
- <script src="https://cdn.jsdelivr.net/npm/p5-phone@1.6.3/dist/p5-phone.min.js"></script>
103
+ <script src="https://cdn.jsdelivr.net/npm/p5-phone@1.8.0/dist/p5-phone.min.js"></script>
71
104
 
72
105
  <!-- Development version (larger, with comments) -->
73
- <!-- <script src="https://cdn.jsdelivr.net/npm/p5-phone@1.6.3/dist/p5-phone.js"></script> -->
106
+ <!-- <script src="https://cdn.jsdelivr.net/npm/p5-phone@1.8.0/dist/p5-phone.js"></script> -->
74
107
  ```
75
108
 
76
109
  ### Basic Setup
@@ -96,9 +129,10 @@ This library simplifies access to the following p5.js mobile sensor and audio co
96
129
 
97
130
  <!-- Load p5.js library -->
98
131
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.10/p5.min.js"></script>
132
+ <!-- For p5.js 2.0: <script src="https://cdn.jsdelivr.net/npm/p5@2/lib/p5.min.js"></script> -->
99
133
 
100
134
  <!-- Load p5-phone library -->
101
- <script src="https://cdn.jsdelivr.net/npm/p5-phone@1.6.3/dist/p5-phone.min.js"></script>
135
+ <script src="https://cdn.jsdelivr.net/npm/p5-phone@1.8.0/dist/p5-phone.min.js"></script>
102
136
 
103
137
  </head>
104
138
  <body>
@@ -163,11 +197,12 @@ function draw() {
163
197
  }
164
198
 
165
199
  // Prevent default touch behavior (optional but recommended)
166
- function touchStarted() {
200
+ // Use mousePressed/mouseReleased — works in both p5.js 1.x and 2.0
201
+ function mousePressed() {
167
202
  return false;
168
203
  }
169
204
 
170
- function touchEnded() {
205
+ function mouseReleased() {
171
206
  return false;
172
207
  }
173
208
  ```
@@ -192,19 +227,51 @@ enableMicButton(text) // Button-based microphone activation
192
227
  enableSoundTap(message) // Tap anywhere to enable sound playback
193
228
  enableSoundButton(text) // Button-based sound activation
194
229
 
230
+ // Speech recognition activation (Web Speech API)
231
+ enableSpeechTap(message) // Tap anywhere to enable speech
232
+ enableSpeechButton(text) // Button-based speech activation
233
+
234
+ // Combined activation (motion + microphone)
235
+ enableAllTap(message) // Tap anywhere to enable both
236
+ enableAllButton(text) // Button-based combined activation
237
+
195
238
  // Vibration motor (Android only)
196
239
  enableVibrationTap(message) // Tap anywhere to enable vibration
197
240
  enableVibrationButton(text) // Button-based vibration activation
198
241
  vibrate(pattern) // Trigger vibration (duration or pattern array)
199
242
  stopVibration() // Stop any ongoing vibration
200
243
 
244
+ // Camera (ML5 integration)
245
+ createPhoneCamera(active, mirror, mode) // Create camera instance
246
+ enableCameraTap(message) // Tap to enable camera
247
+ enableCameraButton(text) // Button-based camera activation
248
+
249
+ // --- Alternative Permission UI Styles (v1.7.0) ---
250
+
251
+ // Canvas-first-touch — permissions fire on first canvas interaction
252
+ enableGyroCanvas(message) // Also: enableMicCanvas, enableSoundCanvas,
253
+ // enableSpeechCanvas, enableVibrationCanvas,
254
+ // enableAllCanvas, enableCameraCanvas
255
+
256
+ // Banner — slim notification bar at top or bottom of screen
257
+ enableGyroBanner(message, position) // position: 'top' or 'bottom'
258
+ // Also: enableMicBanner, enableSoundBanner,
259
+ // enableSpeechBanner, enableVibrationBanner,
260
+ // enableAllBanner, enableCameraBanner
261
+
262
+ // Custom element binding — attach to your own DOM element
263
+ enableGyroOn(selector) // e.g., enableGyroOn('#my-button')
264
+ // Also: enableMicOn, enableSoundOn, enableSpeechOn,
265
+ // enableVibrationOn, enableAllOn, enableCameraOn
266
+
201
267
  // Status variables (check these in your code)
202
268
  window.sensorsEnabled // Boolean: true when motion sensors are active
203
269
  window.micEnabled // Boolean: true when microphone is active
204
270
  window.soundEnabled // Boolean: true when sound output is active
271
+ window.speechEnabled // Boolean: true when speech recognition is active
205
272
  window.vibrationEnabled // Boolean: true when vibration is available (Android only)
206
273
 
207
- // Debug system (enhanced in v1.4.0)
274
+ // Debug system
208
275
  showDebug() // Show on-screen debug panel with automatic error catching
209
276
  hideDebug() // Hide debug panel
210
277
  toggleDebug() // Toggle panel visibility
@@ -233,6 +300,7 @@ this.enableGyroTap('Tap to start');
233
300
  - `window.sensorsEnabled` - Boolean indicating if motion sensors are active
234
301
  - `window.micEnabled` - Boolean indicating if microphone is active
235
302
  - `window.soundEnabled` - Boolean indicating if sound output is active
303
+ - `window.speechEnabled` - Boolean indicating if speech recognition is active
236
304
  - `window.vibrationEnabled` - Boolean indicating if vibration is available (Android only)
237
305
 
238
306
  **Usage:**
@@ -537,7 +605,7 @@ function mousePressed() {
537
605
  }
538
606
 
539
607
  // Touch zones with different haptic patterns
540
- function touchStarted() {
608
+ function mousePressed() {
541
609
  if (window.vibrationEnabled) {
542
610
  if (mouseX < width/2) {
543
611
  vibrate(50); // Left side - short pulse
@@ -570,6 +638,80 @@ function gameOver() {
570
638
  - Don't overuse - vibration can quickly drain battery
571
639
  - Test on Android devices as iOS doesn't support vibration
572
640
 
641
+ ### Speech Recognition Activation
642
+
643
+ **Purpose:** Enable the Web Speech API for voice input and speech-to-text in mobile browsers.
644
+
645
+ **Important:** This does NOT create a `p5.AudioIn` object — it only activates the audio context needed for the Web Speech API. You must create your own `p5.SpeechRec` object after enabling.
646
+
647
+ **Commands:**
648
+ - `enableSpeechTap(message)` - Tap anywhere on screen to enable speech recognition
649
+ - `enableSpeechButton(text)` - Creates a button with custom text to enable speech
650
+
651
+ **Usage:**
652
+ ```javascript
653
+ let speechRec;
654
+
655
+ function setup() {
656
+ createCanvas(windowWidth, windowHeight);
657
+
658
+ // Enable speech recognition
659
+ enableSpeechTap('Tap to enable speech recognition');
660
+ }
661
+
662
+ // Use userSetupComplete() to know when permissions are ready
663
+ function userSetupComplete() {
664
+ if (window.speechEnabled) {
665
+ speechRec = new p5.SpeechRec('en-US');
666
+ speechRec.continuous = true;
667
+ speechRec.interimResults = true;
668
+ speechRec.onResult = gotSpeech;
669
+ speechRec.start();
670
+ }
671
+ }
672
+
673
+ function gotSpeech() {
674
+ if (speechRec.resultValue) {
675
+ debug('You said:', speechRec.resultString);
676
+ }
677
+ }
678
+ ```
679
+
680
+ ### Combined Activation
681
+
682
+ **Purpose:** Enable both motion sensors and microphone with a single permission prompt, reducing the number of taps required.
683
+
684
+ **Commands:**
685
+ - `enableAllTap(message)` - Tap anywhere to enable motion sensors + microphone
686
+ - `enableAllButton(text)` - Button-based combined activation
687
+
688
+ **Usage:**
689
+ ```javascript
690
+ let mic;
691
+
692
+ function setup() {
693
+ createCanvas(windowWidth, windowHeight);
694
+ mic = new p5.AudioIn();
695
+ lockGestures();
696
+
697
+ // One tap enables both sensors and microphone
698
+ enableAllTap('Tap to enable sensors & microphone');
699
+ }
700
+
701
+ function draw() {
702
+ background(220);
703
+
704
+ if (window.sensorsEnabled) {
705
+ circle(width/2 + rotationY * 3, height/2 + rotationX * 3, 50);
706
+ }
707
+
708
+ if (window.micEnabled) {
709
+ let level = mic.getLevel();
710
+ rect(10, 10, level * 200, 20);
711
+ }
712
+ }
713
+ ```
714
+
573
715
  ### PhoneCamera (ML5 Integration)
574
716
 
575
717
  **Purpose:** Simplified camera access optimized for ML5.js machine learning models (FaceMesh, HandPose, BodyPose, etc.). Handles camera initialization, coordinate mapping, mirroring, and display modes automatically.
@@ -768,4 +910,151 @@ debug("Touch points:", touches);
768
910
  debug({rotation: rotationX, acceleration: accelerationX});
769
911
  ```
770
912
 
913
+ ---
914
+
915
+ ## Permission UI Styles
916
+
917
+ Beyond the default **Tap** and **Button** styles, p5-phone v1.7.0 provides three additional ways to present permission prompts. Each permission type (sensors, microphone, speech, all, camera) has all five variants.
918
+
919
+ ### Canvas Style
920
+
921
+ The canvas displays a centered message until the user taps. Great for "full-screen tap to start" experiences where you want the canvas to feel like a splash screen.
922
+
923
+ **Commands:**
924
+ - `enableSensorCanvas(message)`
925
+ - `enableMicCanvas(message)`
926
+ - `enableSpeechCanvas(message)`
927
+ - `enableAllCanvas(message)`
928
+ - `enableCameraCanvas(message)`
929
+
930
+ **Usage:**
931
+ ```javascript
932
+ function setup() {
933
+ createCanvas(windowWidth, windowHeight);
934
+ lockGestures();
935
+ enableSensorCanvas('Tap canvas to begin');
936
+ }
937
+
938
+ function draw() {
939
+ if (!window.sensorsEnabled) return;
940
+ background(220);
941
+ circle(width/2 + rotationY * 3, height/2 + rotationX * 3, 50);
942
+ }
943
+ ```
944
+
945
+ ### Banner Style
946
+
947
+ A styled banner slides in from the top of the screen with an animated entrance. After the user taps, the banner slides away and permissions are activated. Ideal when you want to keep your canvas visible underneath the prompt.
948
+
949
+ **Commands:**
950
+ - `enableSensorBanner(message)`
951
+ - `enableMicBanner(message)`
952
+ - `enableSpeechBanner(message)`
953
+ - `enableAllBanner(message)`
954
+ - `enableCameraBanner(message)`
955
+
956
+ **Usage:**
957
+ ```javascript
958
+ function setup() {
959
+ createCanvas(windowWidth, windowHeight);
960
+ lockGestures();
961
+ enableSensorBanner('Tap here to enable motion sensors');
962
+ }
963
+
964
+ function draw() {
965
+ background(220);
966
+ if (window.sensorsEnabled) {
967
+ text('Rotation: ' + rotationX.toFixed(1), 20, 60);
968
+ }
969
+ }
970
+ ```
971
+
972
+ ### Custom Element Style
973
+
974
+ Bind the permission activation to any existing HTML element on the page using a CSS selector. This gives you full control over the look and placement of the trigger. The element is hidden after successful activation.
975
+
976
+ **Commands:**
977
+ - `enableSensorOn(selector)`
978
+ - `enableMicOn(selector)`
979
+ - `enableSpeechOn(selector)`
980
+ - `enableAllOn(selector)`
981
+ - `enableCameraOn(selector)`
982
+
983
+ **Usage (HTML):**
984
+ ```html
985
+ <button id="start-btn" style="font-size:24px; padding:20px;">
986
+ Start Experience
987
+ </button>
988
+ ```
989
+
990
+ **Usage (sketch.js):**
991
+ ```javascript
992
+ function setup() {
993
+ createCanvas(windowWidth, windowHeight);
994
+ lockGestures();
995
+ enableAllOn('#start-btn');
996
+ }
997
+
998
+ function draw() {
999
+ if (!window.sensorsEnabled) return;
1000
+ background(220);
1001
+ circle(width/2 + rotationY * 3, height/2 + rotationX * 3, 50);
1002
+ }
1003
+ ```
1004
+
1005
+ ### Which Style Should I Use?
1006
+
1007
+ | Style | Best For | How It Works |
1008
+ |-------|----------|-------------|
1009
+ | **Tap** | Quick prototypes | Full-screen transparent overlay |
1010
+ | **Button** | Clear UI | Auto-generated styled button |
1011
+ | **Canvas** | Splash screens | Message drawn on the p5 canvas |
1012
+ | **Banner** | Polished apps | Animated slide-in banner |
1013
+ | **Custom** | Custom designs | Bind to your own HTML element |
1014
+
1015
+ ---
1016
+
1017
+ ## Troubleshooting / FAQ
1018
+
1019
+ ### Why do I have to tap before sensors work?
1020
+
1021
+ iOS Safari requires a **user gesture** (tap, click) before granting access to motion sensors and the microphone. This is a browser security requirement — it cannot be bypassed. Android does not have this restriction, but the tap/button still works on Android (it's a no-op).
1022
+
1023
+ ### My sketch works on desktop but not on my phone
1024
+
1025
+ 1. Make sure you're serving over **HTTPS** — motion sensors and microphone are blocked on insecure origins.
1026
+ 2. Check that you've called one of the `enable...` functions in `setup()`.
1027
+ 3. On iOS, check Settings → Safari → Motion & Orientation Access is enabled.
1028
+
1029
+ ### The debug console isn't showing
1030
+
1031
+ Make sure you're calling `enableConsole()` in your sketch. The console overlay appears at the bottom of the screen. You can use `debug()`, `debugWarn()`, and `debugError()` to log to it.
1032
+
1033
+ ### How do I know when permissions are ready?
1034
+
1035
+ Define a `userSetupComplete()` function — it's called automatically after the user taps and all requested permissions have been granted:
1036
+
1037
+ ```javascript
1038
+ function userSetupComplete() {
1039
+ debug('All permissions granted!');
1040
+ debug('Sensors:', window.sensorsEnabled);
1041
+ debug('Mic:', window.micEnabled);
1042
+ }
1043
+ ```
1044
+
1045
+ You can also check the status variables at any time:
1046
+ - `window.sensorsEnabled`
1047
+ - `window.micEnabled`
1048
+ - `window.speechEnabled`
1049
+
1050
+ ### Camera feed is blank or not loading
1051
+
1052
+ 1. Ensure your page is served over **HTTPS**.
1053
+ 2. Check that you're using `new PhoneCamera(this)` in your sketch.
1054
+ 3. Grant camera permission in the browser when prompted.
1055
+ 4. Some iOS versions require the user to explicitly allow camera access in Settings → Safari → Camera.
1056
+
1057
+ ### Vibration isn't working on iOS
1058
+
1059
+ The Vibration API is **not supported on iOS**. Use `navigator.vibrate` only as an enhancement for Android devices. Check `'vibrate' in navigator` before calling it.
771
1060