p5js AudioIn function not working on instance mode - javascript

I was converting my p5js code to instance mode to run 2 canvases in the same DOM but my p5.AudioIn() function is not working. The error I get is referencing Failed to construct 'AudioWorkletNode'. I have uploaded a screenshot of the error below because it has more information about it. Why isn't AudioIn not working when converted to instance mode but works on global mode.
let s2 = function(sketch) {
sketch.quinnListenMic;
sketch.setup = function() {
let cnv = sketch.createCanvas(300, 300);
cnv.mousePressed(sketch.userStartAudio);
sketch.quinnListenMic = new p5.AudioIn(); //ERROR HERE
sketch.quinnListenMic.start();
}
sketch.draw = function() {
sketch.background(100)
sketch.micLevel = quinnListenMic.getLevel();
console.log(micLevel)
}
}
var myp5_2 = new p5(s2);
<html>
<head>
<script defer src=https://cdn.JsDelivr.net/npm/p5></script>
<script defer src=https://cdn.JsDelivr.net/npm/p5/lib/addons/p5.dom.min.js></script>
<script defer src=https://cdn.JsDelivr.net/npm/p5/lib/addons/p5.sound.min.js></script>
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.0/lib/p5.js"></script>
</head>
<body>
</body>
</html>

There were a couple of issues, fixed below with comments:
let s2 = function(sketch) {
// sketch.quinnListenMic; doesn't make sense. 1) You don't want to store your variables on the p5 instance, and 2) that statement doesn't actually do anything
// This is how you declare a local variable for use in setup/draw functions:
let quinnListenMic;
sketch.setup = function() {
let cnv = sketch.createCanvas(300, 300);
cnv.mousePressed(sketch.userStartAudio);
quinnListenMic = new p5.AudioIn(); //ERROR HERE
quinnListenMic.start();
}
sketch.draw = function() {
// Fixed local variable declaration again
// Note: there is a bug with AudioIn.getLevel not working in all browsers
let micLevel = quinnListenMic.getLevel();
// Let's not spam the console log
// console.log(micLevel)
sketch.background(sketch.map(micLevel, 0, 1, 0, 255));
}
}
var myp5_2 = new p5(s2);
<html>
<head>
<!-- Your script tags were not valid -->
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.0/lib/p5.js"></script>
<!-- For some reason p5.sound does not work with the defer attribute -->
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.0/lib/addons/p5.sound.min.js"></script>
</head>
<body>
</body>
</html>

Related

Javascript code runs fine on Codesandbox but not on localy or on a webserver

I tried to read read QR code thanks to javascript code found in this tutorial
The code provided by this tutorial works inside the codesandbox linked in the tutorial, however it doesn't work when I tired the same exact code on my laptop or on my remote webserver. I've litteraly copy and paste the code with the same file configuration, filenames ect... but I'm getting the following JS error on my browser :
SyntaxError: Identifier 'qrcode' has already been declared (at qrCodeScanner.js:1:1)
Since I run the exact same code I d'ont understand what is going on there. Is there something needed on the server side in order to make the code works that is not mentioned in the tutorial ?
If you want to see the code used and see it in action, you can teste the codesandbox instance there.
EDIT
Here's the code I use :
(HMTL)
<!DOCTYPE html>
<html>
<head>
<title>QR Code Scanner</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width; initial-scale=1.0, maximum-scale=1.0; user-scalable=0;" />
<link rel="stylesheet" href="./src/style.css" />
<script src="https://rawgit.com/sitepoint-editors/jsqrcode/master/src/qr_packed.js"></script>
</head>
<body>
<div id="container">
<h1>QR Code Scanner</h1>
<a id="btn-scan-qr">
<img src="https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2017/07/1499401426qr_icon.svg">
<a/>
<canvas hidden="" id="qr-canvas"></canvas>
<div id="qr-result" hidden="">
<b>Data:</b> <span id="outputData"></span>
</div>
</div>
<script src="./src/qrCodeScanner.js"></script>
</body>
</html>
(Javascript)
const qrcode = window.qrcode;
const video = document.createElement("video");
const canvasElement = document.getElementById("qr-canvas");
const canvas = canvasElement.getContext("2d");
const qrResult = document.getElementById("qr-result");
const outputData = document.getElementById("outputData");
const btnScanQR = document.getElementById("btn-scan-qr");
let scanning = false;
qrcode.callback = res => {
if (res) {
outputData.innerText = res;
scanning = false;
video.srcObject.getTracks().forEach(track => {
track.stop();
});
qrResult.hidden = false;
canvasElement.hidden = true;
btnScanQR.hidden = false;
}
};
btnScanQR.onclick = () => {
navigator.mediaDevices
.getUserMedia({ video: { facingMode: "environment" } })
.then(function(stream) {
scanning = true;
qrResult.hidden = true;
btnScanQR.hidden = true;
canvasElement.hidden = false;
video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
video.srcObject = stream;
video.play();
tick();
scan();
});
};
function tick() {
canvasElement.height = video.videoHeight;
canvasElement.width = video.videoWidth;
canvas.drawImage(video, 0, 0, canvasElement.width, canvasElement.height);
scanning && requestAnimationFrame(tick);
}
function scan() {
try {
qrcode.decode();
} catch (e) {
setTimeout(scan, 300);
}
}
Problem
The problem is that you are probably using a live server or just opening the html file, but in the sandbox parcel-bundler is used. var qrcode from the library collides with your const qrcode.
Solutions
Type module
Replace
<script src="./src/qrCodeScanner.js"></script>
with
<script type="module" src="./src/qrCodeScanner.js"></script>
Rename
Change your variable to something else like const myQrcode
Use a bundler
You can use parcel-bundler as in the sandbox or any other that will resolve variable collision for you

How to load js/css files in custom popup load

In my project i am displaying a custom pop up page like below by javascript which has a form for user to fill,then I need to load some js files when pop up is loaded.
how to load js files,plz help.
<html>
<head>
<script type='text/javascript' src='files/jsfiles/core.js'></script>
</head>
<body>
<!- I need to call javascript function showUsers() from here->
<input type='button' onclick='showUsers();' value='listUsers'>
</body>
</html>
function loadScript(src) {
var script = document.createElement("script");
script.async = false;
script.src = src;
document.head.appendChild(script);
};
function loadStyle(src) {
var style = document.createElement("link");
style.rel = "stylesheet";
style.href = src;
document.head.appendChild(style);
};
function loadFiles() {
var scriptsArray = ['src1url', 'src2url'.., 'scrnurl'];
var csssArray = ['src1url', 'src2url'.., 'scrnurl'];
for (var i = 0; i < scriptsArray.length; i++) {
loadScript(scriptsArray[i]);
}
for (var i = 0; i < csssArray.length; i++) {
loadStyle(csssArray[i]);
}
};
function yoursubmitFcn(callback) {
// your functionality here;
callback();
}
$(document).ready(function () {
// do your stuff
yoursubmitFcn(loadFiles);
});
Also check: Another short form
You can use this library fancybox
Loading jQuery from CDN
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript" src="/fancybox/jquery.fancybox-1.3.4.pack.js"></script>
<link rel="stylesheet" href="/fancybox/jquery.fancybox-1.3.4.css" type="text/css"
media="screen" />
html
Sign in
JS
$('.open_pop').fancybox({
});
function openmsg_sent() {
jQuery(".open_pop").trigger("click");
}
For better and consistent UI, you can use a div which you can display with fixed positioning on click of the button.
I believe Alert wont be able to display css properties if am not wrong.
What you can do is, onclick of the button, in the JS, you can put your popup content into a div which is hidden initially and shown on click.
Hope this helps.

Very basic EaseLJS issue. I can't get it to work

I'm very new to javascript and EaseLJS but I don't understand how this doesnt work.
I have a html file:
<!DOCTYPE html>
<html>
<head>
<script src="easeljs-0.7.1.min.js" type="text/javascript"></script>
<script src="game.s.js" type="text/javascript"></script>
<script>
function init() {
renderLevel();
}
</script>
</head>
<body onLoad="init();">
<canvas id="canvas" width="500" height="300">
alternate content
</canvas>
</body>
</html>
The game.s.js file looks like:
function renderLevel()
{
var stage = new createjs.Stage("canvas");
var bitmap = new createjs.Bitmap("brick.png");
stage.addChild(bitmap);
bitmap.x = 32;
bitmap.y = 32;
stage.update();
alert(stage.canvas);
alert(bitmap.name);
}
The alert I just put there to check the values. stage.canvas rightly points to the HTML5Canvas element but the image won't show!
What am I missing here? :)
Thank you
The problem is that you are adding the image to stage before it loads, then there's no image yet. You need to wait for the image to load before adding it to the stage.
You can do this by using a preload(); function to load all the images before calling init(); or renderLevel();. Here's what this function should look like:
function preload(images, callback) {
var count = images.length;
if (count === 0) {
callback();
}
var loaded = 0;
$(images).each(function () {
$('<img>').attr('src', this).load(function () {
loaded++;
if (loaded === count) {
callback();
}
});
});
}
...and then you can use it like so:
preload(["image1.png", "image2.png"], init());

Change image in button on click

I've got a button with an image inside that I want to swap when clicked. I got that part working, but now I also want it to change back to the original image when clicked again.
The code I'm using:
<button onClick="action();">click me<img src="images/image1.png" width="16px" id="ImageButton1"></button>
And the Javascript:
function action() {
swapImage('images/image2.png');
};
var swapImage = function(src) {
document.getElementById("ImageButton1").src = src;
}
Thanks in advance!
While you could use a global variable, you don't need to. When you use setAttribute/getAttribute, you add something that appears as an attrib in the HTML. You also need to be aware that adding a global simply adds the variable to the window or the navigator or the document object (I don't remember which).
You can also add it to the object itself (i.e as a variable that isn't visible if the html is viewed, but is visible if you view the html element as an object in the debugger and look at it's properties.)
Here's two alternatives. 1 stores the alternative image in a way that will cause it to visible in the html, the other doesn't.
<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}
window.addEventListener('load', mInit, false);
function mInit()
{
var tgt = byId('ImageButton1');
tgt.secondSource = 'images/image2.png';
}
function byId(e){return document.getElementById(e);}
function action()
{
var tgt = byId('ImageButton1');
var tmp = tgt.src;
tgt.src = tgt.secondSource;
tgt.secondSource = tmp;
};
function action2()
{
var tgt = byId('imgBtn1');
var tmp = tgt.src;
tgt.src = tgt.getAttribute('src2');
tgt.setAttribute('src2', tmp);
}
</script>
<style>
</style>
</head>
<body>
<button onClick="action();">click me<img src="images/image1.png" width="16px" id="ImageButton1"></button>
<br>
<button onClick="action2();">click me<img id='imgBtn1' src="images/image1.png" src2='images/image2.png' width="16px"></button>
</body>
</html>
You need to store the old value in a global variable.
For example:
var globalVarPreviousImgSrc;
var swapImage = function(src)
{
var imgBut = document.getElementById("ImageButton1");
globalVarPreviousImgSrc = imgBut.src;
imgBut.src = src;
}
Then in the action method you can check if it was equal to the old value
function action()
{
if(globalVarPreviousImgSrc != 'images/image2.png')
{
swapImage('images/image2.png');
}else{
swapImage(globalVarPreviousImgSrc);
}
}
It's not a good idea to use global variables in javascripts use a closure or object literal. You can do something like using a closure
(function(){
var clickCounter = 0;
var imgSrc1 = "src to first image";
var imgSrc2 = "src to second image"
functions swapImage (src)
{
var imgBut = document.getElementById("ImageButton1");
imgBut.src = src;
}
function action()
{
if(clickCounter === 1)
{
swapImage(imgSrc1);
--clickCounter;
}else{
swapImage(imgSrc2);
++clickCounter;
}
}
})();
(I haven't run this code though)
This nice w3documentation gives you best practices.
Check this a working example just copy paste and run-
HTML
<button onClick="action();">click me<img src="http://dummyimage.com/200x200/000000/fff.gif&text=Image+1" width="200px" id="ImageButton1"></button>
JAVASCRIPT
<script>
function action()
{
if(document.getElementById("ImageButton1").src == 'http://dummyimage.com/200x200/000000/fff.gif&text=Image+1' )
document.getElementById("ImageButton1").src = 'http://dummyimage.com/200x200/dec4ce/fff.gif&text=Image+2';
else
document.getElementById("ImageButton1").src = 'http://dummyimage.com/200x200/000000/fff.gif&text=Image+1';
}
</script>
Check this working example - http://jsfiddle.net/QVRUG/4/

How can I include more than one Javascript file?

I want to use more Javascript files on one canvas, but I can't connect them. For example I want to write a Javascript file that contains all functions and an other Javascript file which is using them.
Show me a guide, how can I make this connection?
Thanks.
This is the first javascript file :
var canvas = null;
var ctx = null;
window.onload = function () {
canvas = document.getElementById('myCanvas');
ctx = canvas.getContext('2d');
line (100,100,300,300);
}
This is the secnond file:
function line (x1,y1,x2,y2) {
ctx.beginPath();
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);
ctx.stroke();
}
And this is my html file:
<!DOCTYPE html>
<html>
<head>
<title>Tutorialok</title>
<script type="text/javascript" src="CanvasElement.js"></script>
<script type="text/javascript" src="line.js"></script>
<style>
#myCanvas {
border: 1px solid #9C9898;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="800" height="600">
Sorry your browser Does not support canvas element!
</canvas>
</body>
</html>
The first file cant find the second files function.
Use namespacing via Objects. I don't recommend a pattern where all functions exist in one file, but this is an idea you could use. You MUST load file1.js before file2.js can do anything.
// file1.js
window.namespace = window.namespace || {};
window.namespace.fns = {
foo: function () {}
};
// file2.js
window.namespace.fns.foo();
jsFile 1
var f1 = function(){};
var f2 = function(){}
jsFile2
var s1 = f1();
var s2 = f2();
use this on the html page
<script src="path/jsFile1.js"></script>
<script src="path/jsFile2.js"></script>
If you're expecting the function to hoist, I don't believe that would work between script files since each one is evaluated independently. Switch the script tags around so line is in scope when CanvasElement.js loads.
Otherwise, the global namespace is shared between the linked scripts.

Categories