I've had this error message "TypeError: a is undefined" for a while and I finally narrowed it down to a few lines of code in my project. I've created a smaller project from the original to demonstrate my problem:
new p5();
var particle = function(X, Y, C, Kind, Fun) {
this.pos = createVector(X, Y);
this.vel = createVector(0, 0);
this.accel = createVector(0, 0);
this.col = C;
this.isDead = false;
this.kind = Kind;
this.affect = Fun;
};
function setup() {
createCanvas(window.innerWidth, window.innerHeight);
};
var particles = new Array(new particle(1, 1, color(1, 1, 1), function () {
cosole.log("your mamma");
}));
function draw() {
};
If I run this in a browser, I get the error message mentioned above. In case you were wondering what my html looks like, here it is:
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
<script src="p5.min.js"></script>
<script src="p5_test.js"></script>
</head>
<style>
body {margin: none; padding: none;}
</style>
<body></body>
</html>
Any suggestions??
It looks like you're trying to use on-demand global mode to get around the restriction of not being able to use P5 functions until after setup() is called. I would expect your code to work.
However, when I run the code, I get this error:
Uncaught TypeError: Cannot read property '_colorMode' of undefined
at new p5.Color (p5.js:6482)
at p5.color (p5.js:6174)
at sketch.js:17
You're using the minified version of the library, so variable names aren't really useful. I'm using the unminified version, so I can see that the actual problem is that the _colorMode variable can't be found.
Tracing through the code, we see that your code calls the color() function, which hits line 6174 of P5.js:
return new p5.Color(this._renderer, arguments);
Which calls the p5.Color constructor, which hits line 6482 of P5.js:
this.mode = renderer._colorMode;
From this, we can see that the renderer variable is undefined, and when we try to access its _colorMode variable, we get the error.
So, it looks like P5's internal renderer variable is not defined, even though you're using on-demand global mode. The on-demand global mode gives you access to simple functions like random(), but it doesn't give you access to functions that require a renderer to have been initialized.
To fix your problem, just move your initialization into your setup() function:
var particle = function(C) {
this.col = C;
};
var particle;
function setup() {
createCanvas(window.innerWidth, window.innerHeight);
particle = new particle(color(1, 1, 1));
}
function draw() {
}
Note that you can also get rid of the new p5() at the top of your code, since it wasn't really helping you at all. Also note that I've simplified your code for the purpose of creating a MCVE, but the same ideas should hold true for your main project.
Related
I'm trying to write a small piece of javascript (p5.js) so I can drag in an image from my desktop into the browser. Then using my mouse cursor X&Y I can distort the image. I had this code working previously by just simply loading the image, but now I wish to have some interactive element with it so the user can load any image they want and apply the same effect.
var c;
var slice;
var sliceCount;
var sliceWidth;
var sliceWidthChecker;
function setup(){
var c = createCanvas(500,500);
background(51);
fill(255);
c.drop(gotFile);
}
function dropped() {
background(0);
}
function gotFile(file){
var img = createImg(file.data).hide();
image(img, 0, 0, 500, 500);
console.log(img)
noStroke();
stroke(0);
fill(255);
text(file.name, 20, 60);
text(file.size+' bytes', 20, 110);
}
function draw(){
/* setting the sliceWidth */
sliceWidth=windowWidth/12;
/* setting the how many slice on the canvas depending on the sliceWidth
*/
var maxSliceCount = windowWidth/sliceWidth;
/* this is trying to control, if the get pixel reads beyond the image,
it goes back, but didn't work.*/
if (sliceWidth >= c.width) {
sliceWidthChecker = sliceWidth - c.width;
} else {
sliceWidthChecker = sliceWidth;
}
/* drawing the slices */
for (sliceCount = 0; sliceCount < maxSliceCount; sliceCount++) {
/* sliceWidthChecker is trying to fix if get pixel reads beyond the
image, didn't work, can be replace by simply "sliceWidth" */
/* *0.5 after mouseX is to help if the mose move too much */
slice = c.get(mouseX*0.5+sliceCount*40, 0, sliceWidthChecker,
c.height);
image(slice, sliceWidth*sliceCount, windowHeight/10, slice.width,
slice.height);
}
}
You're declaring a variable c at the top of your sketch:
var c;
Then you're redeclaring a new variable that happens to have the same name inside your setup() function:
var c = createCanvas(500,500);
Because of the var keyword here, this is a different variable then the one you created above!
Then later, you use the original c variable:
if (sliceWidth >= c.width) {
But note that the original c variable has never been given a value. That's what's causing your error.
To fix this error you can simply remove the var keyword when you initialize the second c variable:
c = createCanvas(500,500);
This code sets the original c variable to the canvas value.
After this you have other errors in your code, but this should get you over this hurdle.
I'm trying to use line like this
myObject3D.children.forEach(
function(pChild){
return pChild.position.multiplyScalar(myMultiplier)
}
);
and this
myObject3D.children.forEach(
function(pChild){
pChild.position.copy(myVector3)
}
);
But for some reasons, functions in child elements of 'myObject3D' seems to be inexistent. ("Uncaught TypeError: pChild.position.multiplyScalar is not a function")
However, elements in 'myObject3D' are 'Mesh' objects.
Can anybody suggest what can I do?
Thanks
First, your forEach callback shouldn't return anything.
There doesn't appear to be anything wrong with your second code segment.
The code below runs without errors.
var group = new THREE.Object3D();
var geo = new THREE.BoxBufferGeometry(10, 10, 10);
var mat = new THREE.MeshBasicMaterial({
color: "red"
});
var mesh = new THREE.Mesh(geo, mat);
group.add(mesh);
group.add(mesh.clone());
group.add(mesh.clone());
group.add(mesh.clone());
group.add(mesh.clone());
var myVector3 = new THREE.Vector3();
group.children.forEach(function(pChild) {
pChild.position.multiplyScalar(5);
pChild.position.copy(myVector3)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.js"></script>
Please verify that you're populating your group with the correct kinds of objects. Also, you can always test if a function is available before using it:
if(obj.someFunction){
obj.someFunction();
}
I've made a processing.js webpage that i'm using to put a platformer game on, so i've got the code already planned out. Now I just have to put it on a webpage. Right now I can make the background red, but when I went to put the code in, I realised that it was't drawing any images. I looked it up, and the image method processing.js uses is very different to what I was doing. It still won't work.
Here is my processing.js code inside the HelloWeb.pde file:
preload =
"file:///E:/Extra%20Curricular/STEM%20Videogame/Art/BlackKingIdle.png";
//note that the E drive is my USB. I don't know if it will have an effect?
//AI Codes
int wolfX = 310;
int wolfY = 200;
int wolfHealth = 50;
//Health
int kingHealth = 100;
int dragon = 500;
//LV design
int floorHeight = 300;
int lvlNum = 1;
//movement (x)
int maxSpeed = 6.25;
int xForce = 0;
int kingXPos = 947.5;
//movement (y)
int kingYPos = floorHeight + 50;
int yForce = -15;
int jumping = false;
void setup() {
size(1895, 800);
background(255, 0, 0);
}
void draw() {
if (lvlNum != 0) {
PImage kingIdle = loadImage("file:///E:/Extra%20Curricular/STEM%20Videogame/Art/BlackKingIdle.png")
}
};
And the HTML:
<!DOCTYPE html>
<html>
<head>
<title>Hello Web - Processing.js Test</title>
<script src="processing.min.js"></script>
</head>
<body>
<h1>Processing.js Test</h1>
<p>This is my first Processing.js web-based sketch:</p>
<canvas data-processing-sources="HelloWeb.pde" width="1895" height="800" style="border:4px solid"></canvas>
</body>
</html>
You should get into the habit of posting an MCVE. Try to narrow your problem down to as few lines as possible. For example this code demonstrates your problem:
/* #pjs preload="C:\\Users\\Kevin\\Desktop\\August 1, 2016\\cropped\\Sky4.JPG"; */
PImage myImage;
void setup(){
size(200,200);
myImage = loadImage("C:\\Users\\Kevin\\Desktop\\August 1, 2016\\cropped\\Sky4.JPG");
}
void draw(){
image(myImage, 50,50, 100,100);
}
You should also get into the habit of checking out your JavaScript console. There you'll see any errors you're getting. If you look there, you should see an error that says "(index):1 Not allowed to load local resource".
And that error says it all. You aren't allowed to access local files from a webpage, even if you're running that webpage locally.
Your Processing.js webpage is being served by a local webserver. Processing handles this for you, which is nice, but that webserver can only touch files that you've imported into your sketch directory. Do this through the sketch menu in the Processing editor, or you can manually add a data folder to your sketch directory, and then put your images in there. Then just refer to the images relative to the sketch.
Two lines in my example code would change:
/* #pjs preload="Sky4.JPG"; */
myImage = loadImage("Sky4.JPG");
If you don't want to put your images in your sketch directory, then you're going to have to use your own webserver. You can run one locally, or you can upload your images to an image host and use the url in your code.
I want to move from well established css styles section and use of classes :
<style>
land { fill:grey; }
focus { fill:yellow; }
</style>
svg.
... // some stuff here
.attr("class","focus");
...to pure js variables :
var land = { 'fill':'grey' };
var focus= { 'fill':'yellow'};
I observe the following...
Conclusion
Passing 2 arguments, with the 2nd a function (1) and or one argument as a variable (2) work perfectly :
.attr("class", function(d){ if(){...}else{...} }) // (1) works
.attr(land) // (2) works
but this exact same function in (1) FAILS when I pass it as a single argument function (3) :
.attr(function(){ return land; }) // fails. Expected to return variable `land`, as for (2).
Any idea if this is an intended d3js behavior ? What do I do wrong ? And, possibly, how to make it work.
Migrate from css styles to pure js as follow.
Your former css:
<style>
land { fill:grey; }
focus { fill:yellow; }
</style>
...resulting js variables :
var land = "fill:grey" ; // no {}
var focus= "fill:yellow, stroke-color: #F00"; // , or ; should be ok.
...and d3js :
...
.attr("style", function(){return land}) // this is the way, together with no {} !
Here's what I thought was simple code:
<html>
<head>
<script>
function Foobar(id) {
self = this;
self.id = id;
self.canvas = document.createElement('canvas');
self.canvas.style.border = '1px solid black';
document.body.appendChild(self.canvas);
self.canvas.addEventListener('mousedown', self.onMouseDown, true);
self.onMouseDown = function(e) {
console.log(self.id);
}
}
var s1, s2;
function onLoad() {
s1 = new Foobar(1);
s2 = new Foobar(2);
}
</script>
</head>
<body onload='onLoad()'>
</body>
</html>
Why does the console not pop up with the id number?
Here's a fiddle: http://jsfiddle.net/VRn7v/
You must assign the method on self before binding the event listner
FIXED
http://jsfiddle.net/landau/VRn7v/3/
self is a property of the window object and is generally a bad variable name. Also, your self variable is an implicit global because you are missing the var keyword. Finally, you are binding the event handler before it is declared.
function Foobar(id) {
var that = this; // pick a better name, and use "var"
that.id = id;
that.canvas = document.createElement('canvas');
that.canvas.style.border = '1px solid black';
document.body.appendChild(that.canvas);
that.onMouseDown = function(e) {
console.log(self.id);
}; // missing semicolon
// bind the handler after declaring it
that.canvas.addEventListener('mousedown', that.onMouseDown, true);
}
self.canvas.addEventListener('mousedown', self.onMouseDown, true);
In this line, self.onMouseDown is undefined, because you assign it only afterwards. Possible quickfixes to get it work:
move the function creation / assignment above the usage
move the onMouseDown function to the prototype (bad, no local self in the scope)
don't use self.onMouseDown, but self.canvas.onmousedown (cross-browser-safe with traditional event registration)
Also, your self variable is global. With a working handler attachment, both clicks will log "2". And, the self variable is not needed in the most places you use it - the only need for it is in the event handler.
Corrected fiddle: http://jsfiddle.net/VRn7v/2/