1

I'm trying to load a 3D model with P5.js in Angular 8. the syntax for creating a 3D canvas is

createCanvas(100, 100, WEBGL);

in Angular WEBGL is regarded as if it were a variable defined somewhere and throws this error.

core.js:6014 ERROR Error: Uncaught (in promise): ReferenceError: WEBGL is not defined ReferenceError: WEBGL is not defined

I tried modifying it like this

createCanvas(100, 100, 'WEBGL');

But when doing that I get this error

p5.js says: createCanvas() was expecting P2D|WEBGL for parameter #2 (zero-based index), received string instead at...

which is indicating it wants a value without parenthesis. How am I supposed to handle this?

UPDATE

I figured I'd share more code to be clearer about how I'm going about doing this.

I import the p5 library into the component like this

import * as p5 from 'p5';

inside my component I have a function that looks like this

private createGraphic(){
    const frameSize: any = this.calcFrameSize(); //calculates a width and height

    this.P5 = new p5(p =>{

            let importedModel: any;  //for pre loading the object

            p.preload = () =>{
                importedModel = p.loadModel(this.Element, true);
                //the this.Element variable is a string aiming to the .obj file
            }

            p.setup = () => {
                p.createCanvas(frameSize.width, frameSize.height, WEBGL); 
            };

            p.draw = () => {
                p.background(255, 17, 180);
                p.fill(0);
                p.scale(0.88);
                p.normalMaterial();
                p.model(importedModel);
            };
        },
        this.GraphicContainer.nativeElement
        //the target for injecting the object
        );
    }

I call this function inside the ngOnInit() like this

ngOnInit(){ this.createGraphic(); }

I tried using this.WEBGL as suggested in the answer bellow and am getting an error in the terminal saying

WEBGL does not exist on type...

because it's searching for it on my component. I'm also getting this error in the console

Error: normalMaterial() is only supported in WEBGL mode. If you'd like to use 3D graphics and WebGL,

I installed the @types library for P5.js to get it working with TypeScript. I successfully got a 2D demo working and moved on to try 3D and am having these problems.

Optiq
  • 2,835
  • 4
  • 33
  • 68

2 Answers2

2

Took me a while to setup you process, but I assume you are using p5.js via the instance method.

Your import needs to be:

import p5 from "p5";

For this import syntax to work and not throw an error, you need to set allowSyntheticDefaultImports (in compiler options) in tsconfig.json to true and have esModuleInterop set to true.

And you instantiate p5 via:

const myp5 = new p5((sketch) => {
  sketch.setup = function() {
    sketch.createCanvas(700, 410, this.WEBGL);
  };
});

Demo on stackblitz

C.OG
  • 6,236
  • 3
  • 20
  • 38
  • interesting. Importing it that way into my component causes a TS1192 error saying `module ........ has no default export` pointing to the P5 folder in the node modules. – Optiq Dec 12 '19 at 05:21
  • ok I just noticed in your stackblitz up above the `@Component` you declare `WEBGL` as a variable. I tried that and am still getting an error telling me WEBGL isn't a part of my component. When I take off `this` and let it target the `WEBGL` variable decalred at the top, it throws another error saying WEBGL is undefined... which is because it doesn't `=` anything. How does your `console.log(this.WEBGL)` return `webgl` when you're not assigning anything to it? What is it attached to and how? – Optiq Dec 12 '19 at 06:25
  • Ive updated the answer to fix the TS1192 error. You need to use `this.WEBGL` and not `WEBGL` and also for your `p.setup` function dont use the arrow notation, use the function keyword, because the context of `this` is important in this use case – C.OG Dec 12 '19 at 10:15
  • I also removed the webgl declaration in the stackblitz as its not necessary – C.OG Dec 12 '19 at 10:15
  • I haven't accepted this as the answer yet because I've run into another issue and have been wondering if I should update/change this question or start a new one. For starters I made the suggested change to my `tsconfig.json` file and I still couldn't import the p5 library the way you suggested, however changing the function syntax and adding `this.` made it work. I'll continue in another comment. – Optiq Dec 15 '19 at 00:29
  • I ran into the same issue again with trying to set the angle mode to degrees which is done with `angleMode(DEGREES);` which again refers to a variable inside the scope of `p5.js` and seeing that it's not being scoped into a function that ultimately generates inside the `p5` scope adding `this.` still makes it look for it somewhere within the component. I'm wondering if this is due to me still importing it as `import * as p5 from 'p5'` or if this really is a scoping issue using it with Angular regardless to which way it's imported. – Optiq Dec 15 '19 at 00:36
  • Also I tried adding the `allowSyntheticDefaultImports` to both the TS compiler options and the Angular compiler options in my `tsconfig.json` file and neither of them allowed me to use the import syntax you suggested. – Optiq Dec 15 '19 at 00:39
  • could you update the question with the way the code is at now, or if you can share the actual repo? – C.OG Dec 16 '19 at 06:48
  • 1
    Just realised that `esModuleInterop` is also required to be true – C.OG Dec 27 '19 at 09:50
0

Actually it turns out all I needed to do was add p to it to keep it in scope.

p.createCanvas(frameSize.width, frameSize.height, p.WEBGL);
Optiq
  • 2,835
  • 4
  • 33
  • 68