Why does canvas draw lines between circle (arc)? - javascript

In the moment canvas draw 15 circles with different speed and size which move from ltr. when one of them leaves the window it will be set to the start. The Problem is that canvas draw lines between the circles and i dont know why? Can anybody help?
window.onload = function () {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var W = canvas.width = window.innerWidth;
var H = canvas.height = window.innerHeight;
var mp = 15; //max particles
var particles = [];
//var rotate = 180;
reqAnimFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame;
for ( var i = 0; i < mp; i++ )
{
particles.push({
x: Math.floor(Math.random()*W), //x-coordinate
y: Math.floor(Math.random()*H), //y-coordinate
d: Math.floor(Math.random()*(mp - 1) + 1), //density
r: Math.floor(Math.random()*(70 - 10) + 10) //radius
})
}
function animate() {
reqAnimFrame(animate);
for ( var i = 0; i < mp; i++ )
{
var p = particles[i];
p.x += p.d;
if(p.x >= W){
p.x = -300;
p.y = Math.floor(Math.random()*H);
}
draw();
}
}
function draw() {
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = "rgba(0,204,142,1";
ctx.beginPath();
for ( var i = 0; i < mp; i++ )
{
var p = particles[i];
ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2, false);
//ctx.moveTo(p.x,p.y);
//ctx.lineTo(p.x + 150, p.y + (-180));
//ctx.lineTo(p.x + 300, p.y);
}
ctx.stroke();
}
animate();
};//onload function

Change the code a little bit as beginPath() and stroke() are now only called once - what happens is that the arcs are accumulated in the loop and since they are not really circles - they have two open ends - these ends will be connected to each other creating lines between the arcs.
Try the following:
function draw() {
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = "rgba(0,204,142,1";
for ( var i = 0; i < mp; i++ ) {
var p = particles[i];
ctx.beginPath();
ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2, false);
ctx.stroke();
}
}

Related

Canvas using high CPU in chrome

I am using a Codepen demo but after checking the CPU usage in chrome, it is using approx 100% of CPU. After trying hard, I am not able to figure out the problem as I am not an expert in javascript and canvas. What modifications do I need to make it use less CPU.
Codepen Link
As per my understanding, the problem is in animating particles or maybe I am wrong.
// Global Animation Setting
window.requestAnimFrame =
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000/60);
};
// Global Canvas Setting
var canvas = document.getElementById('particle');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Particles Around the Parent
function Particle(x, y, distance) {
this.angle = Math.random() * 2 * Math.PI;
this.radius = Math.random() ;
this.opacity = (Math.random()*5 + 2)/10;
this.distance = (1/this.opacity)*distance;
this.speed = this.distance*0.00003;
this.position = {
x: x + this.distance * Math.cos(this.angle),
y: y + this.distance * Math.sin(this.angle)
};
this.draw = function() {
ctx.fillStyle = "rgba(255,255,255," + this.opacity + ")";
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.radius, 0, Math.PI*2, false);
ctx.fill();
ctx.closePath();
}
this.update = function() {
this.angle += this.speed;
this.position = {
x: x + this.distance * Math.cos(this.angle),
y: y + this.distance * Math.sin(this.angle)
};
this.draw();
}
}
function Emitter(x, y) {
this.position = { x: x, y: y};
this.radius = 30;
this.count = 3000;
this.particles = [];
for(var i=0; i< this.count; i ++ ){
this.particles.push(new Particle(this.position.x, this.position.y, this.radius));
}
}
Emitter.prototype = {
draw: function() {
ctx.fillStyle = "rgba(0,0,0,1)";
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.radius, 0, Math.PI*2, false);
ctx.fill();
ctx.closePath();
},
update: function() {
for(var i=0; i< this.count; i++) {
this.particles[i].update();
}
this.draw();
}
}
var emitter = new Emitter(canvas.width/2, canvas.height/2);
function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
emitter.update();
requestAnimFrame(loop);
}
loop();
body{background:#000;}
<canvas id="particle"></canvas>
Avoid semi-transparency as much as possible.
Painting with alpha is a CPU killer, avoid blending as much as possible by using solid colors:
// Global Animation Setting
window.requestAnimFrame =
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000/60);
};
// Global Canvas Setting
var canvas = document.getElementById('particle');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Particles Around the Parent
function Particle(x, y, distance) {
this.angle = Math.random() * 2 * Math.PI;
this.radius = Math.random() ;
this.opacity = (Math.random()*5 + 2)/10;
// convert to solid color '#nnnnnn'
this.color = '#' + Math.floor((this.opacity * 255)).toString(16).padStart(2, 0).repeat(3);
this.distance = (1/this.opacity)*distance;
this.speed = this.distance*0.00003;
this.position = {
x: x + this.distance * Math.cos(this.angle),
y: y + this.distance * Math.sin(this.angle)
};
this.draw = function() {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.radius, 0, Math.PI*2, false);
ctx.fill();
ctx.closePath();
}
this.update = function() {
this.angle += this.speed;
this.position = {
x: x + this.distance * Math.cos(this.angle),
y: y + this.distance * Math.sin(this.angle)
};
this.draw();
}
}
function Emitter(x, y) {
this.position = { x: x, y: y};
this.radius = 30;
this.count = 3000;
this.particles = [];
for(var i=0; i< this.count; i ++ ){
this.particles.push(new Particle(this.position.x, this.position.y, this.radius));
}
}
Emitter.prototype = {
draw: function() {
ctx.fillStyle = "rgba(0,0,0,1)";
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.radius, 0, Math.PI*2, false);
ctx.fill();
ctx.closePath();
},
update: function() {
for(var i=0; i< this.count; i++) {
this.particles[i].update();
}
this.draw();
}
}
var emitter = new Emitter(canvas.width/2, canvas.height/2);
function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
emitter.update();
requestAnimFrame(loop);
}
loop();
body{background:#000;}
<canvas id="particle"></canvas>
But that's still not enough,
Avoid painting as much as possible.
The paint operations are really slow on a canvas (compared to non-paint ones) and should be avoided as much as possible. To do this, you can sort your particles by color and draw them by stack of single Path objects, but this requires that we round up a bit the opacity value (done when solidifying the color).
// Global Animation Setting
window.requestAnimFrame =
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000/60);
};
// Global Canvas Setting
var canvas = document.getElementById('particle');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Particles Around the Parent
function Particle(x, y, distance) {
this.angle = Math.random() * 2 * Math.PI;
this.radius = Math.random() ;
this.opacity = (Math.random()*5 + 2)/10;
// convert to solid color '#nnnnnn'
this.color = '#' + Math.floor((this.opacity * 255)).toString(16).padStart(2, 0).repeat(3);
this.distance = (1/this.opacity)*distance;
this.speed = this.distance*0.00003;
this.position = {
x: x + this.distance * Math.cos(this.angle),
y: y + this.distance * Math.sin(this.angle)
};
this.draw = function() {
// here we remove everything but the 'arc' operation and a moveTo
// no paint
ctx.moveTo(this.position.x + this.radius, this.position.y);
ctx.arc(this.position.x, this.position.y, this.radius, 0, Math.PI*2, false);
}
this.update = function() {
this.angle += this.speed;
this.position = {
x: x + this.distance * Math.cos(this.angle),
y: y + this.distance * Math.sin(this.angle)
};
// 'update' should not 'draw'
// this.draw();
}
}
function Emitter(x, y) {
this.position = { x: x, y: y};
this.radius = 30;
this.count = 3000;
this.particles = [];
for(var i=0; i< this.count; i ++ ){
this.particles.push(new Particle(this.position.x, this.position.y, this.radius));
}
// sort our particles by color (opacity = color)
this.particles.sort(function(a, b) {
return a.opacity - b.opacity;
});
}
Emitter.prototype = {
draw: function() {
ctx.fillStyle = "rgba(0,0,0,1)";
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.radius, 0, Math.PI*2, false);
ctx.fill();
// draw our particles in batches
var particle, color;
ctx.beginPath();
for(var i=0; i<this.count; i++) {
particle = this.particles[i];
if(color !== particle.color) {
ctx.fill();
ctx.beginPath();
ctx.fillStyle = color = particle.color;
}
particle.draw();
}
ctx.fill(); // fill the last batch
},
update: function() {
for(var i=0; i< this.count; i++) {
this.particles[i].update();
}
this.draw();
}
}
var emitter = new Emitter(canvas.width/2, canvas.height/2);
function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
emitter.update();
requestAnimFrame(loop);
}
loop();
body{background:#000;}
<canvas id="particle"></canvas>
That's better but not yet perfect...
Finally, be clever about YOUR animation.
In your animation, the opacity defines the distance. That is, the particles that are farther from the center are the most transparent ones. This exactly defines what a radial gradient is.
We can thus reduce our paint operations to two. Yes, only two paints for 3000 particles, using a radial-gradient and a bit of compositing, we can first draw all the particles in a single shot, and then apply the gradient as a mask which will apply its color only where there were already something painted. We can even keep the transparency.
// Global Animation Setting
window.requestAnimFrame =
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000/60);
};
// Global Canvas Setting
var canvas = document.getElementById('particle');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Particles Around the Parent
function Particle(x, y, distance) {
this.angle = Math.random() * 2 * Math.PI;
this.radius = Math.random() ;
this.opacity = (Math.random()*5 + 2)/10;
this.distance = (1/this.opacity)*distance;
this.speed = this.distance*0.00003;
this.position = {
x: x + this.distance * Math.cos(this.angle),
y: y + this.distance * Math.sin(this.angle)
};
this.draw = function() {
// still no paint here
ctx.moveTo(this.position.x + this.radius, this.position.y);
ctx.arc(this.position.x, this.position.y, this.radius, 0, Math.PI*2, false);
}
this.update = function() {
this.angle += this.speed;
this.position = {
x: x + this.distance * Math.cos(this.angle),
y: y + this.distance * Math.sin(this.angle)
};
this.draw();
}
}
function Emitter(x, y) {
this.position = { x: x, y: y};
this.radius = 30;
this.count = 3000;
this.particles = [];
for(var i=0; i< this.count; i ++ ){
this.particles.push(new Particle(this.position.x, this.position.y, this.radius));
}
// a radial gradient that we will use as mask
// in particle.constructor
// opacities go from 0.2 to 0.7
// with a distance range of [radius, 1 / 0.2 * this.radius]
this.grad = ctx.createRadialGradient(x, y, this.radius, x, y, 1 / 0.2 * this.radius);
this.grad.addColorStop(0, 'rgba(255,255,255,0.7)');
this.grad.addColorStop(1, 'rgba(255,255,255,0.2)');
}
Emitter.prototype = {
draw: function() {
ctx.fillStyle = "rgba(0,0,0,1)";
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.radius, 0, Math.PI*2, false);
ctx.fill();
ctx.closePath();
},
update: function() {
ctx.beginPath(); // one Path
ctx.fillStyle = 'black'; // a solid color
for(var i=0; i< this.count; i++) {
this.particles[i].update();
}
ctx.fill(); // one paint
// prepare the composite operation
ctx.globalCompositeOperation = 'source-in';
ctx.fillStyle = this.grad; // our gradient
ctx.fillRect(0,0,canvas.width, canvas.height); // cover the whole canvas
// reset for next paints (center arc and next frame's clearRect)
ctx.globalCompositeOperation = 'source-over';
this.draw();
}
}
var emitter = new Emitter(canvas.width/2, canvas.height/2);
function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
emitter.update();
requestAnimFrame(loop);
}
loop();
body{background:#000;}
<canvas id="particle"></canvas>

Canvas line drawing animation

I am new learner of animation using HTML5 Canvas. I am struggling to create line drawing animation in a canvas with desired length of a line.
Here is the code
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
width = canvas.width = window.innerWidth,
height = canvas.height = window.innerHeight;
var x = 200;
var y = 200;
draw();
update();
function draw() {
context.beginPath();
context.moveTo(100, 100);
context.lineTo(x, y);
context.stroke();
}
function update() {
context.clearRect(0, 0, width, height);
x = x + 1;
y = y + 1;
draw();
requestAnimationFrame(update);
}
html,
body {
margin: 0px;
}
canvas {
display: block;
}
<canvas id="canvas"></canvas>
The line is growing on Canvas in the above code. But how to achieve that the 200px wide line and animate the movement in x and y direction. And the same animation with multiple lines using for loop and move them in different direction.
Check the reference image ....
Need to move each line in a different direction
Thanks in advance
Find a new reference image which i want to achieve
You need to either use transforms or a bit of trigonometry.
Transforms
For each frame:
Reset transforms and translate to center
Clear canvas
Draw line from center to the right
Rotate x angle
Repeat from step 2 until all lines are drawn
var ctx = c.getContext("2d");
var centerX = c.width>>1;
var centerY = c.height>>1;
var maxLength = Math.min(centerX, centerY); // use the shortest direction for demo
var currentLength = 0; // current length, for animation
var lenStep = 1; // "speed" of animation
function render() {
ctx.setTransform(1,0,0,1, centerX, centerY);
ctx.clearRect(-centerX, -centerY, c.width, c.height);
ctx.beginPath();
for(var angle = 0, step = 0.1; angle < Math.PI * 2; angle += step) {
ctx.moveTo(0, 0);
ctx.lineTo(currentLength, 0);
ctx.rotate(step);
}
ctx.stroke(); // stroke all at once
}
(function loop() {
render();
currentLength += lenStep;
if (currentLength < maxLength) requestAnimationFrame(loop);
})();
<canvas id=c></canvas>
You can use transformation different ways, but since you're learning I kept it simple in the above code.
Trigonometry
You can also calculate the line angles manually using trigonometry. Also here you can use different approaches, ie. if you want to use delta values, vectors or brute force using the math implicit.
For each frame:
Reset transforms and translate to center
Clear canvas
Calculate angle and direction for each line
Draw line
var ctx = c.getContext("2d");
var centerX = c.width>>1;
var centerY = c.height>>1;
var maxLength = Math.min(centerX, centerY); // use the shortest direction for demo
var currentLength = 0; // current length, for animation
var lenStep = 1; // "speed" of animation
ctx.setTransform(1,0,0,1, centerX, centerY);
function render() {
ctx.clearRect(-centerX, -centerY, c.width, c.height);
ctx.beginPath();
for(var angle = 0, step = 0.1; angle < Math.PI * 2; angle += step) {
ctx.moveTo(0, 0);
ctx.lineTo(currentLength * Math.cos(angle), currentLength * Math.sin(angle));
}
ctx.stroke(); // stroke all at once
}
(function loop() {
render();
currentLength += lenStep;
if (currentLength < maxLength) requestAnimationFrame(loop);
})();
<canvas id=c></canvas>
Bonus animation to play around with (using the same basis as above):
var ctx = c.getContext("2d", {alpha: false});
var centerX = c.width>>1;
var centerY = c.height>>1;
ctx.setTransform(1,0,0,1, centerX, centerY);
ctx.lineWidth = 2;
ctx.strokeStyle = "rgba(0,0,0,0.8)";
ctx.shadowBlur = 16;
function render(time) {
ctx.globalAlpha=0.77;
ctx.fillRect(-500, -500, 1000, 1000);
ctx.globalAlpha=1;
ctx.beginPath();
ctx.rotate(0.025);
ctx.shadowColor = "hsl(" + time*0.1 + ",100%,75%)";
ctx.shadowBlur = 16;
for(var angle = 0, step = Math.PI / ((time % 200) + 50); angle < Math.PI * 2; angle += step) {
ctx.moveTo(0, 0);
var len = 150 + 150 * Math.cos(time*0.0001618*angle*Math.tan(time*0.00025)) * Math.sin(time*0.01);
ctx.lineTo(len * Math.cos(angle), len * Math.sin(angle));
}
ctx.stroke();
ctx.globalCompositeOperation = "lighter";
ctx.shadowBlur = 0;
ctx.drawImage(ctx.canvas, -centerX, -centerY);
ctx.drawImage(ctx.canvas, -centerX, -centerY);
ctx.globalCompositeOperation = "source-over";
}
function loop(time) {
render(time);
requestAnimationFrame(loop);
};
requestAnimationFrame(loop);
body {margin:0;background:#222}
<canvas id=c width=640 height=640></canvas>
Here is what I think you are describing...
window.onload = function() {
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
width = canvas.width = 400,
height = canvas.height = 220,
xcenter = 200,
ycenter = 110,
radius = 0,
radiusmax = 100,
start_angle1 = 0,
start_angle2 = 0;
function toRadians(angle) {
return angle * (Math.PI / 180);
}
function draw(x1, y1, x2, y2) {
context.beginPath();
context.moveTo(x1, y1);
context.lineTo(x2, y2);
context.stroke();
}
function drawWheel(xc, yc, start_angle, count, rad) {
var inc = 360 / count;
for (var angle = start_angle; angle < start_angle + 180; angle += inc) {
var x = Math.cos(toRadians(angle)) * rad;
var y = Math.sin(toRadians(angle)) * rad;
draw(xc - x, yc - y, xc + x, yc + y);
}
}
function update() {
start_angle1 += 0.1;
start_angle2 -= 0.1;
if(radius<radiusmax) radius++;
context.clearRect(0, 0, width, height);
drawWheel(xcenter, ycenter, start_angle1, 40, radius);
drawWheel(xcenter, ycenter, start_angle2, 40, radius);
requestAnimationFrame(update);
}
update();
};
html,
body {
margin: 0px;
}
canvas {
display: block;
}
<canvas id="canvas"></canvas>
This is one that is a variable length emerging pattern. It has a length array element for each spoke in the wheel that grows at a different rate. You can play with the settings to vary the results:
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var width = canvas.width = window.innerWidth;
var height = canvas.height = window.innerHeight;
var xcenter = width/4;
var ycenter = height/2;
var radius;
var time;
if(width>height) {
radius = height*0.4;
}
else {
radius = width*0.4;
}
var start_angle1 = 0;
var start_angle2 = 0;
function toRadians (angle) {
return angle * (Math.PI / 180);
}
function draw(x1,y1,x2,y2) {
context.beginPath();
context.moveTo(x1,y1);
context.lineTo(x2,y2);
context.stroke();
}
var radmax=width;
var rads = [];
var radsinc = [];
function drawWheel(xc,yc,start_angle,count,rad) {
var inc = 360/count;
var i=0;
for(var angle=start_angle; angle < start_angle+180; angle +=inc) {
var x = Math.cos(toRadians(angle)) * rads[rad+i];
var y = Math.sin(toRadians(angle)) * rads[rad+i];
draw(xc-x,yc-y,xc+x,yc+y);
rads[rad+i] += radsinc[i];
if(rads[rad+i] > radmax) rads[rad+i] = 1;
i++;
}
}
function update() {
var now = new Date().getTime();
var dt = now - (time || now);
time = now;
start_angle1 += (dt/1000) * 10;
start_angle2 -= (dt/1000) * 10;
context.clearRect(0,0,width,height);
drawWheel(xcenter,ycenter,start_angle1,50,0);
drawWheel(xcenter,ycenter,start_angle2,50,50);
requestAnimationFrame(update);
}
function init() {
for(var i=0;i<100;i++) {
rads[i] = 0;
radsinc[i] = Math.random() * 10;
}
}
window.onload = function() {
init();
update();
};
html, body {
margin: 0px;
}
canvas {
width:100%;
height:200px;
display: block;
}
<canvas id="canvas"></canvas>

Javascript confetti blast effect

I was able to find this code to create a javascript confetti blast.
However, I need three main colours for the confetti, and for the confetti, to be squares. Any help would be much appreciated.
Below is the code
// shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
W = window.innerWidth,
H = window.innerHeight,
circles = [];
canvas.width = W;
canvas.height = H;
//Random Circles creator
function create() {
//Place the circles at the center
this.x = W/2;
this.y = H/2;
//Random radius between 2 and 6
this.radius = 2 + Math.random()*3;
//Random velocities
this.vx = -5 + Math.random()*10;
this.vy = -5 + Math.random()*10;
//Random colors
this.r = Math.round(Math.random())*255;
this.g = Math.round(Math.random())*255;
this.b = Math.round(Math.random())*255;
}
for (var i = 0; i < 500; i++) {
circles.push(new create());
}
function draw() {
//Fill canvas with black color
ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = "rgba(0,0,0,0.15)";
ctx.fillRect(0, 0, W, H);
//Fill the canvas with circles
for(var j = 0; j < circles.length; j++){
var c = circles[j];
//Create the circles
ctx.beginPath();
ctx.arc(c.x, c.y, c.radius, 0, Math.PI*2, true);
ctx.fillStyle = "rgba("+c.r+", "+c.g+", "+c.b+", 1)";
ctx.fill();
c.x += c.vx;
c.y += c.vy;
c.radius -= .02;
if(c.radius > 3)
circles[j] = new create();
}
}
function animate() {
requestAnimFrame(animate);
draw();
}
animate();
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Untitled Document</title>
<style type="text/css">
body{
padding: 0; margin: 0;
min-height: 400px; height: 100%;
width: 100%;
overflow: hidden;
background-color: #000000;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="explosion.js"></script>
</body>
</html>
I wrote up an alternative solution. I noticed your current solutions had some runtime error, also a lot of unnecessary code (IMO - might be cleaner or easier to read?) and painted the whole rectangle canvas, you could apply this as a background colour via CSS, or leave as transparent as you probably want the confetti to show over something?
https://codepen.io/BenMoses/pen/MWyEePJ
ctx.globalCompositeOperation = "source-over"; //not needed as is default.
// shim layer with setTimeout fallback ? This is globally support so probably unnecessary?
//this.radius = 2 + Math.random()*3; //this is only for circles so can be removed
// all circle references should be updated to rect or square or confetti and confetto (a single confetti :o )
Pass in the index and use modulus operator to determine what color to set. Basic idea:
function create(ind) {
/* other code */
if(ind%3===0) { /* set color one */ }
else if (ind%2===0) { /* set color two */ }
else { /* set color three */ }
}
for (var i = 0; i < 500; i++) {
circles.push(new create(i));
}
Hopefully you figure out you need to change the this.r, this.g, and this.b values to match the color you need.
There are just a couple of places to modify (commented below).
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body{
padding: 0; margin: 0;
min-height: 400px; height: 100%;
width: 100%;
overflow: hidden;
background-color: #000000;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>
<script>
// shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
W = window.innerWidth,
H = window.innerHeight,
circles = [];
canvas.width = W;
canvas.height = H;
//Random Circles creator
function create() {
//Place the circles at the center
this.x = W/2;
this.y = H/2;
//Random radius between 2 and 6
this.radius = 2 + Math.random()*3;
//Random velocities
this.vx = -5 + Math.random()*10;
this.vy = -5 + Math.random()*10;
}
for (var i = 0; i < 500; i++) {
circles.push(new create());
}
function draw() {
//Fill canvas with black color
ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = "rgba(0,0,0,0.15)";
ctx.fillRect(0, 0, W, H);
var myColors = ["e8e8e8", "a98547", "ccac7b"];
var which = 0;
//Fill the canvas with circles
for(var j = 0; j < circles.length; j++){
var c = circles[j];
//Create the circles
ctx.beginPath();
//ctx.arc(c.x, c.y, c.radius, 0, Math.PI*2, true);
ctx.fillRect(c.x , c.y, 20, 20); //change to box
//ctx.fillStyle = "rgba("+c.r+", "+c.g+", "+c.b+", 1)";
ctx.fillStyle = "#" + myColors[which].toString();
ctx.fill();
c.x += c.vx;
c.y += c.vy;
c.radius -= .02;
if(c.radius > 3)
circles[j] = new create();
if(which < myColors.length - 1) {
which++;
}
else {
which = 0;
}
}
}
function animate() {
requestAnimFrame(animate);
draw();
}
animate();
</script>
</body>
</html>
Here is the final code, thank you Stephen Brickner for all the help. I've learned a hell of alot
// shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
W = window.innerWidth,
H = window.innerHeight,
circles = [];
canvas.width = W;
canvas.height = H;
//Random Circles creator
function create() {
//Place the circles at the center
this.x = W/2;
this.y = H/2;
//Random radius between 2 and 6
this.radius = 2 + Math.random()*3;
//Random velocities
this.vx = -10 + Math.random()*30;
this.vy = -10 + Math.random()*30;
}
for (var i = 0; i < 100; i++) {
circles.push(new create());
}
function draw() {
//Fill canvas with black color
ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = "rgba(175,38,28,255)";
ctx.fillRect(0, 0, W, H);
var myColors = ["e8e8e8", "a98547", "ccac7b"];
var which = 0;
//Fill the canvas with circles
for(var j = 0; j < circles.length; j++){
var c = circles[j];
//Create the circles
ctx.beginPath();
//ctx.arc(c.x, c.y, c.radius, 0, Math.PI*2, true);
ctx.fillRect(c.x , c.y, 8, 8); //change to box
//ctx.fillStyle = "rgba("+c.r+", "+c.g+", "+c.b+", 1)";
ctx.fillStyle = "#" + myColors[which].toString();
ctx.fill();
c.x += c.vx;
c.y += c.vy;
c.radius -= .02;
if(c.radius > 3)
circles[j] = new create();
if(which < myColors.length - 1) {
which++;
}
else {
which = 0;
}
}
}
function animate() {
requestAnimFrame(animate);
draw();
}
animate();

Does this script have anything that would conflict with other javascript on my page?

I am not quite sure what is going on. I create a fresh html page and set up this JS snippet I found and it works. I apply it to my IPB Forum and it doesn't work at all. Could there be anything here that could conflict with other javascript on my page? Is there any no conflict code I should try to add to accompany this JS snippet? I am fairly new to JS so I could use all the help I could get.
window.onload = function(){
//canvas init
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
//canvas dimensions
var W = window.innerWidth;
var H = window.innerHeight;
canvas.width = W;
canvas.height = H;
//snowflake particles
var mp = 25; //max particles
var particles = [];
for(var i = 0; i < mp; i++)
{
particles.push({
x: Math.random()*W, //x-coordinate
y: Math.random()*H, //y-coordinate
r: Math.random()*4+1, //radius
d: Math.random()*mp //density
})
}
//Lets draw the flakes
function draw()
{
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
ctx.beginPath();
for(var i = 0; i < mp; i++)
{
var p = particles[i];
ctx.moveTo(p.x, p.y);
ctx.arc(p.x, p.y, p.r, 0, Math.PI*2, true);
}
ctx.fill();
update();
}
//Function to move the snowflakes
//angle will be an ongoing incremental flag. Sin and Cos functions will be applied to it to create vertical and horizontal movements of the flakes
var angle = 0;
function update()
{
angle += 0.01;
for(var i = 0; i < mp; i++)
{
var p = particles[i];
//Updating X and Y coordinates
//We will add 1 to the cos function to prevent negative values which will lead flakes to move upwards
//Every particle has its own density which can be used to make the downward movement different for each flake
//Lets make it more random by adding in the radius
p.y += Math.cos(angle+p.d) + 1 + p.r/2;
p.x += Math.sin(angle) * 2;
//Sending flakes back from the top when it exits
//Lets make it a bit more organic and let flakes enter from the left and right also.
if(p.x > W+5 || p.x < -5 || p.y > H)
{
if(i%3 > 0) //66.67% of the flakes
{
particles[i] = {x: Math.random()*W, y: -10, r: p.r, d: p.d};
}
else
{
//If the flake is exitting from the right
if(Math.sin(angle) > 0)
{
//Enter from the left
particles[i] = {x: -5, y: Math.random()*H, r: p.r, d: p.d};
}
else
{
//Enter from the right
particles[i] = {x: W+5, y: Math.random()*H, r: p.r, d: p.d};
}
}
}
}
}
//animation loop
setInterval(draw, 33);
}

html canvas - drawing circle with animation & number

i'm totally new in javascript and css3. What I would like to achieve is to have an animation of drawing circle (in fact four of them). Everything should work like that:
1. animation of circle #1 and after animation put number 78 inside
2. animation of circle #2 and after animation put number 460 inside
3. the same but with number 20 inside
4. same but with 15 inside.
I've find a piece of code here:
http://jsfiddle.net/uhVj6/100/
// requestAnimationFrame Shim
(function() {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
})();
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var endPercent = 101;
var curPerc = 0;
var counterClockwise = false;
var circ = Math.PI * 2;
var quart = Math.PI / 2;
context.lineWidth = 10;
context.strokeStyle = '#ad2323';
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
function animate(current) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.arc(x, y, radius, -(quart), ((circ) * current) - quart, false);
context.stroke();
curPerc++;
if (curPerc < endPercent) {
requestAnimationFrame(function () {
animate(curPerc / 100)
});
}
}
animate();
and I added few lines. But being honest I have to idea how to load four of them (one by one with animation) and then show those numbers inside (usually numbers puted in show under the circle.
Any ideas? thank you!
Here's how I'd do it :
(function() {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
}());
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var circles = [];
createCircle(100,100,'78', function() {
createCircle(270,100,'460', function() {
createCircle(440,100,'20', function() {
createCircle(610,100,'15', null);
});
});
});
function createCircle(x,y,text,callback) {
var radius = 75;
var endPercent = 101;
var curPerc = 0;
var counterClockwise = false;
var circ = Math.PI * 2;
var quart = Math.PI / 2;
context.lineWidth = 10;
context.strokeStyle = '#ad2323';
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
function doText(context,x,y,text) {
context.lineWidth = 1;
context.fillStyle = "#ad2323";
context.lineStyle = "#ad2323";
context.font = "28px sans-serif";
context.fillText(text, x-15, y+5);
}
function animate(current) {
context.lineWidth = 10;
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.arc(x, y, radius, -(quart), ((circ) * current) - quart, false);
context.stroke();
curPerc++;
if (circles.length) {
for (var i=0; i<circles.length; i++) {
context.lineWidth = 10;
context.beginPath();
context.arc(circles[i].x, circles[i].y, radius, -(quart), ((circ) * circles[i].curr) - quart, false);
context.stroke();
doText(context,circles[i].x,circles[i].y,circles[i].text);
}
}
if (curPerc < endPercent) {
requestAnimationFrame(function () {
animate(curPerc / 100)
});
}else{
var circle = {x:x,y:y,curr:current,text:text};
circles.push(circle);
doText(context,x,y,text);
if (callback) callback.call();
}
}
animate();
}
FIDDLE

Categories

Resources