@@ -51,7 +51,7 @@ Then just open `http://localhost:3001` in a browser.
51
51
52
52
### Javascript
53
53
54
- ``` javascript
54
+ ``` jsx
55
55
import React from " react" ;
56
56
import { ReactP5Wrapper } from " react-p5-wrapper" ;
57
57
@@ -86,7 +86,7 @@ first and only argument.
86
86
87
87
#### Option 1: Declaring a sketch using the ` P5CanvasInstance ` type
88
88
89
- ``` typescript
89
+ ``` tsx
90
90
import React from " react" ;
91
91
import { P5CanvasInstance , ReactP5Wrapper } from " react-p5-wrapper" ;
92
92
@@ -116,13 +116,13 @@ Using the `Sketch` type has one nice benefit over using `P5CanvasInstance` and
116
116
that is that the ` p5 ` argument passed to the sketch function is auto-typed as a
117
117
` P5CanvasInstance ` for you.
118
118
119
- > Sidenote :
119
+ > Side note :
120
120
>
121
- > In general it comes down to personal preference as to how you declare your
121
+ > In general, it comes down to personal preference as to how you declare your
122
122
> sketches and there is nothing wrong with using the ` P5CanvasInstance ` manually
123
123
> in a regular ` function ` declaration.
124
124
125
- ``` typescript
125
+ ``` tsx
126
126
import React from " react" ;
127
127
import { ReactP5Wrapper , Sketch } from " react-p5-wrapper" ;
128
128
@@ -157,12 +157,12 @@ below, we create a custom internal type called `MySketchProps` which is a union
157
157
type of ` SketchProps ` and a custom type which has a ` rotation ` key applied to
158
158
it.
159
159
160
- > Sidenote :
160
+ > Side note :
161
161
>
162
162
> We could also write the ` MySketchProps ` type as an interface to do exactly the
163
163
> same thing if that is to your personal preference:
164
164
>
165
- > ``` typescript
165
+ > ``` ts
166
166
> interface MySketchProps extends SketchProps {
167
167
> rotation: number ;
168
168
> }
@@ -174,7 +174,7 @@ correctly typed as a `number`.
174
174
175
175
##### Usage with the ` P5CanvasInstance ` type
176
176
177
- ` ` ` typescript
177
+ ` ` ` tsx
178
178
import React , { useEffect , useState } from " react" ;
179
179
import {
180
180
P5CanvasInstance ,
@@ -228,7 +228,7 @@ export function App() {
228
228
229
229
##### Usage with the ` Sketch ` type
230
230
231
- ``` typescript
231
+ ``` tsx
232
232
import React , { useEffect , useState } from " react" ;
233
233
import { ReactP5Wrapper , Sketch , SketchProps } from " react-p5-wrapper" ;
234
234
@@ -278,7 +278,7 @@ export function App() {
278
278
279
279
### Using abstracted setup and draw functions
280
280
281
- ``` javascript
281
+ ``` jsx
282
282
import React from " react" ;
283
283
import { ReactP5Wrapper } from " react-p5-wrapper" ;
284
284
@@ -329,7 +329,7 @@ wrapper are changed, if it is set within your sketch. This way we can render our
329
329
` ReactP5Wrapper ` component and react to component prop changes directly within
330
330
our sketches!
331
331
332
- ``` javascript
332
+ ``` jsx
333
333
import React , { useEffect , useState } from " react" ;
334
334
import { ReactP5Wrapper } from " react-p5-wrapper" ;
335
335
@@ -377,7 +377,8 @@ export function App() {
377
377
378
378
To render a component on top of the sketch, you can add it as a child of the
379
379
` ReactP5Wrapper ` component and then use the exported ` P5WrapperClassName `
380
- constant in your to style one element above the other via css.
380
+ constant in your css-in-js library of choice to style one element above the
381
+ other via css.
381
382
382
383
For instance, using [ styled components] ( https://styled-components.com ) , we could
383
384
center some text on top of our sketch like so:
@@ -430,10 +431,135 @@ export function App() {
430
431
}
431
432
```
432
433
433
- Of course you can also use any other css-in-js library or by just using simple
434
+ Of course, you can also use any other css-in-js library or by just using simple
434
435
css to achieve almost anything you can imagine just by using the wrapper class
435
436
as your root selector.
436
437
438
+ ## P5 plugins and constructors
439
+
440
+ As discussed in multiple issues such as
441
+ [ #62 ] ( https://github.com/P5-wrapper/react/issues/62 ) ,
442
+ [ #61 ] ( https://github.com/P5-wrapper/react/issues/61 ) ,
443
+ [ #11 ] ( https://github.com/P5-wrapper/react/issues/11 ) ,
444
+ [ #23 ] ( https://github.com/P5-wrapper/react/issues/23 ) and more, there seems to be
445
+ confusion as to how we can use plugins out of the box.
446
+
447
+ ### Plugins
448
+
449
+ Since P5 is being used in
450
+ [ P5 instance mode] ( https://github.com/processing/p5.js/wiki/Global-and-instance-mode )
451
+ as part of this project, P5 will not automatically load global plugins like it
452
+ usually might in global mode.
453
+
454
+ Let's say we want to use the
455
+ [ P5 sound plugin] ( https://p5js.org/reference/#/libraries/p5.sound ) in our
456
+ component, we could do the following:
457
+
458
+ ``` tsx
459
+ import * as p5 from " p5" ;
460
+ import React , { useEffect , useState } from " react" ;
461
+ import { ReactP5Wrapper , Sketch } from " react-p5-wrapper" ;
462
+
463
+ (window as any ).p5 = p5 ;
464
+
465
+ await import (" p5/lib/addons/p5.sound" );
466
+
467
+ const sketch: Sketch = p5 => {
468
+ let song: p5 .SoundFile ;
469
+ let button: p5 .Element ;
470
+
471
+ p5 .setup = () => {
472
+ p5 .createCanvas (600 , 400 , p5 .WEBGL );
473
+ p5 .background (255 , 0 , 0 );
474
+ button = p5 .createButton (" Toggle audio" );
475
+
476
+ button .mousePressed (() => {
477
+ if (! song ) {
478
+ const songUrlPath = " /piano.mp3" ;
479
+ song = p5 .loadSound (
480
+ songPath ,
481
+ () => {
482
+ song .play ();
483
+ },
484
+ () => {
485
+ console .error (
486
+ ` Could not load the requested sound file ${songPath } `
487
+ );
488
+ }
489
+ );
490
+ return ;
491
+ }
492
+
493
+ if (! song .isPlaying ()) {
494
+ song .play ();
495
+ return ;
496
+ }
497
+
498
+ song .pause ();
499
+ });
500
+ };
501
+
502
+ p5 .draw = () => {
503
+ p5 .background (250 );
504
+ p5 .normalMaterial ();
505
+ p5 .push ();
506
+ p5 .rotateZ (p5 .frameCount * 0.01 );
507
+ p5 .rotateX (p5 .frameCount * 0.01 );
508
+ p5 .rotateY (p5 .frameCount * 0.01 );
509
+ p5 .plane (100 );
510
+ p5 .pop ();
511
+ };
512
+ };
513
+
514
+ export default function App() {
515
+ return <ReactP5Wrapper sketch = { sketch } />;
516
+ }
517
+ ```
518
+
519
+ In this Typescript + React example, we can see a few key things.
520
+
521
+ - Firstly we need to set ` p5 ` on the ` window ` object manually. This is because
522
+ ` p5.sound ` requires that it be executed client side only AND that ` p5 ` be
523
+ available BEFORE it is imported into the global (` window ` ) scope.
524
+ - Secondly, we ensure that audio is played after a user action, in our case this
525
+ happens on a button click. This is because in some browsers, without waiting
526
+ for a user interaction before playing audio, the audio will be blocked by the
527
+ browser from playing at all.
528
+ - Thirdly and relevant especially to Safari users, Safari blocks audio from all
529
+ tabs by default, you will need to manually change this setting in your Safari
530
+ settings. This could affect other browsers but sadly this is a browser
531
+ decision and until [ P5 Sound] ( https://github.com/processing/p5.js-sound ) is
532
+ updated to support newer audio APIs and browser requirements. This could
533
+ happen at anytime in other places and is a
534
+ [ P5 Sound] ( https://github.com/processing/p5.js-sound ) issue most generally
535
+ because it does not ask for permissions by default, even though browsers have
536
+ been requiring it for some time.
537
+
538
+ > ** Note:** The above example requires support for
539
+ > [ top level await] ( https://caniuse.com/mdn-javascript_operators_await_top_level ) ,
540
+ > [ dynamic import statements] ( https://caniuse.com/es6-module-dynamic-import ) and
541
+ > [ the stream API] ( https://caniuse.com/stream ) to be supported in your browser.
542
+ > Furthermore, [ the stream API] ( https://caniuse.com/stream ) built into the
543
+ > browser requires that HTTPS is used to ensure secure data transmission.
544
+
545
+ ### Constructors
546
+
547
+ To access P5 constructors such as ` p5.Vector ` or ` p5.Envelope ` , you need to use
548
+ the instance mode syntax instead. For example:
549
+
550
+ | Constructor | Global mode accessor | Instance mode accessor |
551
+ | ----------- | -------------------- | ----------------------- |
552
+ | Vector | p5.Vector | p5.constructor.Vector |
553
+ | Envelope | p5.Envelope | p5.constructor.Envelope |
554
+
555
+ So now that we know this, let's imagine we want a random 2D Vector instance. In
556
+ our ` sketch ` function we would simply call ` p5.constructor.Vector.random2D() `
557
+ instead of ` p5.Vector.random2D() ` . This is because of how the
558
+ [ P5 instance mode] ( https://github.com/processing/p5.js/wiki/Global-and-instance-mode )
559
+ was implemented by the P5 team. While I am not sure why they decided to change
560
+ the API for instance mode specifically, it is still quite simple to use the
561
+ constructs we are used to without much extra work involved.
562
+
437
563
## Development
438
564
439
565
** NOTE:** The source code for the component is in the ` src ` directory.
0 commit comments