9

I am using an npm, webpack, babel environment to write an application with p5.js. To be able to have the sketch as a module, I have the sketch in instance mode and import the library and add-ons as modules:

import p5 from 'p5';
import 'p5/lib/addons/p5.sound';
import 'p5/lib/addons/p5.dom';

Then I load them to the window inside my sketch:

const sketch = (p5) => {
   window.p5 = p5;
   ...
}
new p5(sketch);

When I try to use:

amp = new p5.Amplitude()

I get a 'p5.Amplitude is not a constructor' error. My prediction is that there is a conflict between naming the library p5 on the window and using the constructors from the library that use p5.something like p5.Amplitude, p5.Vector, p5.Soundfile. I have not been able to find a workaround to using these objects or constructors within instance mode. I am however able to use the methods from these objects that do not require a constructor. For example, loadSound() is a method of p5.Soundfile. The following works:

sound = p5.loadSound('assets/sound.wav)

but when I try console.log(p5.SoundFile) I get undefined.

I am lost!

Julio Gudiño
  • 320
  • 2
  • 10

3 Answers3

4

I'm not a JavaScript expert, but your syntax doesn't match the syntax on the instance mode page.

Specifically, what are you doing here?

const sketch = (p5) => {
   window.p5 = p5;
   ...
}
new p5(sketch);

Compare that to the syntax on the instance mode page:

var sketch = function (p) {
  var gray = 0; 

  p.setup = function () {
    p.createCanvas(600, 400);
  };

  p.draw = function () {
    p.background(gray);
    p.rect(p.width/2, p.height/2, 200, 200);
  };

  p.mousePressed = function () {
    gray = (gray + 16) % 256;
  };
};

new p5(sketch);

It looks like your code is redefining the p5 variable, which is going to cause the kinds of problems you're seeing. I would rewrite your code to no longer redefine the p5 variable, and use the syntax from the instance mode page instead:

var sketch = function(p) {
   //your code here
   //but don't change the p5 variable!
}
new p5(sketch);
Kevin Workman
  • 41,537
  • 9
  • 68
  • 107
  • Thanks for the response Kevin. I use `window.p5 = p5` to be able to load the library using es6 modules. With the latter I am making the library available in the window after using `import p5 from '....'`. I am able to use the rest of the functionality just like instance mode using p5 instead of p. Def not a javascript expert either, but I based this decision based on [this](https://github.com/vogelino/molecular-networks-p5-algorithm/blob/master/src/js/index.js) project which seems to pull it off smoothly. Cheers! – Julio Gudiño Sep 26 '16 at 15:59
  • I struggled for hours trying to get p5.js to work with es6 module syntax, until I found your answer, Kevin. Works great! – Justin C Oct 11 '16 at 03:30
  • I raised a similar issue here that follows a similar solution like what you proposed here... stackoverflow.com/questions/64887033/… I'm able to get function calls like .loadSound() to work but not constructor eg: .Envelope() do you know why? – Vennsoh Nov 18 '20 at 14:13
1

You're correct that you're overwriting the p5 class provided by the library with the instance that's provided to your code upon construction.

This should work:

import p5 from 'p5';
import 'p5/lib/addons/p5.sound';

const sketch = (p5) => {
   window.myp5 = p5;

   p5.setup = () => {
     //whatever
   };

   p5.draw = draw;
}

function draw() {
  //methods hang off the instance:
  const mysound = myp5.loadSound("/path/to/sound.mp3");
  //constructors hang off the class:
  const amp = new p5.Amplitude()
}
new p5(sketch);

Note that myp5 is available to the draw function because of the assignment at the beginning of the sketch function. Also note that you shouldn't need to import the addons.

nvioli
  • 4,137
  • 3
  • 22
  • 38
  • I raised a similar issue here that follows a similar solution like what you proposed here... https://stackoverflow.com/questions/64887033/how-do-i-add-p5-sound-to-react-using-react-p5-wrapper/64888427#64888427 I'm able to get function calls like .loadSound() to work but not constructor eg: .Envelope() do you know why? – Vennsoh Nov 18 '20 at 07:01
1

I think I figured out our problems. You need to use p5.sound library from version 0.9.0 and place it in your project's directory. I explain more fully in my answer here:

How to import and utilize P5.Sound in Vue?

Bob McBobson
  • 743
  • 1
  • 9
  • 29