@@ -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,136 @@ 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
+ [ #11 ] ( https://github.com/P5-wrapper/react/issues/11 ) ,
442
+ [ #23 ] ( https://github.com/P5-wrapper/react/issues/23 ) ,
443
+ [ #61 ] ( https://github.com/P5-wrapper/react/issues/61 ) and
444
+ [ #62 ] ( https://github.com/P5-wrapper/react/issues/62 ) , there seems to be
445
+ confusion as to how we can use P5 plugins and constructors out of the box. This
446
+ section aims to clarify these!
447
+
448
+ ### Plugins
449
+
450
+ Since P5 is being used in
451
+ [ P5 instance mode] ( https://github.com/processing/p5.js/wiki/Global-and-instance-mode )
452
+ as part of this project, P5 will not automatically load global plugins like it
453
+ usually might in global mode.
454
+
455
+ Let's say we want to use the
456
+ [ P5 sound plugin] ( https://p5js.org/reference/#/libraries/p5.sound ) in our
457
+ component, we could do the following:
458
+
459
+ ``` tsx
460
+ import * as p5 from " p5" ;
461
+ import React , { useEffect , useState } from " react" ;
462
+ import { ReactP5Wrapper , Sketch } from " react-p5-wrapper" ;
463
+
464
+ (window as any ).p5 = p5 ;
465
+
466
+ await import (" p5/lib/addons/p5.sound" );
467
+
468
+ const sketch: Sketch = p5 => {
469
+ let song: p5 .SoundFile ;
470
+ let button: p5 .Element ;
471
+
472
+ p5 .setup = () => {
473
+ p5 .createCanvas (600 , 400 , p5 .WEBGL );
474
+ p5 .background (255 , 0 , 0 );
475
+ button = p5 .createButton (" Toggle audio" );
476
+
477
+ button .mousePressed (() => {
478
+ if (! song ) {
479
+ const songUrlPath = " /piano.mp3" ;
480
+ song = p5 .loadSound (
481
+ songPath ,
482
+ () => {
483
+ song .play ();
484
+ },
485
+ () => {
486
+ console .error (
487
+ ` Could not load the requested sound file ${songPath } `
488
+ );
489
+ }
490
+ );
491
+ return ;
492
+ }
493
+
494
+ if (! song .isPlaying ()) {
495
+ song .play ();
496
+ return ;
497
+ }
498
+
499
+ song .pause ();
500
+ });
501
+ };
502
+
503
+ p5 .draw = () => {
504
+ p5 .background (250 );
505
+ p5 .normalMaterial ();
506
+ p5 .push ();
507
+ p5 .rotateZ (p5 .frameCount * 0.01 );
508
+ p5 .rotateX (p5 .frameCount * 0.01 );
509
+ p5 .rotateY (p5 .frameCount * 0.01 );
510
+ p5 .plane (100 );
511
+ p5 .pop ();
512
+ };
513
+ };
514
+
515
+ export default function App() {
516
+ return <ReactP5Wrapper sketch = { sketch } />;
517
+ }
518
+ ```
519
+
520
+ In this Typescript + React example, we can see a few key things.
521
+
522
+ - Firstly we need to set ` p5 ` on the ` window ` object manually. This is because
523
+ ` p5.sound ` requires that it be executed client side only AND that ` p5 ` be
524
+ available BEFORE it is imported into the global (` window ` ) scope.
525
+ - Secondly, we ensure that audio is played after a user action, in our case this
526
+ happens on a button click. This is because in some browsers, without waiting
527
+ for a user interaction before playing audio, the audio will be blocked by the
528
+ browser from playing at all.
529
+ - Thirdly and relevant especially to Safari users, Safari blocks audio from all
530
+ tabs by default, you will need to manually change this setting in your Safari
531
+ settings. This could affect other browsers but sadly this is a browser
532
+ decision and until [ P5 Sound] ( https://github.com/processing/p5.js-sound ) is
533
+ updated to support newer audio APIs and browser requirements. This could
534
+ happen at anytime in other places and is a
535
+ [ P5 Sound] ( https://github.com/processing/p5.js-sound ) issue most generally
536
+ because it does not ask for permissions by default, even though browsers have
537
+ been requiring it for some time.
538
+
539
+ > ** Note:** The above example requires support for
540
+ > [ top level await] ( https://caniuse.com/mdn-javascript_operators_await_top_level ) ,
541
+ > [ dynamic import statements] ( https://caniuse.com/es6-module-dynamic-import ) and
542
+ > [ the stream API] ( https://caniuse.com/stream ) to be supported in your browser.
543
+ > Furthermore, [ the stream API] ( https://caniuse.com/stream ) built into the
544
+ > browser requires that HTTPS is used to ensure secure data transmission.
545
+
546
+ ### Constructors
547
+
548
+ To access P5 constructors such as ` p5.Vector ` or ` p5.Envelope ` , you need to use
549
+ the instance mode syntax instead. For example:
550
+
551
+ | Constructor | Global mode accessor | Instance mode accessor |
552
+ | ----------- | -------------------- | ----------------------- |
553
+ | Vector | p5.Vector | p5.constructor.Vector |
554
+ | Envelope | p5.Envelope | p5.constructor.Envelope |
555
+
556
+ So now that we know this, let's imagine we want a random 2D Vector instance. In
557
+ our ` sketch ` function we would simply call ` p5.constructor.Vector.random2D() `
558
+ instead of ` p5.Vector.random2D() ` . This is because of how the
559
+ [ P5 instance mode] ( https://github.com/processing/p5.js/wiki/Global-and-instance-mode )
560
+ was implemented by the P5 team. While I am not sure why they decided to change
561
+ the API for instance mode specifically, it is still quite simple to use the
562
+ constructs we are used to without much extra work involved.
563
+
437
564
## Development
438
565
439
566
** NOTE:** The source code for the component is in the ` src ` directory.
0 commit comments