pirela
pirela

Reputation: 553

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 ?

Upvotes: 1

Views: 177

Answers (2)

pirela
pirela

Reputation: 553

After exploring previous solution, i learn two things :

  • it's not mandatory to go through instanciation (despite probably a good practise): default is the current window, accessible by 'this'.
  • if graphics did not appear in first try when looping, it was because origin of coordinates are not reset at each loop in graphics.(see source core\p5.Graphics.js function draw())

The following gives a solution derived from previous. Have a look on push()/pop() around the call of graphics

let myGraph;

function setup() {
  myGraph = createGraphics(100, 100, WEBGL);
  canvas = createCanvas(200, 200, WEBGL);
  frameRate(0.5);
}

function draw() {
  // coordinates of window are reset at each draw.   
  translate(-width / 2, -height / 2);
  someDraw(this);
  // graphics coordinates cumulate at each draw.Protect:
  myGraph.push();
    myGraph.translate(-myGraph.width / 2, -myGraph.height / 2);
    someDraw(myGraph);
  myGraph.pop();

  // draw myGraph on canvas
  image(myGraph, 100, 100);
}

function someDraw(pg) {
  pg.clear();
  pg.background('blue');
  // origin will be now restored in main draw
  translate(10, 10);
  pg.stroke('red');
  pg.noFill();
  pg.line(0, 0, 100, 100);
  pg.rect(0, 0, 60, 60);
  pg.ellipse(25, 50, 50, 50);
}

enter image description here

Upvotes: 1

Rabbid76
Rabbid76

Reputation: 210889

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>

Upvotes: 1

Related Questions