Using HTML canvas element inside PsychoPy Builder Code (JavaScript) component – is it possible?

Hi everyone, I’ve been a bit stuck on a Builder Code Component issue for which I can’t seem to find an answer for elsewhere… so I was wondering whether any of you more experienced folks out there would know something about it!

Using a code component (written in JavaScript) in Psychopy v2020.2.6 , I am trying to draw some squares that use parameters previously defined in a preceding code component (e.g., number of squares, x/y coordinates of the squares). Due to number of squares varying between trials, I can’t use the exisiting “polygon” stimulus component.

So I wrote up some JS code (snippets below) that works fine when it is a part of a HTML file created separately. However this code doesn’t work when put into the PsychoPy builder component. I suspect this is because there is no tag specified – since the below code returns a “getContext returns NULL” error in the browser console when the experiment is piloted on Pavlovia.

const canvas = document.getElementById("canv");
const ctx = canvas.getContext("2d");
const width = window.innerWidth;
const height = window.innerHeight;
const maxWH = Math.max(width, height);
  
canvas.width = width;
canvas.height = height;

function drawSomeSquares(n){
     for(let i = 0; i < n; i++){
    // some code here to alter x, y coordinates and size of i'th square depending on other parameters already defined in a previous code component  

     ctx.fillStyle = coloursChosen[i]; // some colour depending on other parameters already defined in a previous code component
     ctx.fillRect(x,y,size,size);
   }
}

drawSomeSqures(k); // k previously defined

Would anyone know if it’s possible to get the above to work at all – for instance by including the canvas tag anywhere within PsychoPy? Or otherwise, if there’s some other possible method that exists for the Builder to draw these squares in the way we need?

Thanks a lot for any pointers you might be able to provide!

Cheers,
Amy

Why not? It will be much easier than creating your own from scratch (because PsychoJS stimuli already know where to draw themselves to). Simply create as many polygons as you need, set their locations etc, and draw them. API here:

Although I would suggest that you just create the required number of polygons once per trial, rather than create them and draw them at the same time. Depending on timing (e.g. if you want them visible for the whole duration of the trial), you could create them just once and set their autodraw property to true. Otherwise, separate the creation and drawing into separate functions.

There’s more than one way to skin a cat, of course. Instead of creating multiple polygon stimuli, you can just create one and then draw it at each of a number of locations. Using this approach, you could even use a Builder polygon stimulus component, rather than creating your own in code.

1 Like