@@ -51,7 +51,7 @@ Then just open `http://localhost:3001` in a browser.
5151
5252### Javascript
5353
54- ``` javascript
54+ ``` jsx
5555import React from " react" ;
5656import { ReactP5Wrapper } from " react-p5-wrapper" ;
5757
@@ -86,7 +86,7 @@ first and only argument.
8686
8787#### Option 1: Declaring a sketch using the ` P5CanvasInstance ` type
8888
89- ``` typescript
89+ ``` tsx
9090import React from " react" ;
9191import { P5CanvasInstance , ReactP5Wrapper } from " react-p5-wrapper" ;
9292
@@ -116,13 +116,13 @@ Using the `Sketch` type has one nice benefit over using `P5CanvasInstance` and
116116that is that the ` p5 ` argument passed to the sketch function is auto-typed as a
117117` P5CanvasInstance ` for you.
118118
119- > Sidenote :
119+ > Side note :
120120>
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
122122> sketches and there is nothing wrong with using the ` P5CanvasInstance ` manually
123123> in a regular ` function ` declaration.
124124
125- ``` typescript
125+ ``` tsx
126126import React from " react" ;
127127import { ReactP5Wrapper , Sketch } from " react-p5-wrapper" ;
128128
@@ -157,12 +157,12 @@ below, we create a custom internal type called `MySketchProps` which is a union
157157type of ` SketchProps ` and a custom type which has a ` rotation ` key applied to
158158it.
159159
160- > Sidenote :
160+ > Side note :
161161>
162162> We could also write the ` MySketchProps ` type as an interface to do exactly the
163163> same thing if that is to your personal preference:
164164>
165- > ``` typescript
165+ > ``` ts
166166> interface MySketchProps extends SketchProps {
167167> rotation: number ;
168168> }
@@ -174,7 +174,7 @@ correctly typed as a `number`.
174174
175175##### Usage with the ` P5CanvasInstance ` type
176176
177- ` ` ` typescript
177+ ` ` ` tsx
178178import React , { useEffect , useState } from " react" ;
179179import {
180180 P5CanvasInstance ,
@@ -228,7 +228,7 @@ export function App() {
228228
229229##### Usage with the ` Sketch ` type
230230
231- ``` typescript
231+ ``` tsx
232232import React , { useEffect , useState } from " react" ;
233233import { ReactP5Wrapper , Sketch , SketchProps } from " react-p5-wrapper" ;
234234
@@ -278,7 +278,7 @@ export function App() {
278278
279279### Using abstracted setup and draw functions
280280
281- ``` javascript
281+ ``` jsx
282282import React from " react" ;
283283import { ReactP5Wrapper } from " react-p5-wrapper" ;
284284
@@ -329,7 +329,7 @@ wrapper are changed, if it is set within your sketch. This way we can render our
329329` ReactP5Wrapper ` component and react to component prop changes directly within
330330our sketches!
331331
332- ``` javascript
332+ ``` jsx
333333import React , { useEffect , useState } from " react" ;
334334import { ReactP5Wrapper } from " react-p5-wrapper" ;
335335
@@ -377,7 +377,8 @@ export function App() {
377377
378378To render a component on top of the sketch, you can add it as a child of the
379379` 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.
381382
382383For instance, using [ styled components] ( https://styled-components.com ) , we could
383384center some text on top of our sketch like so:
@@ -430,10 +431,136 @@ export function App() {
430431}
431432```
432433
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
434435css to achieve almost anything you can imagine just by using the wrapper class
435436as your root selector.
436437
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+
437564## Development
438565
439566** NOTE:** The source code for the component is in the ` src ` directory.
0 commit comments