I am making canvas creation by for loop.
Each 20 circles wihch has each different size shows up every second.
I need to stop/escape loop when the total of circles becomes 100.
I tried to stop interval like below. However, it continues looping in console even though the shape of circle stops showing up.
if (circles.length > 100) {
console.log('STOP');
return;
}
Is there any way?
Thank you.
class circle {
constructor() {
this.x = 0;
this.y = 0;
this.r = 0;
}
}
const canvas = document.getElementById('canvas');
const context = canvas.getContext("2d");
let colors = ["#96ceb4","#ffeead","#ff6f69","#ffcc5c","#88d8b0"];
let circles = new Array();
window.addEventListener('load', function(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
context.clearRect( 0, 0, canvas.width, canvas.height );
function draw() {
for (let i=0; i < 20; i++) { //20 blocks at a time
const item = new circle();
item.x = Math.floor(Math.random()*canvas.width);
item.y = Math.floor(Math.random()*canvas.height);
item.r = Math.floor(Math.random()*50);
circles.push(item);
console.log(circles.length);
if (circles.length > 100) {
console.log('STOP');
return;
}
context.beginPath();
context.fillStyle=colors[Math.floor(Math.random()*colors.length)];
context.globalAlpha=0.5;
context.arc(item.x, item.y, item.r, 0, Math.PI*2, true);
context.fill();
};
};
setInterval(draw, 1000);
});
body {overflow: hidden;}
<canvas id="canvas"></canvas>
You need to use the setInterval return to get the id to clear.
class circle {
constructor() {
this.x = 0;
this.y = 0;
this.r = 0;
}
}
var timer;
function stopTimer(){
clearInterval(timer);
}
const canvas = document.getElementById('canvas');
const context = canvas.getContext("2d");
let colors = ["#96ceb4","#ffeead","#ff6f69","#ffcc5c","#88d8b0"];
let circles = new Array();
window.addEventListener('load', function(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
context.clearRect( 0, 0, canvas.width, canvas.height );
function draw() {
for (let i=0; i < 20; i++) { //20 blocks at a time
const item = new circle();
item.x = Math.floor(Math.random()*canvas.width);
item.y = Math.floor(Math.random()*canvas.height);
item.r = Math.floor(Math.random()*50);
circles.push(item);
console.log(circles.length);
if (circles.length > 100) {
console.log('STOP');
stopTimer();
return;
}
context.beginPath();
context.fillStyle=colors[Math.floor(Math.random()*colors.length)];
context.globalAlpha=0.5;
context.arc(item.x, item.y, item.r, 0, Math.PI*2, true);
context.fill();
};
};
timer = setInterval(draw, 1000);
});
body {overflow: hidden;}
<canvas id="canvas"></canvas>
Related
I am having problems when drawing a circle. How do I clear it?
I also still want to maintain the transparent background as much as possible as I am planning on making particles rain down. I also would want to not use images to lower the load on the server.
var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext("2d");
const ParticleFactory = function(){
this.interval = 100;
this.lastOutput = Date.now();
this.particles = [];
}
ParticleFactory.prototype.tick = function(){
if (Date.now() > this.lastOutput + this.interval) {
const particle = new Particle(500, 100, 4);
this.particles.push(particle);
this.lastOutput = Date.now();
}
for (var i=0; i < this.particles.length; i++) {
this.particles[i].tick();
};
}
ParticleFactory.prototype.draw = function(){
for (var i=0; i < this.particles.length; i++) {
this.particles[i].draw();
};
}
ParticleFactory.prototype.del = function(toDelete){
this.particles = this.particles.filter(item => item !== toDelete);
}
const Particle = function(x, y, r){
this.x = x;
this.y = y;
this.r = r;
}
Particle.prototype.tick = function(){
this.x -= 0.1;
}
Particle.prototype.draw = function(){
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
ctx.fillStyle = "rgb(0, 0, 255)";
ctx.fill();
ctx.closePath();
}
// Definitions
let particleFactory = new ParticleFactory;
function draw(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
particleFactory.draw();
}
function tick(){
particleFactory.tick();
draw()
window.requestAnimationFrame(tick)
}
document.addEventListener("DOMContentLoaded", function() {
tick();
});
ctx.clearRect() doesn't clear the curcle that is being draws every tick by Particle.draw()
The dot moves and leaves a trail behind even when ctx.clearRect() is run before every draw.
Please check out this code :
(function() {
var cnv = document.getElementById('canvas');
if (cnv.getContext) {
var ctx = cnv.getContext('2d');
} else {
alert('God Damn it ...');
}
function initialize() {
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
}
function draw() {
for (var i = 0; i < 25; i++) {
width = Math.random() * cnv.width;
height = Math.random() * cnv.height;
ctx.beginPath();
ctx.arc(width, height, 15, 0, Math.PI * 2);
ctx.strokeStyle = '#E1E1E1';
ctx.lineWidth = 1;
ctx.stroke();
}
}
function resizeCanvas() {
cnv.width = window.innerWidth;
cnv.height = window.innerHeight;
draw();
}
initialize();
})();
I have created 25 Circle shape with random position and I want to create an animation that scales up or down in a interval time. I know about setInterval but how should I call my shape to do something on it?
The first thing you will want to do is to have a place to store the position of your circles, since they are all going to be the same radius we can just store the x and y position. For that we can create a Circle function ("class") and have an array of circles:
var circles = []; // Array to store our circles
var minRadius = 1; // The smallest radius we can hit
var maxRadius = 100; // The largest radius we can hit
var currentRadius = 15;// The current radius of all our circles
var scaleBy = 1; // How the radius changes
var cnv = document.getElementById('canvas');
// ...
function initialize() {
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
// Populating the array of circles to use when drawing
for (var i = 0; i < 25; i++) { // Make sure to do this after re-sizing the canvas
width = Math.random() * cnv.width;
height = Math.random() * cnv.height;
circles.push(new Circle(width, height));
}
}
// ...
function Circle(x, y){
this.x = x;
this.y = y;
}
Circle.prototype.draw = function(){
ctx.beginPath();
ctx.arc(this.x, this.y, currentRadius, 0, Math.PI * 2);
ctx.strokeStyle = '#E1E1E1';
ctx.lineWidth = 5;
ctx.stroke();
}
Now that you have some circles when you call draw you can iterate through the array and call circle.draw() for each circle element in your array:
function draw() {
// Clear the screen and draw the circles in our array
ctx.clearRect(0,0, cnv.width, cnv.height);
for (var i = 0; i < circles.length; i++) {
circles[i].draw();
}
}
One note is you will want to use ctx.clearRect(0,0, cnv.width, cnv.height) to clear the screen before drawing.
Finally you can now use setInterval to change the currentRadius (*While there is nothing wrong with setInterval I'd recommend using window.requestAnimationFrame for animation as it's a bit more smooth and efficient method). Then when you call draw it will draw the circles with the new value of currentRadius. In this example I'm going to have it start at 15. Then increase by 1 until it hits maxRadius, then we can flip the sign of scaleBy to start decreasing the radius to make them smaller. Finally when it his our minRadius you can flip the sign of scaleBy again to make it start scaling up again:
var timer = setInterval( function(){
// If we hit our min or max start scaling in the other direction
if(currentRadius > maxRadius || currentRadius < minRadius){
scaleBy *= -1;
}
currentRadius += scaleBy;
draw();
}, 50);
Below is a code snippet of the complete program:
(function() {
var circles = [];
var minRadius = 1;
var maxRadius = 100;
var currentRadius = 15;
var scaleBy = 1;
var cnv = document.getElementById('canvas');
if (cnv.getContext) {
var ctx = cnv.getContext('2d');
} else {
alert('God Damn it ...');
}
function initialize() {
window.addEventListener('resize', resizeCanvas, false);
resizeCanvas();
for (var i = 0; i < 25; i++) {
width = Math.random() * cnv.width;
height = Math.random() * cnv.height;
circles.push(new Circle(width, height));
}
}
function draw() {
ctx.clearRect(0,0, cnv.width, cnv.height);
for (var i = 0; i < circles.length; i++) {
circles[i].draw();
}
}
function resizeCanvas() {
cnv.width = window.innerWidth;
cnv.height = window.innerHeight;
}
function Circle(x, y){
this.x = x;
this.y = y;
}
Circle.prototype.draw = function(){
ctx.beginPath();
ctx.arc(this.x, this.y, currentRadius, 0, Math.PI * 2);
ctx.strokeStyle = '#E1E1E1';
ctx.lineWidth = 5;
ctx.stroke();
}
initialize();
var timer = setInterval( function(){
if(currentRadius > maxRadius || currentRadius < minRadius){
scaleBy *= -1;
}
currentRadius += scaleBy;
draw();
}, 50);
})();
<canvas id="canvas"></canvas>
I am trying to get my balls, in the array, to move directly down the canvas after a short period of time, one after the other to equal exactly 100 balls dropped. I included all of my code to try and show more of what i want the program to do.
Really the balls spawn and a user controls the paddle scoring points for each ball hit. Their are radio buttons that can be checked to make the balls fall faster or slower.
Im just stuck on getting the balls to move down the canvas one at a time.
var posY = 0;
var spawnRateOfDescent = 2;
var spawnRate = 500;
var lastSpawn = -1;
var balls = [100];
var startTime = Date.now();
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
function checkRadio() {
if (document.getElementById("moderate").checked == true) {
spawnRate = 250;
} else if (document.getElementById("hard").checked == true) {
spawnRate = 100;
} else if (document.getElementById("easy").checked == true) {
spawnRate = 500;
}
}
function startGame() {
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
baton = new batonPiece(50, 10, "28E060", 210, 250)
}
function ball() {
this.x = Math.random() * (canvas.width - 30) + 15;
this.y = 0;
this.radius = 10;
this.color = randomColor();
this.draw = function () {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
ctx.fillStyle = randomColor();
ctx.fill();
ctx.closePath();
}
}
var balls = [];
for (var i = 0; i < 100; i++) {
balls[i] = new ball();
balls[i].draw();
}
function batonPiece(width, height, color, x, y) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
function randomColor() {
var letter = "0123456789ABCDEF".split("");
var color = "#";
for (var i = 0; i < 6; i = i + 1) {
color += letter[Math.round(Math.random() * 15)];
}
return color;
}
function moveLeft() {
batonPiece.x -= 1;
}
function moveRight() {
baton.x += 1;
}
function stopMove() {
baton.x = 0;
}
I am looking for a way to fillStyle of all circles in 4 colors: #00ce66, #e3bf37, #cc5543, #a1b7c2.
I want circles to show in the way: 25% of circles are red, 25% circles are yellow… etc. on canvas while the page is loaded.
When I added Math.random() and put inside the colors, circles are black. Please help :-)
(function() {
var width, height, largeHeader, canvas, ctx, circles, target, animateHeader = true;
// Main
initHeader();
addListeners();
function initHeader() {
width = window.innerWidth;
height = window.innerHeight;
target = {x: 0, y: height};
largeHeader = document.getElementById('large-header');
largeHeader.style.height = height+'px';
canvas = document.getElementById('canvas');
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext('2d');
// create particles
circles = [];
for(var x = 0; x < width*0.2; x++) {
var c = new Circle();
circles.push(c);
}
animate();
}
// Event handling
function addListeners() {
window.addEventListener('scroll', scrollCheck);
window.addEventListener('resize', resize);
}
function scrollCheck() {
if(document.body.scrollTop > height) animateHeader = false;
else animateHeader = true;
}
function resize() {
width = window.innerWidth;
height = window.innerHeight;
largeHeader.style.height = height+'px';
canvas.width = width;
canvas.height = height;
}
function animate() {
if(animateHeader) {
ctx.clearRect(0,0,width,height);
for(var i in circles) {
circles[i].draw();
}
}
requestAnimationFrame(animate);
}
// Canvas manipulation
function Circle() {
var _this = this;
// constructor
(function() {
_this.pos = {};
init();
console.log(_this);
})();
function init() {
_this.pos.x = Math.random()*width;
_this.pos.y =-50;
_this.alpha = 0.1+Math.random()*0.9;
_this.scale = 0.1+Math.random()*1;
_this.velocity = Math.random();
}
this.draw = function() {
if(_this.alpha <= 0) {
init();
}
_this.pos.y -= -_this.velocity;
_this.alpha -= 0.0005;
ctx.beginPath();
ctx.arc(_this.pos.x, _this.pos.y, _this.scale*10, 0, 2 * Math.PI, false);
ctx.fillStyle = 'rgba(16,239,173,'+ _this.alpha+')';
ctx.fill();
};
}
})();
You can create an array with the 4 colors and choose a random one at the creation of each circle.
Here is code for the Circle function:
function Circle() {
var _this = this;
// constructor
(function() {
_this.pos = {};
init();
console.log(_this);
})();
function init() {
_this.pos.x = Math.random()*width;
_this.pos.y =-50;
_this.alpha = 0.1+Math.random()*0.9;
_this.scale = 0.1+Math.random()*1;
_this.velocity = Math.random();
var colors = [[0,206,102], [227, 191, 55], [204,85,67], [161,183, 194]];
var random_index = Math.floor(0 + (Math.random() * ((3 + 1) - 0)));
_this.color = colors[random_index];
}
this.draw = function() {
if(_this.alpha <= 0) {
init();
}
_this.pos.y -= -_this.velocity;
_this.alpha -= 0.0005;
ctx.beginPath();
ctx.arc(_this.pos.x, _this.pos.y, _this.scale*10, 0, 2 * Math.PI, false);
var c = _this.color;
ctx.fillStyle = 'rgba('+c[0]+','+c[1]+','+c[2]+','+ _this.alpha+')';
ctx.fill();
};
}
I'm trying to set up a background in canvas and have some small circles just flow throughout the background, eventually I'll change the shapes and add more details in, but I'm just having trouble with the set up.
I know my code is janky, but are there any suggestions to the structure of the code?
var dx = 1;
var dy = 2;
var circle=new Circle(400,30,10);
var timer;
function Circle(x,y,r){
this.x=x;
this.y=y;
this.r=r;
}
function init() {
// Get the canvas element.
canvas = document.getElementById("canvas");
if (canvas.getContext) {
ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
}
timer=setInterval(draw, 10);
return timer;
}
function gradient (){
var my_gradient=ctx.createLinearGradient(0,0,1000,0);
my_gradient.addColorStop(0,"black");
my_gradient.addColorStop(1,"white");
ctx.fillStyle=my_gradient;
ctx.fillRect(0,0,1000,1000);
ctx.rect(0, 0, 1000, 1000);
stars();
}
function stars(){
for (i = 0; i <= 50; i++) {
// Get random positions for stars
var x = Math.floor(Math.random() * 1000)
var y = Math.floor(Math.random() * 1000)
ctx.fillStyle = "yellow";
//if (x < 30 || y < 30) ctx.fillStyle = "black";
ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
}
function move(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = gradient.my_gradient;
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = "#003300";
drawBall(circle);
if (circle.x +dx > canvas.width || circle.x +dx < 0)
dx=-dx;
if(circle.y+dy>bar.y && circle.x>bar.x && circle.x<bar.x+barImg.width)
dy=-dy;
if (circle.y +dy > canvas.height || circle.y +dy < 0)
dy=-dy;
circle.x += dx;
circle.y += dy;
}
I tried to code a working exemple. Here stars are popping up continuously.
HTML
<!DOCTYPE html>
<html>
<head>
<title>Exemple</title>
</head>
<body>
<canvas id="viewport"></canvas>
<script src='test.js'></script>
</body>
</html>
JS
var doc = document;
var canvas = doc.getElementById('viewport');
var ctx = canvas.getContext('2d');
var settings = {
area : {
height : 100,
width : 100
}
};
canvas.width = settings.area.width;
canvas.height = settings.area.height;
function draw() {
for (var i = 10; i--;) {
var x = Math.floor(Math.random() * 1000)
var y = Math.floor(Math.random() * 1000)
ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI * 2, true);
ctx.fillStyle = "yellow";
ctx.closePath();
ctx.fill();
}
}
function gameLoop (render, element) {
var running, lastFrame = +new Date;
function loop( now ) {
// stop the loop if render returned false
if ( running !== false ) {
requestAnimationFrame( loop, element );
running = render( now - lastFrame );
lastFrame = now;
}
}
loop( lastFrame );
}
gameLoop (function (deltaT) {
draw();
}, canvas );
Here is the fiddle : https://jsfiddle.net/q4q0uLht/
----- EDIT -----
/*
Basic config
*/
var doc = document,
canvas = doc.getElementById('viewport'),
ctx = canvas.getContext('2d');
var settings = {
canvas: {
height: 200,
width: 300
}
}
canvas.height = settings.canvas.height;
canvas.width = settings.canvas.width;
canvas.style.border = '1px #000 solid';
/*
easy gets a random number, inside a range of [0, x);
*/
function getRandomNumber(x) {
return parseInt(Math.random() * x, 10);
}
/*
Checks if the obj passed in argument is still in the canvas limits
*/
function incorrectPosition(obj) {
return obj.x < 0 || obj.y < 0 || obj.x > settings.canvas.width || obj.y > settings.canvas.height;
}
/*
stars array and Star object.
*/
var stars = [];
function Star(r) {
this.x = getRandomNumber(canvas.width);
this.y = getRandomNumber(canvas.height);
this.r = r || 10;
this.move = function(dx, dy) {
this.x += dx;
this.y += dy;
};
}
/*
This function adds new stars,
calculates new coordinates of each star,
and removes them from the stars array
when they are out of the canvas limits.
*/
function update() {
var len = stars.length;
if (len < 10) {
stars.push(new Star());
}
for (var i = len; i--;) {
var star = stars[i];
star.move(1, 2);
if (incorrectPosition(star)) {
stars.splice(i, 1);
}
}
}
/*
This function clears the canvas each turn and
draws each star which is stored inside the stores array.
*/
function draw() {
ctx.clearRect(0, 0, settings.canvas.width, settings.canvas.height);
var len = stars.length;
for (var i = len; i--;) {
var star = stars[i];
ctx.beginPath();
ctx.arc(star.x, star.y, 3, 0, Math.PI * 2, true);
ctx.fillStyle = "yellow";
ctx.closePath();
ctx.fill();
}
}
// Here is the loop inside which are called functions
setInterval(loop, 33);
function loop() {
update(); // update first
draw(); // then draw
}
<!DOCTYPE html>
<html>
<head>
<title>Exemple</title>
</head>
<body>
<canvas id="viewport"></canvas>
<script src='test.js'></script>
</body>
</html>