How to set canvas attributes from P5.js? - javascript

I am using P5.js (https://p5js.org/) for an application where I need multiple off-screen canvases. This is working just fine. Each canvas is created within a class as follows:
this.canvas = createGraphics(w, h);
In an attempt to experiment with performance, I decided it might be interesting to set willReadFrequently to true:
https://html.spec.whatwg.org/multipage/canvas.html#concept-canvas-will-read-frequently
This, in response to a warning I got:
Canvas2D: Multiple readback operations using getImageData are faster
with the willReadFrequently attribute set to true.
I can read the canvas attributes just fine using:
console.log(this.canvas.drawingContext.getContextAttributes());
The result is:
alpha: true
colorSpace: "srgb"
desynchronized: false
willReadFrequently: "undefined"
However, I can't seem to come-up with a way to set this attribute. P5.js does have a setAttributes() method:
https://p5js.org/reference/#/p5/setAttributes
When I try to use it, like this, I get a setAttributes is not a function or Cannot read proproties of undefined error:
this.canvas.drawingContext.setAttributes("willReadFrequently", true);
// or
this.canvas.setAttributes("willReadFrequently", true);
// or
this.canvas.setAttributes[{"willReadFrequently": true}];
These two attempts (tried all lower case as well) result in Cannot set properties of undefined (setting 'willReadFrequently'):
this.canvas.drawingContext.setAttributes.willReadFrequently = true;
this.canvas.drawingContext.setAttributes["willReadFrequently"] = true;
This attempt did not generate any errors, yet getContextAttributes() shows that nothing changed:
this.canvas.drawingContext.willReadFrequently = true;
Finally, looking at the Canvas API documentation...
https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext
I thought I should be able to do something like this:
this.canvas.drawingContext({willReadFrequently:true});
Once again, the error is is not a function.
I'm pretty sure I am missing something very fundamental here. I don't have the freedom to completely abandon P5 for the entire application. Do I need to rewrite this class to use the raw Canvas API for this to work? That's a lot of work. I wanted to get a sense of potential performance improvement before doing something like that.

Related

What does window.__context do?

I know it’s usually better to answer these questions with a google search, but I can’t seem to find it anywhere online. I wrote a function for creating a GlowScript canvas and adding it to an inputted div. I based it off of the code given on the website with some changes. Here is the function (it won't run on here because you need to import libraries, but it does create a 3D shape and put it in the div):
make_box("my_div")
function make_box(my_div){
window.__context = {glowscript_container: document.getElementById(my_div)}
var scene = canvas();
// create some shapes:
box( {pos:vec(.25,-1.4,0), size:vec(4.8,.3,2.5), color:color.red} )
}
I think the first line is required to add the canvas to the div. Without the line, I get the error:
Uncaught TypeError: Cannot set property ‘canvas_selected’ of undefined
I don’t really understand what it’s doing, however, and what the window context means. Does anyone have any insight into the line? Thanks!
This is what I found when I searched for window and context separately via google.
Apparently window is an object and .__context is a version of this. More information can be found in the links below.
https://www.w3schools.com/js/js_window.asp
https://towardsdatascience.com/javascript-context-this-keyword-9a78a19d5786

Query.swap Backwards compatibility

I'm trying to use a datepicker known as flexcal on my site. It is important for me to use it accurately, to allow selection from a Jewish calendar. My site is based on jQuery v3.3.1, but flexcal was designed for jQuery v2.1.3. I thought it shouldn't cause any problems, but I came across the following error:
Uncaught TypeError: $.swap is not a function
After searching, I found here that this is a method that was intended to be private and was never documented, Anyway at the moment I'm having trouble embedding a widget on my site. Reviewing the source code of the widget reveals that the use of the method looks like this:
return $.swap(
parent,
{display:'inline-block'}, // make it visible but shrink to contents
swapper.bind(this, elem, parent.parentNode)
);
Does anyone know what the purpose of the method is, does it have a parallel alternative, or some other troubleshooting advice?
If you look at the source of jQuery.swap (https://github.com/jquery/jquery/blob/3.4.1/src/css/var/swap.js), you'll see that all it does is temporarily change some CSS attributes of the first argument (parent, in your case), run a calculation, and the restore the original attribute values. You can implement that yourself. It's particularly easy in your case, since the only CSS attribute we're temporarily changing is display:
var old_display = parent.style['display'];
parent.style['display'] = 'inline-block';
var ret = swapper.bind(this, elem, parent.parentNode).apply(parent, []);
parent.style['display'] = old_display;
return ret;

How to change video playbackRate with coffeescript

I have a video, and I need it to run slower.
Current code:
ready = undefined
set_rate = undefined
set_rate = =>
$('#background').attr playbackRate: '.1'
return
ready = =>
set_rate()
return
$(document).ready ready
$('#background') selects my <video>
I have also tried $('#background').playbackRate = .1 and $('#background').playbackRate = '.1'
But I can never see any difference(alerting the playbackRate results in .1), I've also tried using vlc to slow down the video, but it becomes jumpy, and un-usable.
Notice: I am using coffeescript, not javascript (even though they're 'the same')
Also, the video is muted, I believe that makes things easier.
The jQuery attr() method (see the docs) expects a string which is the name of the attribute you want to change, and the value you want to set it to.
$('#background').attr 'playbackRate', 0.1
EDIT
If that doesn't work, try setting it directly via the DOM element rather than jQuery (use [0] to access it from it's jQuery wrapper)
$('#background')[0].playbackRate = 3.0;
If it's still not working, please post an example snippet of you code here or in a jsfiddle where we can reproduce and try out fixes.

Can't get audio to play in my Flash / HTML5 / Canvas project

Having lots of problems getting my sounds to play in a Flash-based Canvas project. I'm using the base example here (http://createjs.com/Docs/SoundJS/classes/Sound.html) in order work and all I get is a black screen and the following errors:
SyntaxError: missing ) after argument list
Which in my JS file is the following:
createjs.Sound.on("fileload", createjs.proxy(this.loadHandler, (this));
So I add the extra ) but now another error:
TypeError: createjs.Sound is undefined
Which is this:
createjs.Sound.registerPlugins([createjs.WebAudioPlugin, createjs.FlashAudioPlugin]);
What's going on here? Why can't I just get this to play?
Here's the complete code:
createjs.Sound.registerPlugins([createjs.WebAudioPlugin, createjs.FlashAudioPlugin]);
createjs.Sound.alternateExtensions = ["mp3"];
createjs.Sound.on("fileload", createjs.proxy(this.loadHandler, (this)));
createjs.Sound.registerSound("sounds/LaGrange.mp3", "sound");
function loadHandler(event) {
// This is fired for each sound that is registered.
var instance = createjs.Sound.play("sound"); // play using id. Could also use full source path or event.src.
instance.on("complete", createjs.proxy(this.handleComplete, this));
instance.volume = 0.5;
}
Well that's embarrassing. The example does have 2 errors. The first is the missing ")", which you caught and corrected. The second is that the FlashAudioPlugin is not completely setup. You need to add this line to set the path to the FlashAudioPlugin.swf before you register the plugins:
createjs.FlashAudioPlugin.swfPath = "../src/soundjs/flashaudio";
Thanks for catching this. I've pushed up a fixed version of this to github. Also, all the of the demos are well tested if you want more working examples to test from.
Hope that helps.
If you are testing locally (ie, not on a webserver - remote or local), then WebAudio can not play, since it uses XHR to load it, which does not work cross-domain (using file:/// is considered unsafe as well)
Change it to only use HTMLAudio when testing, and it should work.

Why is javascript saying that addcallback function is not defined?

my first time on here.
My problem is with AS3, Javascript and possibly the browsers Firefox and IE.
I have done so much searching for an answer so i will print my code:
i am using this line to call the flash application and in all browsers its combatible and actually traces in firebug to hold an OBJECT->FLASH_ID so thats not the problem.
var obj = document.getElementById('test');
then i use addcallback:
obj.sendStatus(loggedIn);
now whats weird is that i trace all individual elments in chrome and
-obj = flash object
-sendStatus = flash->function
-loggedIn = either false or true;
everything works great but when i am on firefox or ie
it traces differently
-obj = flash object
-sendStatus = undefined
-loggedIn = either true or false;
now what am i missing??????????
i tried embedding rather than object insertion
i made sure that the id's were all unique
i checked to make sure i had the right flash object selected with getElementById
im so confused.. and it feels like something simple.
I know about some browser - dependent timing problems, making the interface of the flash object available...
A timer could help, try this:
var obj = document.getElementById('test');
setTimeout(function(){obj.sendStatus(loggedIn);}, 500);
500 is a bit to long, but just to be sure. If it works you can try to lower it to 200 - 300.
make sure you declared allowScriptAccess = sameDomain both in embed tag and object tag
in case you don't use swfObject
Maybe the way you get a reference to the swf is wrong, try this
function thisMovie(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName];
} else {
return document[movieName];
}
}
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/external/ExternalInterface.html
The problem is that using ExternalInterface requires both parties (browser and flash) to be ready.
You can have the flash poll a method in the page which just returns true so that you know its ready to receive calls from flash.
On the flip side if the page is cached, it can sometimes happen that the page wants to send to flash before flash is ready, so I use a callback to the page telling it flash is ready, so its like a handshake, once both parties are ready, then we can start sending data back and forth.
This has been my approach since Firefox 3.

Categories