Repeating task Using nested Loops - javascript

I am trying to use the following code to draw 9 circles horizontally and 9 circles vertically on a canvas.
I have inserted a nested for-loop for this operation, but unfortunately I am having only one horizontal line of 9 circles.
Can anyone help please?
<canvas id="sCanvas" width="550" height="1000"> </canvas>
<script>
var randomColour;
var size;
var xPos;
var yPos;
var ctx;
var i;
var j;
function drawCircle(size, x, y, randomColour) {
ctx.beginPath();
ctx.arc(x, y, size / 2, 0, 2 * Math.PI, randomColour);
ctx.fill();
ctx.fillStyle = randomColour;
ctx.stroke();
ctx.strokeStyle = randomColour;
}
var c = document.getElementById("sCanvas");
ctx = c.getContext("2d");
xPos = 20;
yPos = 20;
for (j = 0; j < 9; j++) {
randomColour = "hsl(" + 360 * Math.random() + ",50%,50%)";
drawCircle(30, xPos, yPos, randomColour);
xPos += 50;
for (i = 0; i < 9; i++) {
randomColour = "hsl(" + 360 * Math.random() + ",50%,50%)";
drawCircle(30, xPos, yPos, randomColour);
xPos += 50;
}
yPos += 30;
}
</script>

You have to reset your xPos after every iteration, otherwise you just keep advancing right. This will work:
for (j = 0; j < 9; j++) {
xPos = 20; //Moved this in here from outside
randomColour = "hsl(" + 360 * Math.random() + ",50%,50%)";
drawCircle(30, xPos, yPos, randomColour);
for (i = 0; i < 9; i++) {
randomColour = "hsl(" + 360 * Math.random() + ",50%,50%)";
drawCircle(30, xPos, yPos, randomColour);
xPos += 50;
}
yPos += 50;
}
Fiddle

Related

Create a "tail" for an object that is orbiting

Edit
Here is a JSFiddle with the code for the "tail" function commenting out.Solar System JSFiddle
I have this object I am working on that has an object orbiting a center mass. That works perfectly.
I am now trying to add a trailing line or "tail" that follows behind the planet.
My tail object looks like this:
function Tail(maxLength){
this.points = [];
this.maxLength = maxLength;
this.addPoint = function(point){
for(var i = Math.min(maxLength, this.points.length); i < maxLength; i++){
this.points[i] = this.points[i - 1];
}
this.points[0] = point;
}
this.draw = function(ctx){
for(var i = 1; Math.min(maxLength, this.points.length); i++){
if(i < maxLength - 20){
ctx.globalAlpha = 1;
} else {
ctx.globalAlpha = (this.maxLength - i) / 20;
}
ctx.beginPath();
ctx.moveTo(this.points[i - 1].x, this.points[i - 1].y);
ctx.lineTo(this.points[i].x, this.points[i].y);
ctx.stroke();
}
ctx.globalAlpha = 1;
}
}
The addPoint function takes an object that looks like '{x: currentX, y: currentY}
currentX and currentY are the x and y point of the object when ever it gets called.
I am lost on how I need to add the point to the points array and then draw based on those coordinates.
I modified your version to working condition
var canvas, width, height, ctx;
var bodies = [];
function init(){
canvas = document.getElementById("space-time");
width = window.innerWidth;
height = window.innerHeight;
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext('2d');
createBodies();
setInterval(function(){
updateSystem();
updateBodies(0.01);
ctx.clearRect(0, 0, width, height);
drawBodies();
}, 10);
}
function createBodies(){
bodies.push(new Body((this.width / 2) - 250, (this.height / 2) - 300, 200, 0, 1, 10, "#14c71d", true));
bodies.push(new Body((this.width / 2) + 100, (this.height / 2) + 100, 350, 0, 1, 5, "#de2d16", true));
bodies.push(new Body(this.width / 2, this.height / 2, 0, 0, 1000000, 30, "#FF8501", false)); //sun
}
function drawBodies(){
for(var i = 0; i < bodies.length; i++){
bodies[i].draw(ctx);
}
}
function updateBodies(dt){
for(var i = 0; i < bodies.length; i++){
bodies[i].update(dt);
}
}
function updateSystem(){
var G = 10;
for(var i = 0; i < bodies.length; i++){
for(var j = 0; j < bodies.length; j++){
if(i === j) continue;
var b1 = bodies[i];
var b2 = bodies[j];
var dist = Math.sqrt((b1.x - b2.x) * (b1.x - b2.x) + (b1.y - b2.y) * (b1.y - b2.y));
var force = G * (b1.m * b2.m) / dist / dist;
var nx = (b2.x - b1.x) / dist;
var ny = (b2.y - b1.y) / dist;
b1.ax += nx * force / b1.m;
b1.ay += ny * force / b1.m;
b2.ax -= nx * force / b2.m;
b2.ay -= ny * force / b2.m;
}
}
}
function Body(x, y, v, angle, mass, radius, color, hasTail){
this.x = x;
this.y = y;
this.vx = v * Math.cos(angle);
this.vy = v * Math.sin(angle);
this.m = mass;
this.radius = radius;
this.color = color;
this.ax = 0;
this.ay = 0;
if (hasTail) {
this.tail = new Tail(50);
}
this.update = function(dt){
this.vx += this.ax * dt;
this.vy += this.ay * dt;
this.x += this.vx * dt;
this.y += this.vy * dt;
this.ax = 0;
this.ay = 0;
if(this.tail){
this.tail.addPoint({x: this.x, y: this.y});
}
}
this.draw = function(ctx){
ctx.strokeStyle = this.color;
ctx.fillStyle = this.color;
ctx.shadowColor = this.color;
ctx.shadowBlur = 5;
if(this.tail){
this.tail.draw(ctx);
}
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 6.28);
ctx.fill();
}
}
function Tail(maxLength){
this.points = [];
this.maxLength = maxLength;
this.addPoint = point => {
this.points = [point].concat(this.points).slice(0, this.maxLength);
}
this.draw = function(ctx){
for(var i = 1; i < this.points.length; i++){
ctx.beginPath();
if(i < maxLength - 20){
ctx.globalAlpha = 1;
} else {
ctx.globalAlpha = (this.maxLength - i) / 20;
}
ctx.moveTo(this.points[i - 1].x, this.points[i - 1].y);
ctx.lineTo(this.points[i].x, this.points[i].y);
ctx.stroke();
}
ctx.globalAlpha = 1;
}
}
#space-time {
background-color: #1a1a1c;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Solar System AJ</title>
</head>
<body onload="init();">
<canvas id="space-time"></canvas>
</body>
</html>
You can visualisate the track of objects, if you fill frame with background with low opacity instead of clearing it:
var canvas, width, height, ctx;
var bodies = [];
function init(){
canvas = document.getElementById("space-time");
width = window.innerWidth;
height = window.innerHeight;
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext('2d');
createBodies();
setInterval(function(){
updateSystem();
updateBodies(0.01);
// ctx.clearRect(0, 0, width, height);
// All magic here:
ctx.fillStyle = `rgba(0, 0, 0, .05)`;
ctx.shadowBlur = 0;
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawBodies();
}, 10);
}
function createBodies(){
bodies.push(new Body((this.width / 2) - 250, (this.height / 2) - 300, 200, 0, 1, 10, "#14c71d", true));
bodies.push(new Body((this.width / 2) + 100, (this.height / 2) + 100, 350, 0, 1, 5, "#de2d16", true));
bodies.push(new Body(this.width / 2, this.height / 2, 0, 0, 1000000, 30, "#FF8501", false)); //sun
}
function drawBodies(){
for(var i = 0; i < bodies.length; i++){
bodies[i].draw(ctx);
}
}
function updateBodies(dt){
for(var i = 0; i < bodies.length; i++){
bodies[i].update(dt);
}
}
function updateSystem(){
var G = 10;
for(var i = 0; i < bodies.length; i++){
for(var j = 0; j < bodies.length; j++){
if(i === j) continue;
var b1 = bodies[i];
var b2 = bodies[j];
var dist = Math.sqrt((b1.x - b2.x) * (b1.x - b2.x) + (b1.y - b2.y) * (b1.y - b2.y));
var force = G * (b1.m * b2.m) / dist / dist;
var nx = (b2.x - b1.x) / dist;
var ny = (b2.y - b1.y) / dist;
b1.ax += nx * force / b1.m;
b1.ay += ny * force / b1.m;
b2.ax -= nx * force / b2.m;
b2.ay -= ny * force / b2.m;
}
}
}
function Body(x, y, v, angle, mass, radius, color, hasTail){
this.x = x;
this.y = y;
this.vx = v * Math.cos(angle);
this.vy = v * Math.sin(angle);
this.m = mass;
this.radius = radius;
this.color = color;
this.ax = 0;
this.ay = 0;
this.update = function(dt){
this.vx += this.ax * dt;
this.vy += this.ay * dt;
this.x += this.vx * dt;
this.y += this.vy * dt;
this.ax = 0;
this.ay = 0;
}
this.draw = function(ctx){
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, 6.28);
ctx.strokeStyle = this.color;
ctx.fillStyle = this.color;
ctx.shadowColor = this.color;
ctx.shadowBlur = 5;
ctx.fill();
}
}
#space-time {
background-color: #1a1a1c;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Solar System AJ</title>
</head>
<body onload="init();">
<canvas id="space-time"></canvas>
</body>
</html>

How to remove straight lines from multiple rotated arc on canvas?

I want to create Star Trail on canvas.
The idea to create it, i have to draw multiple images that increment size, and some calculation for the next image position. Store multiple image in array. Choose the image randomly each draw and draw it with different angle each image.
I made it.
var canvas=document.getElementById('canvas'),ctx=canvas.getContext('2d');
var starsimage=['https://1.bp.blogspot.com/-prwJzDDwQRU/XTjNfQhQnDI/AAAAAAAACBo/wpbhqkfc-9wQQeg95O6poFbFyu77q4vdACLcBGAs/s1600/CircleWhite100.png','https://1.bp.blogspot.com/-lm4F2UOMCdE/XTjNghXjrOI/AAAAAAAACB0/L6pya6HQk0cU5R5RP9Wo_-Bm_UhO_qCawCLcBGAs/s1600/CircleWhite75.png','https://1.bp.blogspot.com/-7ennrlohEo0/XTjNfoji8KI/AAAAAAAACBw/G0SQhFEZ0IMMf2z3g_Mvbon97BMktSw-QCLcBGAs/s1600/CircleWhite50.png','https://1.bp.blogspot.com/-I7aeA-F4OWY/XTjNfiO-rxI/AAAAAAAACBs/lKYC-SmaWSQWc0PoPVdgCHeyDUPdoJd7gCLcBGAs/s1600/CircleWhite25.png','https://1.bp.blogspot.com/-V2Ak6YU2XNA/XTjNh7iIwZI/AAAAAAAACCA/tNo5Ho6iC4gndoftPJfSCInGqgyfcd6nQCLcBGAs/s1600/TrailBlue100.png','https://1.bp.blogspot.com/-ylpi3AZvces/XTjNi7uy1kI/AAAAAAAACCM/uWZ7_zYRXXQN4q3QRSngCFeT5RoEeG4xgCLcBGAs/s1600/TrailBlue75.png','https://1.bp.blogspot.com/-NoPiS9k0o0U/XTjNivmKVjI/AAAAAAAACCI/gZzDMn9zomMWrQc2hhKfNB9JK0ruh2wyQCLcBGAs/s1600/TrailBlue50.png','https://1.bp.blogspot.com/-KYkWDwtmS7A/XTjNiSE8Y_I/AAAAAAAACCE/jDyTIbJqBBs3FP1tyGFICjShyx_GCCy0gCLcBGAs/s1600/TrailBlue25.png'];
var stars=new Array();var starsloaded=0;
var xpos=0,ypos=0,w=25,h=25,ix=0,xa=25,ya=25,rot=0,ang=0;
for(var i=0;i<starsimage.length;i++){//load images
stars[i]=new Image();stars[i].src=starsimage[i];
stars[i].onload=function(){starsloaded++;if(starsloaded==starsimage.length){
draw();
}}
}
function minmaxdraw(min,max){return Math.floor(Math.random() * (max - min + 1)) + min}
function randomindeximage(l){return Math.floor(Math.random()*l)}
function draw(){
xpos=canvas.width/2;ypos=canvas.height/2;
for(var i=0;i<500;i++){//500 images
xy=minmaxdraw(2,4);//gap randomly
ix=randomindeximage(starsimage.length);
w+=xy;h+=xy;ang=minmaxdraw(0,359);
if(i>0){xa=w-xa;ya=h-ya;xpos=xpos-xa/2;ypos=ypos-ya/2;
ctx.save();
ctx.translate(xpos+w/2,ypos+h/2);
rot=ang*Math.PI/180;ctx.rotate(rot);
ctx.drawImage(stars[ix],-w/2,-h/2,w,h);
ctx.restore();
xa=w;ya=h;
}
else{ctx.drawImage(stars[ix],xpos,ypos,w,h)}
}
}
body{margin:0;padding:0;position:relative;background:#101010;height:580px;width:100%}
#canvas{z-index:2;background-color:transparent;position:absolute;width:100vw;left:50%;top:50%;transform:translate(-50%,-50%)}
body:before{content:'';z-index:1;position:absolute;width:100%;height:100%;left:0;top:0;background:linear-gradient(15deg, #1458ac, #000);}
<canvas id="canvas" width="640" height="580"></canvas>
But. the quality is bad. Because the image size is static, blurry if the increment width is larger than actually image size, and the small stars is barely visible
I think, it's better to create it with multiple arc.
The idea is same, i have to draw multiple arc. But, i'm dummy, i made with two canvas, different angle each canvas. (It's actually same with my work before, but at the time, i use 1 image that have cutted circle). Because if i made it only on one canvas, the straight line appears. So, i draw multiple arc in each canvas. It works, and no straight line appears. (It's still basic arc)
var canvas1=document.getElementById('canvas1'),ctx=canvas1.getContext('2d'),canvas2=document.getElementById('canvas2'),ctx2=canvas2.getContext('2d');var xy=0;var angle=new Array();
function minmaxdraw(min,max){return Math.floor(Math.random() * (max - min + 1)) + min}
function randomindeximage(l){return Math.floor(Math.random()*l)}
function draw1(){
var xpos=canvas1.width/2;var ypos=canvas1.height/2;var r=15,ang=0;
ctx.beginPath();
for(var i=0;i<55;i++){
r+=minmaxdraw(4,9);
ctx.moveTo(xpos + r, ypos);
ctx.arc(xpos, ypos, r, 0, 1.5*Math.PI,true);
}ctx.stroke();
}
function draw2(){
var xpos=canvas2.width/2;var ypos=canvas2.height/2;var r=15;
ctx2.beginPath();
for(var t=0;t<55;t++){
r+=minmaxdraw(4,9);
ctx2.moveTo(xpos, ypos + r);
ctx2.arc(xpos, ypos, r, Math.PI / 2, Math.PI);
}ctx2.stroke();
}
draw1();draw2();
body{margin:0;padding:0;position:relative;height:480px;width:100%}
.canvas{background-color:transparent;position:absolute;width:100vw;left:50%;top:50%;margin:-50% 0 0 -50%}
<canvas id='canvas1' class='canvas' width='640' height='480'></canvas>
<canvas id='canvas2' class='canvas' width='640' height='480'></canvas>
It's not rotated yet.
So, if i want make circle trail, i have to rotate each arc randomly like i did before with image, but the problem is here. The straight lines come wickedly.
var canvas1=document.getElementById('canvas1'),ctx=canvas1.getContext('2d'),canvas2=document.getElementById('canvas2'),ctx2=canvas2.getContext('2d');var xy=0;var angle=new Array();
function minmaxdraw(min,max){return Math.floor(Math.random() * (max - min + 1)) + min}
function randomindeximage(l){return Math.floor(Math.random()*l)}
function draw1(){
var xpos=canvas1.width/2;var ypos=canvas1.height/2;
var r=15,ang=0,dx=0,dy=0;
ctx.beginPath();
for(var i=0;i<55;i++){//200 images
ang=minmaxdraw(0,359);
dx=minmaxdraw(0,canvas1.width),dy=minmaxdraw(0,canvas1.height);
r+=minmaxdraw(3,7);
ang=Math.atan2(dx-xpos,dy-ypos);angle[i]=ang;
ctx.moveTo(xpos, ypos);
ctx.arc(xpos, ypos, r, ang + 0 * Math.PI, ang + Math.PI * 1.5,true);
}ctx.stroke();
}
function draw2(){
var xpos=canvas2.width/2;var ypos=canvas2.height/2;var r=15;
ctx2.beginPath();
for(var t=0;t<55;t++){
r+=minmaxdraw(3,7);
ctx2.moveTo(xpos, ypos + r);
ctx2.arc(xpos, ypos, r, angle[t] + Math.PI / 2, angle[t] + Math.PI);
}ctx2.stroke();
}
draw1();draw2();
body{margin:0;padding:0;position:relative;height:480px;width:100%}
.canvas{background-color:transparent;position:absolute;width:100vw;left:50%;top:50%;margin:-50% 0 0 -50%}
<canvas id='canvas1' class='canvas' width='640' height='480'></canvas>
<canvas id='canvas2' class='canvas' width='640' height='480'></canvas>
Is there any solution to remove that straight lines?
Not sure why you have the calls to moveTo and maybe I just didn't understand the question but I just moved beginPath and stroke inside the loops.
var canvas1 = document.getElementById('canvas1'),
ctx = canvas1.getContext('2d'),
canvas2 = document.getElementById('canvas2'),
ctx2 = canvas2.getContext('2d');
var xy = 0;
var angle = new Array();
function minmaxdraw(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
function randomindeximage(l) {
return Math.floor(Math.random() * l)
}
function draw1() {
var xpos = canvas1.width / 2;
var ypos = canvas1.height / 2;
var r = 15,
ang = 0,
dx = 0,
dy = 0;
for (var i = 0; i < 55; i++) { //200 images
ang = minmaxdraw(0, 359);
dx = minmaxdraw(0, canvas1.width), dy = minmaxdraw(0, canvas1.height);
r += minmaxdraw(3, 7);
ang = Math.atan2(dx - xpos, dy - ypos);
angle[i] = ang;
ctx.beginPath();
ctx.arc(xpos, ypos, r, ang + 0 * Math.PI, ang + Math.PI * 1.5, true);
ctx.stroke();
}
}
function draw2() {
var xpos = canvas2.width / 2;
var ypos = canvas2.height / 2;
var r = 15;
for (var t = 0; t < 55; t++) {
r += minmaxdraw(3, 7);
ctx2.beginPath();
ctx2.arc(xpos, ypos, r, angle[t] + Math.PI / 2, angle[t] + Math.PI);
ctx2.stroke();
}
}
draw1();
draw2();
body {
margin: 0;
padding: 0;
position: relative;
height: 550px;
width: 100%
}
.canvas {
background-color: transparent;
position: absolute;
width: 100vw;
left: 50%;
top: 50%;
margin: -50% 0 0 -50%
}
<canvas id='canvas1' class='canvas' width='640' height='480'></canvas>
<canvas id='canvas2' class='canvas' width='640' height='480'></canvas>
Also I don't understand why you have 2 canvases. It works fine with just one
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
var xy = 0;
var angle = new Array();
function minmaxdraw(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
function randomindeximage(l) {
return Math.floor(Math.random() * l)
}
function draw1() {
var xpos = canvas.width / 2;
var ypos = canvas.height / 2;
var r = 15,
ang = 0,
dx = 0,
dy = 0;
for (var i = 0; i < 55; i++) { //200 images
ang = minmaxdraw(0, 359);
dx = minmaxdraw(0, canvas.width), dy = minmaxdraw(0, canvas.height);
r += minmaxdraw(3, 7);
ang = Math.atan2(dx - xpos, dy - ypos);
angle[i] = ang;
ctx.beginPath();
ctx.arc(xpos, ypos, r, ang + 0 * Math.PI, ang + Math.PI * 1.5, true);
ctx.stroke();
}
}
function draw2() {
var xpos = canvas.width / 2;
var ypos = canvas.height / 2;
var r = 15;
for (var t = 0; t < 55; t++) {
r += minmaxdraw(3, 7);
ctx.beginPath();
ctx.arc(xpos, ypos, r, angle[t] + Math.PI / 2, angle[t] + Math.PI);
ctx.stroke();
}
}
draw1();
draw2();
<canvas id='canvas' class='canvas' width='640' height='480'></canvas>
The reason you got lines before is all arc does is add points.
arc is effectively this
// pseudo code
function arc(x, y, radius, start, end) {
const numSegments = 100; // no idea what number real arc uses here
for (let i = 0; i < numSegments; ++i) {
const angle = start + (end - start) * i / numSegments;
ctx.lineTo(Math.cos(angle) * radius, Math.sin(angle) * radius);
}
}
As you can see the code above just adds the points around the arc. So if you do a
ctx.moveTo(x, y);
ctx.arc(x, y, ...);
you're adding a point in the center of the arc and then more points to the edge. That's why you're getting a line from the centers to the edge of each arc.
If you wanted to leave the code the same as you had it and just stroke all the arcs at once then you'd need to change the moveTo to move to the edge of the arc instead of the center.
ctx.moveTo(x + Math.cos(start) * radius, y + Math.sin(start) * radius);
ctx.arc(x, y, radius, start, ...);

Bad canvas context

I am currently working on a canvas animation, it works pretty well.
You can check out my code below:
var canvas = document.getElementById('bubble'),
ctx = canvas.getContext('2d');
ctx.save();
var wW = canvas.width = window.innerWidth,
wH = canvas.height = window.innerHeight;
var particles = [];
var particleIndex = 0;
var dx = dy = distance = 0;
function Particle(){
this.x = Math.random() * wW;
this.y = Math.random() * wH;
this.rad = 20;
this.color = "blue";
this.vX = Math.random() * (1.01 - (-1)) + (-1);
this.vY = Math.random() * (1.01 - (-1)) + (-1);
particles[particleIndex] = this;
particleIndex++;
}
Particle.prototype.draw = function(){
this.x += this.vX;
this.y += this.vY;
this.collision();
//outer
ctx.beginPath();
ctx.arc(this.x, this.y, this.rad, 0, Math.PI * 2);
ctx.stroke();
//center
ctx.beginPath();
ctx.arc(this.x, this.y, this.rad/10, 0, Math.PI * 2);
ctx.fillStyle="red";
ctx.fill();
}
Particle.prototype.collision = function(){
if(this.x + this.rad >= wW || this.x - this.rad <= 0){
this.vX *= -1;
}
if(this.y + this.rad >= wH || this.y - this.rad <= 0){
this.vY *= -1;
}
}
function line(){
for(var i=0; i < particles.length; i++){
for(var j=0; j < particles.length; j++){
dx = particles[i].x - particles[j].x;
dy = particles[i].y - particles[j].y;
distance = Math.sqrt(dx * dx + dy * dy);
if(distance <= 60){
ctx.beginPath();
ctx.moveTo(particles[i].x, particles[i].y);
ctx.lineTo(particles[j].x, particles[j].y);
ctx.strokeStyle="rgba(0,0,0,"+ 6/distance +")";
ctx.stroke();
}
}
}
}
for(var i=0; i<20; i++){
new Particle();
}
function anim(){
requestAnimationFrame(anim);
ctx.clearRect(0,0,wW,wH);
line();
for(var i=0; i < particles.length; i++){
particles[i].draw();
}
}
anim();
html, body{
padding:0;
margin:0;
}
body{
height: 100%;
width: 100%;
overflow:hidden;
}
<canvas id="bubble"></canvas>
I have a function line() which calculates the space between each circle and draws line between them.
In this function, i put this :
ctx.strokeStyle="rgba(0,0,0,"+ 6/distance +")";
I want to change the line opacity as a function of distance. However, it changes the circle opacity and not the line. I don't understand why, I tried to restore the context but it did not work..
Thank you !
You can store it to a variable before starting the line drawing and revert it afterwards
function line() {
var originalStrokeStyle = ctx.strokeStyle;
for (var i = 0; i < particles.length; i++) {
for (var j = 0; j < particles.length; j++) {
dx = particles[i].x - particles[j].x;
dy = particles[i].y - particles[j].y;
distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 60) {
ctx.beginPath();
ctx.moveTo(particles[i].x, particles[i].y);
ctx.lineTo(particles[j].x, particles[j].y);
ctx.strokeStyle = "rgba(0,0,0," + 6 / distance + ")";
ctx.stroke();
}
}
}
ctx.strokeStyle = originalStrokeStyle;
}
Updated demo at http://codepen.io/gpetrioli/pen/aBZpXJ

Random number of Circles

I got this code to draw 10 normal and 10 splattered circles on canvas, but I need to draw a random number of circles between 1 and 20. How can I do it?
var randomColour;
var randomSize;
var randomNumber;
var xPos;
var yPos;
var i;
var j;
c = document.getElementById("myCanvas");
ctx = c.getContext("2d");
function drawFilledCircle(size,xPos,yPos,colour){
ctx.beginPath();
ctx.arc(xPos,yPos,size,0,2*Math.PI);
ctx.fillStyle = colour;
ctx.fill();
}
function drawSplatter(size,xPos,yPos,colour){
for(j=0;j<10;j++){
var splatSize = size / Math.round(Math.random()*30);
drawFilledCircle(splatSize,xPos + Math.round(Math.random()*40),yPos + Math.round(Math.random()*50),colour);
}
}
for(i=0;i<10;i++){
randomColour = '#' + Math.random().toString(16).substring(2, 8);
randomSize = Math.round(Math.random()*50);
xPos = Math.round(Math.random()*640);
yPos = Math.round(Math.random()*480);
drawFilledCircle(randomSize, xPos, yPos, randomColour);
drawSplatter(randomSize, xPos, yPos, randomColour);
}
Try this
//Find random number between 1 and 20.
var rand = Math.floor(Math.random() * 20) + 1;
for( i = 0; i < rand; i++ ){
randomColour = '#' + Math.random().toString(16).substring(2, 8);
randomSize = Math.round(Math.random()*50);
xPos = Math.round(Math.random()*640);
yPos = Math.round(Math.random()*480);
drawFilledCircle(randomSize, xPos, yPos, randomColour);
drawSplatter(randomSize, xPos, yPos, randomColour);
}

how can I make change the color of an object with a condition using rgba colors in canvas

I'm trying to make a blackhole simulation, and although I'm almost done, I wish to make disappear the dots that are drawn on the blackhole progressively, here is my code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>test trou noir</title>
<script>
var canvas, ctx;
var blackhole;
var circle;
var circles = new Array();
var G = 6.67e-11,//gravitational constant
pixel_G = G/1e-11,
c = 3e8, //speed of light (m/s)
M = 12e31,// masseof the blackhole in kg (60 solar masses)
pixel_M = M/1e32
Rs = (2 * G * M) / 9e16, //Schwarzchild radius
pixel_Rs = Rs/1e3, // scaled radius
ccolor=128;
function update() {
var pos, i, distance, somethingMoved = false;
for (i = 0; i < circles.length; i++) {
pos = circles[i].position;
distance = Math.sqrt(((pos.x - 700) * (pos.x - 700)) + ((pos.y - 400) * (pos.y - 400)));
if (distance > pixel_Rs && visible(circles[i])) {
var delta = new Vector2D(0, 0);
var forceDirection = Math.atan2(pos.y - 400, pos.x - 700);
var evelocity = Math.sqrt( (2*pixel_G*pixel_M)/(distance*1e-2));
delta.x += Math.cos(forceDirection) * evelocity;
delta.y += Math.sin(forceDirection) * evelocity;
pos.x += delta.x;
pos.y += delta.y;
somethingMoved = true;
}
}
if (somethingMoved) {
drawEverything();
requestAnimationFrame(update);
} else {
ccolor -=10;
};
}
function visible(ball) {
return ball.position.x > ball.radius && ball.position.x < canvas.width - ball.radius &&
ball.position.y > ball.radius && ball.position.y < canvas.height - ball.radius;
}
function drawEverything() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
blackhole.draw(ctx);
for (var i = 0; i < circles.length; i++) {
if (visible(circles[i])) {
circles[i].draw(ctx);
}
}
}
function init() {
canvas = document.getElementById("space");
ctx = canvas.getContext('2d');
blackhole = new Ball(pixel_Rs, {
x: 700,
y: 400
}, "black");
for (var i = 0; i < 200; i++) {
var vec2D = new Vector2D(Math.floor(Math.random() * 1400), Math.floor(Math.random() * 800));
circle = new Ball(5, vec2D, 'rgba('+ccolor+','+ccolor+','+ccolor+',1)');
circles.push(circle);
}
drawEverything();
requestAnimationFrame(update);
}
function Ball(radius, position, color) {
this.radius = radius;
this.position = position;
this.color = color;
}
Ball.prototype.draw = function(ctx) {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.radius, 0, 2 * Math.PI);
ctx.closePath();
ctx.fill();
};
function Vector2D(x, y) {
this.x = x;
this.y = y;
}
window.onload = init;
</script>
<style>
body {
background-color: #021c36;
margin: 0px;
}
</style>
</head>
<body>
<canvas id="space" , width="1400" , height="800">
</canvas>
</body>
</html>
now as you can see, I created a variable called ccolor which is integrated in the rgba code, but I don't know why the colors don't tend to zero, so the circles that are inside the blackhole gradually disappear, if someone could lend me a hand it'd be great
In update, if any circles[i] is captured by the Blackhole you decrement its this.color. It might be easier if you change this.color to an integer that you use to create a fillStyle:
ctx.fillStyle='rgba(' + this.color + ',' + this.color + ',' + this.color + ',1)'.
Here's a quick demo:
View this demo Full Page or the black hole is off-screen
var canvas, ctx;
var blackhole;
var circle;
var circles = new Array();
var G = 6.67e-11, //gravitational constant
pixel_G = G / 1e-11,
c = 3e8, //speed of light (m/s)
M = 12e31, // masseof the blackhole in kg (60 solar masses)
pixel_M = M / 1e32
Rs = (2 * G * M) / 9e16, //Schwarzchild radius
pixel_Rs = Rs / 1e3, // scaled radius
ccolor = 128;
function update() {
var pos, i, distance, somethingMoved = false;
for (i = 0; i < circles.length; i++) {
pos = circles[i].position;
distance = Math.sqrt(((pos.x - 700) * (pos.x - 700)) + ((pos.y - 400) * (pos.y - 400)));
if (distance > pixel_Rs && visible(circles[i])) {
var delta = new Vector2D(0, 0);
var forceDirection = Math.atan2(pos.y - 400, pos.x - 700);
var evelocity = Math.sqrt((2 * pixel_G * pixel_M) / (distance * 1e-2));
delta.x += Math.cos(forceDirection) * evelocity;
delta.y += Math.sin(forceDirection) * evelocity;
pos.x += delta.x;
pos.y += delta.y;
somethingMoved = true;
} else {
circles[i].color -= 0.50;
}
}
if (somethingMoved) {
drawEverything();
requestAnimationFrame(update);
};
}
function visible(ball) {
return ball.position.x > ball.radius && ball.position.x < canvas.width - ball.radius &&
ball.position.y > ball.radius && ball.position.y < canvas.height - ball.radius;
}
function drawEverything() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
blackhole.draw(ctx);
for (var i = 0; i < circles.length; i++) {
if (visible(circles[i])) {
circles[i].draw(ctx);
}
}
}
function init() {
canvas = document.getElementById("space");
ctx = canvas.getContext('2d');
blackhole = new Ball(pixel_Rs, {
x: 700,
y: 400
}, 0);
for (var i = 0; i < 200; i++) {
var vec2D = new Vector2D(Math.floor(Math.random() * 1400), Math.floor(Math.random() * 800));
circle = new Ball(5, vec2D, ccolor);
circles.push(circle);
}
drawEverything();
requestAnimationFrame(update);
}
function Ball(radius, position, color) {
this.radius = radius;
this.position = position;
this.color = color;
}
//
Ball.prototype.draw = function(ctx) {
var c=parseInt(this.color);
ctx.fillStyle = 'rgba(' + c + ',' + c + ',' + c + ',1)';
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.radius, 0, 2 * Math.PI);
ctx.closePath();
ctx.fill();
};
function Vector2D(x, y) {
this.x = x;
this.y = y;
}
init();
body{ background-color: #021c36; margin: 0px; }
<canvas id="space" width=1400 height=800></canvas>
Simple solution:
In drawEverything() function move blackhole.draw(ctx) to be the last step
Not so simple: Use one of the many JS particle systems

Categories

Resources