Search code examples
javascriptcanvasprocessingp5.js

P5 try to factorize Graphics and Canvas code


I want to factorize code for drawing same thing in a graphics or in the standard canvas.
( In my real program, i want to have autonomous class that draw themselves in some context given at construction time )
I cannot find some equivalent from canvas that can match graphics instructions except line.
In the following, i try to give either a canvas or a graphics object to the drawing method someDraw , but only line appears on canvas, while whole drawing appears in graphics.


let canvas;
let myGraph;

function setup() {
    canvas = createCanvas(200,300,WEBGL);
    canvas.parent('sketch-div');
    myGraph = createGraphics(200,300,WEBGL);
    stroke('red');
    noFill();
    noLoop();
}

function draw(){
    // direct draw on canvas / doesn't work correctly
    someDraw(canvas);
    // indirect draw on graphics, then show image 
    someDraw(myGraph);
    // show result
    image(myGraph,100,100);
}

function someDraw(pg){
 pg.clear();
 pg.background(color(0,0,200));

  // as webgl set 0,0 upper left 
 pg.translate(-pg.width/2, -pg.height/2);
 pg.stroke('red');
 pg.line(0,0,100,50);
 pg.rect(0,0,60,60);
 pg.ellipse (25,50,50,100);
}

You can see the (red) line drawn in canvas but not the rect or the ellipse. The graphics is correct. enter image description here

Another effect: if this small prog loops ( see noLoop() in setup ), the graphics appears fleeting first time then is no more displayed.

So, canvas and graphics are not in the same hierarchy, but is there a common way to draw on both without duplicating all code ?


Solution

  • Use Instantiation:

    var sketch = function( p ) {
        
        let canvas;
        let myGraph;
    
        p.setup = function() {
            canvas = p.createCanvas(200,300, p.WEBGL);
            canvas.parent('sketch-div');
            myGraph = p.createGraphics(200,300,p.WEBGL);        
            p.noLoop();
        }
    
        p.draw = function(){
            // [...]
        }
    }
    
    var test_3d = new p5(sketch);
    

    Pass either the p5 instance to someDraw

    someDraw(p);
    

    or the p5.Renderer object:

    someDraw(myGraph);
    

    Complete example:

    var sketch = function( p ) {
        let canvas;
        let myGraph;
    
        p.setup = function() {
            canvas = p.createCanvas(200,300,p.WEBGL);
            canvas.parent('sketch-div');
            myGraph = p.createGraphics(200,300,p.WEBGL);        
            p.noLoop();
        }
    
        p.draw = function(){
            // direct draw on canvas / doesn't work correctly
            someDraw(p);
            // indirect draw on graphics, then show image 
            someDraw(myGraph);
            // show result
            p.image(myGraph,100,100);
        }
    
        function someDraw(pg){
            pg.clear();
            pg.background(pg.color(0,0,200));
            // as webgl set 0,0 upper left 
            pg.translate(-pg.width/2, -pg.height/2);
            pg.stroke('red');
            pg.noFill();
            pg.line(0,0,100,50);
            pg.rect(0,0,60,60);
            pg.ellipse (25,50,50,100);
        }
    }
    
    var test_3d = new p5(sketch);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
    <div id="sketch-div"></div>