Identifying Parameter Passed to Draw Funciton

In short I am attempting to pass numbers (received from an api) into the draw function to be printed onto an instance of a canvas, when the user's mouseIsPressed. Essentially I need to figure out how to know if a value is being passed into the draw function or not. Below is a very simple example of what I am trying to accomplish.

function setup() {
    createCanvas(1000, 600);
}

function draw(Lat, Long) {
    if (Lat == 'undefined') {
        console.log(2);
    } else {
       console.log(3); 
    }
}

I'd like the console to print 2 if there are no values being passed, but when this sketch runs, 3 is logged to the console. Sorry for the noob javascript question, any insight would be appreciated. Also, if this sample code (dumbed down version of what I am trying to accomplish) is not enough, let me know and I will post my exact code. Thanks!

Answers

  • edited October 6

    ADVICE: As for convention, only use UpperCamelCase names for classes & constructor functions. Therefore, parameters Lat & Long should be renamed as lat & lon, following LowerCamelCase naming convention. L-)

    • draw() is a callback function, whose caller is the p5.js sketch instance itself.
    • p5.js is pre-programmed to callback draw() w/ no arguments at all.
    • And we can't change that call signature unfortunately, unless we hack the p5.js library itself.
    • Nonetheless, the simplest workaround is declaring those parameters as global variables instead: let lat, lon;
  • edited October 6

    Another non-conventional approach is adding them as properties of draw().
    So you kinda make them somewhat "local" to that callback. :ar!

    I've made a simple example demoing it. Go to the link below to see it running online: O:-)
    http://p5js.SketchPad.cc/sp/pad/view/ro.C4DoFhUDGlhV0s/latest

    /**
     * Callback Local Properties (v1.0)
     * GoToLoop (2017-Oct-06)
     *
     * Forum.Processing.org/two/discussion/24414/
     * identifying-parameter-passed-to-draw-funciton#Item_2
     *
     * p5js.SketchPad.cc/sp/pad/view/ro.C4DoFhUDGlhV0s/latest
     */
    
    "use strict";
    
    function setup() {
      createCanvas(320, 200).mousePressed(latitude);
      noLoop();
    
      colorMode(RGB).blendMode(BLEND);
      fill('yellow').stroke(0).strokeWeight(2.5).strokeCap(ROUND);
      textSize(64).textAlign(CENTER, CENTER).textStyle(BOLD);
    }
    
    function draw() {
      background('#' + hex(~~random(0x1000), 3));
      text(draw.lat + '\n' + draw.lon, width>>1, height>>1);
    }
    
    function keyPressed() {
      longitude();
      return false;
    }
    
    function latitude() {
      draw.lat = ~~random(360);
      redraw();
    }
    
    function longitude() {
      draw.lon = ~~random(360);
      redraw();
    }
    
  • @GoToLoop

    I ran your code and there is a bug. I fixed it by doing the following modification:

    function latitude() {
      draw.lat = ~~random(360);
      //redraw();
      longitude();
    }
    

    The reason of this bug is that draw.lon is not being init or updated in the sketch. Maybe you have a better idea of how to fix it as a see mine more of a hack.

    Kf

  • edited October 6

    I ran your code and there is a bug.

    Which bug? It runs fine on me, both online & locally. :-/

    The reason of this bug is that draw.lon is not being init...

    Under OP's original post, it checks for undefined: if (Lat == 'undefined') console.log(2);

    So not being initialized is also expected and dealt w/. :-j

  • Merging first post and your post will do it.

    Kf

  • @GoToLoop can you elaborate more on line 14. Every time mouseIsPressed, the canvas is being drawn but passed the parameter of latitude? Also, can you explain text(draw.lat + '\n' + draw.lon, width>>1, height>>1);

    I understand the text function but I do not understand the function of draw.lat and draw.lon. The API I am using is here, http://api.open-notify.org/iss-now.json. I am attempting to have the JSON data refresh every second and update to the text function. What I have is below.

    HTML

    <!DOCTYPE html>
    <html>
        <head>
            <script src="Resources/p5.js"></script>
            <script language="javascript" type="text/javascript" src="Resources/p5.dom.js"></script>
            <script language="javascript" type="text/javascript" src="Resources/p5.sound.js"></script>
            <script language="javascript" type="text/javascript" src="Sketches/Painthead/Painthead.js"></script>
            <title>painthead</title>
        </head>
        <body>
        </body>
    </html>
    

    JS (Painthead.js)

    var PH13 = function ( p ) {
        var myCanvas;
        var mic;
        var Display;
        var lat;
        var long;
    
        p.GetValue = function() {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function() {
                    if (this.readyState == 4 && this.status == 200) {
                        var requestResponse = xhr.responseText;
                        var issInfo = JSON.parse(requestResponse);
                        var lat = issInfo.iss_position.latitude;
                        var long = issInfo.iss_position.longitude;
                        p.draw(lat, long);
                    }
                };
                xhr.open("GET", "http://api.open-notify.org/iss-now.json", true);
                xhr.send();
        }
        p.centerCanvas = function() {
            var x = (p.windowWidth - p.width) / 2;
            myCanvas.position(x, 8450);
            }
    
        p.setup = function() {
            myCanvas = p.createCanvas(1000, 600);
            p.centerCanvas();
            mic = new p5.AudioIn()
            mic.start();
            p.GetValue();
            }
    
        p.windowResized = function() {
            p.centerCanvas();
            } 
    
        p.draw = function(lat, long) {
            micLevel = mic.getLevel();   
            if (p.mouseIsPressed) {
                if ((micLevel >= 0) && (micLevel <.003)) {
                    vol = 0.0001;
                    volspec = 0.1;
                } else if ((micLevel >= 0.003) && (micLevel <= .4)){
                    vol = 1.4;
                    volspec = 0.06;
                } else {
                    vol = 2000;
                    volspec = 0;
                }
                p.GetValue();
                p.background('#fff1e1');
                p.text("IS", 3000*volspec*micLevel+400, 3000*volspec*micLevel+300);
                p.text("S", 4000*vol*micLevel+411, -2000*vol*micLevel+300);
                p.text("POSITION", -2000*vol*micLevel+ 425, -3500*vol*micLevel+300);
                p.text("Lat: ", -6000*vol*micLevel+412, -4000*vol*micLevel+350);
                p.text(Lat, 6000*volspec*micLevel+435, -4000*volspec*micLevel+350);
                p.text("Long: ", -3000*vol*micLevel+412, 4000*vol*micLevel+390);
                p.text(Long, 3000*volspec*micLevel+443, -4000*volspec*micLevel+390);
            } else {
                p.background(255);
            }
        }
    }
    myp5 = new p5(PH13);
    

    This works the first time the user's mouseIsPressed. The lat and long update. If the user lets go of mouse and attempts to press their mouse again, to reveal the lat and long values, an error

    Uncaught TypeError: Cannot read property 'toString' of undefined
        at p5.Renderer2D.text (p5.js:13140)
        at p5.text (p5.js:26611)
        at PH13.p.draw (Painthead.js:688)
        at p5.redraw (p5.js:14113)
        at p5.<anonymous> (p5.js:9147)
    

    is received. I am assuming this is because at some point the draw function is attempting to print the vals of lat and long, but they are not defined because the callback from p.GetValue has not had time to execute, or there is some discontinuity there. I am aware of the loadJSON function here https://p5js.org/reference/#/p5/loadJSON but am not sure how to update this information every second the draw loop is executed, as I want this information updated while the user is viewing. Sorry for the long post. Thanks for the help @GoToLoop and @kfrajer

  • Answer ✓

    I was checking the reference: https://p5js.org/reference/#/p5/draw

    and draw() has no parameters. So this is the first thing to modify in your code. Also notice that you are calling p.GetValue inside draw(lat,lon) and in the former function you are calling p.draw(lat,lon) making this a recursive call. This behavior is probably not desired in your application. I might suggest the following alternate version, which is untested:

    1. Remove line 16.

    2. Update your calls of draw to p.draw().

    Now every time p.GetValue(); is called, it will update the global values of lat and lon. These values are then used by the p.draw() function.

    Kf

  • @kfrajer perfect! Thank you. Needed a reminder in scope! Thanks again.

Sign In or Register to comment.