I'm a newbie with p5.js, but I want to create a blob that follows my cursor across the screen. I saw that you could do it with the mouseX and mouseY variables. Here is my code:
let kMax;
let step;
let n = 100; // number of blobs
let radius = -50; // diameter of the circle
let inter = 0.1; // difference between the sizes of two blobs
let maxNoise = 1100;
let lapse = 0; 10 // timer
let mouseX;
let mouseY;
let noiseProg = (x) => (x);
function setup() {
createCanvas(windowWidth, windowHeight);
//colorMode(HSB, 1);
angleMode(DEGREES);
noFill();
//noLoop();
kMax = random(0.6, 1.0);
step = 0.01;
noStroke();
mouseX
mouseY
}
function draw() {
blendMode(BLEND);
background(5,4,0);
blendMode(LIGHTEST);
let t = frameCount/100;
for (let i = n; i > 0; i--) {
let alpha = pow(1 - noiseProg(i / n), 3);
let size = radius + i * inter;
let k = kMax * sqrt(i/n);
let noisiness = maxNoise * noiseProg(i / n);
fill(142, 0, 255, alpha*255);
blob(size, width/2, height/2, k, t - i * step, noisiness, mouseX, mouseY, pmouseX, pmouseY);
fill (255,0,255, alpha*255);
blob(size, width/2, height/2, k, t - i * step + 1, noisiness, mouseX, mouseY, pmouseX, pmouseY);
fill (171, 126, 255, alpha*255);
blob(size, width/2, height/2, k, t - i * step + 2, noisiness, mouseX, mouseY, pmouseX, pmouseY);
//fill (03, 25, 250, alpha*255); aqua blue
//blob(size, width/2, height/2, k, t - i * step + 1, noisiness);
// fill(150, 0, 255, alpha*255);
// blob(size, width/2, height/2, k, t - i * step + 2, noisiness);
}
}
function blob(size, xCenter, yCenter, k, t, noisiness) {
beginShape();
let angleStep = 360 / 12;
for (let theta = 0; theta <= 360 + 14 * angleStep; theta += angleStep) {
let r1, r2;
/*
if (theta < PI / 2) {
r1 = cos(theta);
r2 = 1;
} else if (theta < PI) {
r1 = 0;
r2 = sin(theta);
} else if (theta < 3 * PI / 2) {
r1 = sin(theta);
r2 = 0;
} else {
r1 = 1;
r2 = cos(theta);
}
*/
r1 = cos(theta)+1;
r2 = sin(theta)+1;
let r = size + noise(k * r1, k * r2, t) * noisiness;
let x = xCenter + r * cos(theta);
let y = yCenter + r * sin(theta);
curveVertex(x, y);
}
endShape();
}
I've been trying different options, but currently, it is not working, and I cannot figuring why. When I try with the ellipse function it seems to work ok. Can you help me? :(
Related
I'm trying make render 3d rotating cube but cube has weird shape, I can't find the bug/glitch.
I'm following this tutorial on youtube.
I think I made something wrong on my code but everything seems good to me and I checked values on chrome debugging mode.
But when I following the tutorial I make some personal change but i'm sure this changes doesn't effect code working and make optimization on working.
Thanks.
const canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d');
const W = 600, H = 600;
const MODEL_MAX_X = 2, MODEL_MIN_X = -2, MODEL_MAX_Y = 2, MODEL_MIN_Y = -2, STEP = 0.5;
var points = [], triangles = [];
for (let x = -1; x <= 1; x += STEP)
for (let y = -1; y <= 1; y += STEP)
for (let z = -1; z <= 1; z += STEP)
points.push([x, y, z]);
for (let dimension = 0; dimension <= 2; ++dimension)
for (let side = -1; side <= 1; side += 2) {
var sidePoints = points.filter(point => point[dimension] == side).slice(0,3);
triangles.push([...sidePoints]);
}
function persvectiveProjection([x, y, z]) {
return [x / (z + 4), y / (z + 4)];
}
function project(point) {
const [x, y] = persvectiveProjection(point);
return [
W * (x - MODEL_MIN_X) / (MODEL_MAX_X - MODEL_MIN_X),
H * (1 - y - MODEL_MIN_Y) / (MODEL_MAX_Y - MODEL_MIN_Y)
];
}
ctx.lineWidth = 4;
ctx.strokeStyle = '#000';
function renderPoint(point) {
const [x, y] = project(point);
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + 1, y + 1);
ctx.stroke();
}
function renderTriangle (triangle) {
const projectedTriangle = triangle.map(project);
const [a, b, c] = projectedTriangle;
ctx.beginPath();
ctx.moveTo(a[0], a[1]);
ctx.lineTo(b[0], b[1]);
ctx.lineTo(c[0], c[1]);
ctx.lineTo(a[0], a[1]);
ctx.stroke();
}
function rotateY(point, theta) {
const [x, y, z] = point;
return [
Math.cos(theta) * x - Math.sin(theta) * z,
y,
Math.sin(theta) * x + Math.cos(theta) * z
]
}
function rotateX(point, theta) {
const [x, y, z] = point;
return [
x,
Math.cos(theta) * y - Math.sin(theta) * z,
Math.sin(theta) * y + Math.cos(theta) * z
]
}
var theta = 0;
var dtheta = 0.01;
function render() {
ctx.clearRect(0, 0, W, H);
theta += dtheta;
triangles.forEach(triangle => {
var rotatedTriangle = triangle.map(point => rotateX(rotateY(point, theta), 0.43 * theta));
renderTriangle(rotatedTriangle);
})
requestAnimationFrame(render);
}
render();
// Initial Setup
const canvas = document.querySelector('canvas');
const c = canvas.getContext('2d');
// Canvas size
canvas.width = innerWidth;
canvas.height = innerHeight;
//Color
const colors = [
{r: 51, g: 99, b: 252}
//{r: 77, g: 57, b: 206},
// {r: 0, g: 189, b: 255},
];
// Utility Functions
function randomIntFromRange(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
function randomColor(colors) {
return colors[Math.floor(Math.random() * colors.length)];
}
function distance(x1, y1, x2, y2) {
const xDist = x2 - x1;
const yDist = y2 - y1;
return Math.sqrt(Math.pow(xDist, 2) + Math.pow(yDist, 2));
}
function rotateVelocities(velocity, theta) {
const rotatedVelocity = {
x: velocity.x * Math.cos(theta) - velocity.y * Math.sin(theta),
y: velocity.x * Math.sin(theta) + velocity.y * Math.cos(theta)
};
return rotatedVelocity;
}
// Objects
function Particle(x, y, radius, rgb) {
this.x = x;
this.y = y;
this.velocity = {
x: (Math.random() - 0.5) * 3,
y: (Math.random() - 0.5) * 3
};
this.radius = radius;
this.mass = 1;
this.opacity = 0;
this.r = rgb.r;
this.g = rgb.g;
this.b = rgb.b;
this.update = particles => {
this.draw();
for (let i = 0; i < particles.length; i++) {
const otherParticle = particles[i];
if (this.x === otherParticle.x) continue;
if (distance(this.x, this.y, otherParticle.x, otherParticle.y) - this.radius * 2 < 0) {
const res = {
x: this.velocity.x - otherParticle.velocity.x,
y: this.velocity.y - otherParticle.velocity.y
};
if (res.x * (otherParticle.x - this.x) + res.y * (otherParticle.y - this.y) >= 0) {
const m1 = this.mass;
const m2 = otherParticle.mass;
const theta = -Math.atan2(otherParticle.y - this.y, otherParticle.x - this.x);
const rotatedVelocity1 = rotateVelocities(this.velocity, theta);
const rotatedVelocity2 = rotateVelocities(otherParticle.velocity, theta);
const swapVelocity1 = { x: rotatedVelocity1.x * (m1 - m2) / (m1 + m2) + rotatedVelocity2.x * 2 * m2 / (m1 + m2), y: rotatedVelocity1.y };
const swapVelocity2 = { x: rotatedVelocity2.x * (m1 - m2) / (m1 + m2) + rotatedVelocity1.x * 2 * m2 / (m1 + m2), y: rotatedVelocity2.y };
const u1 = rotateVelocities(swapVelocity1, -theta);
const u2 = rotateVelocities(swapVelocity2, -theta);
this.velocity.x = u1.x;
this.velocity.y = u1.y;
otherParticle.velocity.x = u2.x;
otherParticle.velocity.y = u2.y;
}
}
if (distance(this.x, this.y, otherParticle.x, otherParticle.y) - this.radius * 2 < 0 ) {
this.opacity = 0.1;
}
}
if (this.x + this.radius >= canvas.width || this.x - this.radius <= 0)
this.velocity.x = -this.velocity.x;
if (this.y + this.radius >= canvas.height || this.y - this.radius <= 0)
this.velocity.y = -this.velocity.y;
this.x += this.velocity.x;
this.y += this.velocity.y;
};
this.draw = () => {
c.beginPath();
c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
c.strokeStyle = `rgba(${this.r}, ${this.g}, ${this.b}, 1)`;
c.stroke();
c.fillStyle = `rgba(${this.r}, ${this.g}, ${this.b}, ${this.opacity}`;
c.fill();
c.closePath();
};
}
// Implementation
let particles;
function init() {
particles = [];
let radius = 80
for (let i = 0; i < 10; i++) {
let x = randomIntFromRange(radius, innerWidth - radius);
let y = randomIntFromRange(radius, innerHeight - radius);
if (particles.length >= 1) {
for (let j = 0; j < particles.length; j++) {
if (distance(x, y, particles[j].x, particles[j].y) - radius * 2 < 0) {
x = randomIntFromRange(radius, innerWidth - radius);
y = randomIntFromRange(radius, innerHeight - radius);
j = -1;
continue;
}
}
}
particles.push(new Particle(x, y, radius, randomColor(colors)));
}
}
//I would like to initiate one circle out of all as red and whenever the red circle collide with other circle, other circle got red and at last all circle become red. but when two white circle collide it should not become red. basically one infected circle making other circle infected by touching.
I'm writing a simple raycast in htm5l and the main issue with the raycast is that the line goes off in a direction of probably infinite length.. I would like to limit that length to a specific radius but I'm not having any luck. If someone could guide me that'd be great.
window.addEventListener('DOMContentLoaded', (event) => {
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let coord = {
x: 0,
y: 0
}
function line(x1, y1, x2, y2) {
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
class Vector {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class Boundery {
constructor(x1, y1, x2, y2) {
this.a = new Vector(x1, y1);
this.b = new Vector(x2, y2);
}
show() {
ctx.strokeStyle = '#000000'
line(this.a.x, this.a.y, this.b.x, this.b.y);
}
}
class Ray {
constructor(x, y) {
this.pos = new Vector(x, y);
this.dir = new Vector(Math.cos(1), Math.sin(0));
}
show() {
ctx.strokeStyle = '#000000';
ctx.beginPath();
ctx.ellipse(this.pos.x, this.pos.y, 5, 5, 0, 0, Math.PI * 2);
ctx.stroke();
}
cast(wall) {
let x1 = wall.a.x;
let y1 = wall.a.y;
let x2 = wall.b.x;
let y2 = wall.b.y;
let x3 = this.pos.x;
let y3 = this.pos.y;
let x4 = this.pos.x + this.dir.x;
let y4 = this.pos.y + this.dir.y;
let den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
if (den == 0) {
return;
}
let t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / den;
let u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / den;
if (t > 0 && t < 1 && u > 0) {
let point = new Vector(x1 + t * (x2 - x1), y1 + t * (y2 - y1));
return point;
} else {
return;
}
}
}
let wall = new Boundery(300, 100, 300, 300);
let ray = new Ray(100, 200);
function tick(timestamp) {
ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
wall.show();
ray.show();
let r = ray.cast(wall);
if (r) {
ctx.fillStyle = 'red';
ctx.ellipse(r.x, r.y, 10, 10, 0, 0, 2 * Math.PI);
ctx.fill();
}
requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
});
<canvas id="canvas" width="2000" height="1000"></canvas>
So the ray currently fires to the right (1,0) of the small red circle but it's distance just goes on forever so I'm trying to limit that distance. In the example the position the ray hits the wall is the red circle that's drawn on the wall
Ray length and direction
Modify the ray to have the start position, a direction, and a length. as follows
class Ray {
constructor(pos, direction, length) {
this.pos = pos;
this.dir = direction;
this.length = length;
}
You can get the end point with
get end() {
return new Vector(
this.pos.x + Math.cos(this.dir) * this.length,
this.pos.y + Math.sin(this.dir) * this.length
);
}
When you cast the ray you convert the ray to a line segment and then check against any wall segments for the intercept. Only points withing the length of the ray will be found.
Example.
The example uses a ray to check against many walls. It finds the closest intercept to the to the start of the ray and within the rays length.
Note (FOR example only) the walls are random so if a wall gets to close to the ray, click the canvas to randomize the walls.
I have re-organised it somewhat with Vector as a point, Line (2 vectors) as a line segment with an intercept function (also represents a wall), And Ray as a vector, direction and length. The Ray.cast finds the intercept of an array of line, returning undefined if no intercept found.
const ctx = canvas.getContext("2d");
Math.TAU = Math.PI * 2;
Math.rand = (min, max) => Math.random() * (max - min) + min;
var myRay;
const WALL_COUNT = 30;
const WALL_STYLE = {radius: 0, lineWidth: 1, strokeStyle: "#000"};
const RAY_STYLE_A = {radius: 2, lineWidth: 1, strokeStyle: "#0FF", fillStyle: "#F00"};
const RAY_STYLE_B = {radius: 5, lineWidth: 3, strokeStyle: "#00F", fillStyle: "#F00"};
const RAY_INTERCEPT_STYLE = {radius: 5, lineWidth: 1, strokeStyle: "#000", fillStyle: "#FF0"};
const ROTATE_RAY = 10; // seconds per rotation
const walls = [];
setTimeout(init, 0);
canvas.addEventListener("click",init);
class Vector {
constructor(x, y) {
this.x = x;
this.y = y;
}
draw(ctx, {radius = 5, lineWidth = 2, strokeStyle = "#000", fillStyle = "#F00"} = {}) {
ctx.strokeStyle = strokeStyle;
ctx.fillStyle = fillStyle;
ctx.lineWidth = lineWidth;
ctx.beginPath();
ctx.arc(this.x, this.y, radius, 0, Math.TAU);
ctx.fill();
ctx.stroke();
}
}
class Line {
constructor(start, end) {
this.start = start;
this.end = end;
}
draw(ctx, {radius = 5, lineWidth = 2, strokeStyle = "#000", fillStyle = "#F00"} = {}) {
if (radius > 0) {
this.start.draw(ctx, {radius, lineWidth, strokeStyle, fillStyle});
this.end.draw(ctx, {radius, lineWidth, strokeStyle, fillStyle});
}
ctx.strokeStyle = strokeStyle;
ctx.lineWidth = lineWidth;
ctx.beginPath();
ctx.moveTo(this.start.x, this.start.y);
ctx.lineTo(this.end.x, this.end.y);
ctx.stroke();
}
intercept(line) {
var x1, y1, x2, y2, x3, y3, c, u;
x1 = line.end.x - line.start.x;
y1 = line.end.y - line.start.y;
x2 = this.end.x - this.start.x;
y2 = this.end.y - this.start.y;
c = x1 * y2 - y1 * x2;
if (c) {
x3 = line.start.x - this.start.x;
y3 = line.start.y - this.start.y;
u = (x1 * y3 - y1 * x3) / c;
if (u >= 0 && u <= 1) {
u = (x2 * y3 - y2 *x3) / c;
if (u >= 0 && u <= 1) { return [u, line.start.x + x1 * u, line.start.y + y1 * u] }
}
}
}
}
class Ray {
constructor(pos, direction, length) {
this.pos = pos;
this.dir = direction;
this.length = length;
}
draw(ctx, {radius = 5, lineWidth = 2, strokeStyle = "#000", fillStyle = "#F00"} = {}) {
this.pos.draw(ctx, {radius, lineWidth, strokeStyle, fillStyle});
ctx.strokeStyle = strokeStyle;
ctx.lineWidth = lineWidth;
ctx.beginPath();
ctx.moveTo(this.pos.x, this.pos.y);
ctx.lineTo(
this.pos.x + Math.cos(this.dir) * this.length,
this.pos.y + Math.sin(this.dir) * this.length
);
ctx.stroke();
}
get end() {
return new Vector(
this.pos.x + Math.cos(this.dir) * this.length,
this.pos.y + Math.sin(this.dir) * this.length
);
}
get line() {
return new Line(this.pos, this.end);
}
cast(lines) {
const tLine = this.line;
var minDist = 1, point;
for (const line of lines) {
const result = line.intercept(tLine);
if (result) {
const [u, x, y] = result;
if (u <= minDist) {
minDist = u;
if (!point) { point = new Vector(x, y) }
else {
point.x = x;
point.y = y;
}
point.u = u;
}
}
}
return point;
}
}
function init() {
walls.length = 0;
for (let i = 0; i < WALL_COUNT / 2; i++) {
walls.push(new Ray(
new Vector(Math.rand(0, canvas.width * 0.4), Math.rand(0, canvas.height)),
(Math.rand(0, 8) | 0) / 4 * Math.PI, 100
).line);
walls.push(new Ray(
new Vector(Math.rand(canvas.width * 0.6, canvas.width), Math.rand(0, canvas.height)),
(Math.rand(0, 8) | 0) / 4 * Math.PI, 100
).line);
}
if(!myRay) {
myRay = new Ray(new Vector(canvas.width / 2, canvas.height / 2), 0, Math.max(canvas.width, canvas.height) * 0.485);
requestAnimationFrame(mainLoop);
}
}
function mainLoop(time) {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
myRay.dir = (time / (ROTATE_RAY * 1000)) * Math.TAU;
const point = myRay.cast(walls)
myRay.draw(ctx, RAY_STYLE_A);
for(const w of walls) { w.draw(ctx, WALL_STYLE) }
if (point) {
const len = myRay.length;
myRay.length = point.u * len;
myRay.draw(ctx, RAY_STYLE_B);
myRay.length = len;
point.draw(ctx, RAY_INTERCEPT_STYLE);
}
requestAnimationFrame(mainLoop);
}
#canvas {
border: 2px solid black;
}
<canvas id="canvas" width="500" height="500"> </canvas>
I'm trying to make a simple game in Processing. The canvas consist of two ellipsis, as in the following image:
This is my code:
var angle = Math.random()*360;
var diff = 1;
var region = {};
var first = true;
var o;
centerX = 250; centerY = 250; radiusX = 150; radiusY = 200;
var score = 0;
function setup() {
createCanvas(500, 500);
}
function draw() {
o = ellipseGetPoint(250,250,150,200,angle);
angle += diff;
background(220);
stroke("black");
fill("#333333");
ellipse(250,250,300,400);
stroke("white")
drawRegion(250,250,150,200);
stroke("red");
line(250,250,o.pointX, o.pointY);
fill("#999999");
stroke(0);
ellipse(250,250,200,300);
textSize(50);
text(str(score), 20, 490);
fill(0, 102, 153);
}
function ellipseGetPoint(centerX, centerY, radiusX, radiusY, angle) {
let o = {};
let pointX = centerX + radiusX * Math.cos(angle*Math.PI / 180);
let pointY = centerY + radiusY * Math.sin(angle*Math.PI / 180);
o.pointX = Math.floor(pointX);
o.pointY = Math.floor(pointY);
o.angle = angle;
return o;
}
function drawRegion(centerX, centerY, radiusX, radiusY) {
if (first) {
first = false;
region = ellipseGetPoint(centerX, centerY, radiusX, radiusY, Math.random()*360);
}
let currentX = region.pointX;
let currentY = region.pointY;
let t = 1;
for (let i = 0; i < 1000; i++) {
line(250,250, currentX, currentY);
currentX = centerX + radiusX * Math.cos(t*region.angle*Math.PI / 180)
currentY = centerY + radiusY * Math.sin(t*region.angle*Math.PI / 180)
t+=0.00015;
}
}
function keyPressed() {
if (key == " ") {
diff*=-1;
}
let x = Math.floor(o.pointX);
let y = Math.floor(o.pointY);
let t = 1;
for (let i = 0; i < 1000; i++) {
currentX = centerX + radiusX * Math.cos(t*region.angle*Math.PI / 180)
currentY = centerY + radiusY * Math.sin(t*region.angle*Math.PI / 180)
t+=0.00015;
if (Math.floor(currentX) == x) {
first = true
}
}
if (first) ++score;
else --score;
if (diff > 0 && diff < 3) diff += 0.1;
else if (diff > -3) diff -= 0.1;
}
The problem I'm facing is that, making the white area, I'm getting a different size of area depending of where it spawns.
I did it by getting a random point and adding a little offset, and drawing that 1000 times. I know this is not a good way to do it, but I don't know how to generate that region. Any way to do it?
Maybe you're looking for arc?
void draw() {
arc(50, 50, 80, 80, 0, QUARTER_PI, PIE);
}
Here's the documentation for more details. I think you'll love this.
Use arc() to draw an elliptical arc segment.
Compute the start and end angle in ellipseGetPoint and draw the arc:
function drawRegion(centerX, centerY, radiusX, radiusY) {
if (first) {
first = false;
region = ellipseGetPoint(centerX, centerY, radiusX, radiusY, Math.random()*360);
}
let t = 1;
let start = t*region.angle*Math.PI / 180;
t+= 0.15;
let end = t*region.angle*Math.PI / 180;
arc(centerX, centerY, radiusX*2, radiusY*2, start, end)
}
Note, you have to set the fill color before drawing the arc:
stroke("white")
drawRegion(250,250,150,200);
See the example:
var angle = Math.random()*360;
var diff = 1;
var region = {};
var first = true;
var o;
centerX = 250; centerY = 250; radiusX = 150; radiusY = 200;
var score = 0;
function setup() {
createCanvas(500, 500);
}
function draw() {
o = ellipseGetPoint(250,250,150,200,angle);
angle += diff;
background(220);
stroke("black");
fill("#333333");
ellipse(250,250,300,400);
fill("white")
stroke("white")
drawRegion(250,250,150,200);
stroke("red");
line(250,250,o.pointX, o.pointY);
fill("#999999");
stroke(0);
ellipse(250,250,200,300);
textSize(50);
text(str(score), 20, 490);
fill(0, 102, 153);
}
function ellipseGetPoint(centerX, centerY, radiusX, radiusY, angle) {
let o = {};
let pointX = centerX + radiusX * Math.cos(angle*Math.PI / 180);
let pointY = centerY + radiusY * Math.sin(angle*Math.PI / 180);
o.pointX = Math.floor(pointX);
o.pointY = Math.floor(pointY);
o.angle = angle;
return o;
}
function drawRegion(centerX, centerY, radiusX, radiusY) {
if (first) {
first = false;
region = ellipseGetPoint(centerX, centerY, radiusX, radiusY, Math.random()*360);
}
let t = 1;
let start = t*region.angle*Math.PI / 180;
t+= 0.15;
let end = t*region.angle*Math.PI / 180;
arc(centerX, centerY, radiusX*2, radiusY*2, start, end)
}
function keyPressed() {
if (key == " ") {
diff*=-1;
}
let x = Math.floor(o.pointX);
let y = Math.floor(o.pointY);
let t = 1;
for (let i = 0; i < 1000; i++) {
currentX = centerX + radiusX * Math.cos(t*region.angle*Math.PI / 180)
currentY = centerY + radiusY * Math.sin(t*region.angle*Math.PI / 180)
t+=0.00015;
if (Math.floor(currentX) == x) {
first = true
}
}
if (first) ++score;
else --score;
if (diff > 0 && diff < 3) diff += 0.1;
else if (diff > -3) diff -= 0.1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
I'm working on a custom button animation for my Wix website it is written in JavaScript and I get this error when I plug the code into an onclick event:
"cannot read property 'requestAnimationFrame' of undefined"
I've tried removing the return and I think the problem has to do with some sort of iframe issue because the original code was built to run in an html <iframe> element but that dident end up working out.
If someone could rewrite this code so that it dosent give this error that would be super helpful.
export function button7_click(event) {
$w.window.requestAnimFrame = (function() {
return $w.window.requestAnimationFrame ||
$w.window.webkitRequestAnimationFrame ||
$w.window.mozRequestAnimationFrame ||
$w.window.oRequestAnimationFrame ||
$w.window.msRequestAnimationFrame ||
function(callback) {
$w.window.setTimeout(callback, 1000 / 60);
};
})();
Math.randMinMax = function(min, max, round) {
var val = min + (Math.random() * (max - min));
if (round) val = Math.round(val);
return val;
};
Math.TO_RAD = Math.PI / 180;
Math.getAngle = function(x1, y1, x2, y2) {
var dx = x1 - x2,
dy = y1 - y2;
return Math.atan2(dy, dx);
};
Math.getDistance = function(x1, y1, x2, y2) {
var xs = x2 - x1,
ys = y2 - y1;
xs *= xs;
ys *= ys;
return Math.sqrt(xs + ys);
};
var FX = {};
(function() {
var canvas = $w.document.getElementById('myCanvas'),
ctx = canvas.getContext('2d'),
lastUpdate = new Date(),
mouseUpdate = new Date(),
lastMouse = [],
width, height;
FX.particles = [];
setFullscreen();
$w.document.getElementById('button').addEventListener('mousedown', buttonEffect);
function buttonEffect() {
var button = $w.document.getElementById('button'),
height = button.offsetHeight,
left = button.offsetLeft,
top = button.offsetTop,
width = button.offsetWidth,
x, y, degree;
for (var i = 0; i < 40; i = i + 1) {
if (Math.random() < 0.5) {
y = Math.randMinMax(top, top + height);
if (Math.random() < 0.5) {
x = left;
degree = Math.randMinMax(-45, 45);
} else {
x = left + width;
degree = Math.randMinMax(135, 225);
}
} else {
x = Math.randMinMax(left, left + width);
if (Math.random() < 0.5) {
y = top;
degree = Math.randMinMax(45, 135);
} else {
y = top + height;
degree = Math.randMinMax(-135, -45);
}
}
createParticle({
x: x,
y: y,
degree: degree,
speed: Math.randMinMax(100, 150),
vs: Math.randMinMax(-4, -1)
});
}
}
$w.window.setTimeout(buttonEffect, 100);
loop();
$w.window.addEventListener('resize', setFullscreen);
function createParticle(args) {
var options = {
x: width / 2,
y: height / 2,
color: 'hsla(' + Math.randMinMax(160, 290) + ', 100%, 50%, ' + (Math.random().toFixed(2)) + ')',
degree: Math.randMinMax(0, 360),
speed: Math.randMinMax(300, 350),
vd: Math.randMinMax(-90, 90),
vs: Math.randMinMax(-8, -5)
};
for ($w.key in args) {
options[$w.key] = args[$w.key];
}
FX.particles.push(options);
}
function loop() {
var thisUpdate = new Date(),
delta = (lastUpdate - thisUpdate) / 1000,
amount = FX.particles.length,
size = 2,
i = 0,
p;
ctx.fillStyle = 'rgba(15,15,15,0.25)';
ctx.fillRect(0, 0, width, height);
ctx.globalCompositeStyle = 'lighter';
for (; i < amount; i = i + 1) {
p = FX.particles[i];
p.degree += (p.vd * delta);
p.speed += (p.vs); // * delta);
if (p.speed < 0) continue;
p.x += Math.cos(p.degree * Math.TO_RAD) * (p.speed * delta);
p.y += Math.sin(p.degree * Math.TO_RAD) * (p.speed * delta);
ctx.save();
ctx.translate(p.x, p.y);
ctx.rotate(p.degree * Math.TO_RAD);
ctx.fillStyle = p.color;
ctx.fillRect(-size, -size, size * 2, size * 2);
ctx.restore();
}
lastUpdate = thisUpdate;
$w.requestAnimFrame(loop);
}
function setFullscreen() {
width = canvas.width = $w.window.innerWidth;
height = canvas.height = $w.window.innerHeight;
};
})();
}
The button once clicked should run the JavaScript code and play the animation. Thanks for your help.