Create a "tail" for an object that is orbiting - javascript

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>

Related

Canvas Animation Javascript reverse

I have a top to bottom falling canvas animation, but I want to reverse it (go from bottom to top). I can't figure out how to change the direction
I have my code here
http://js.do/code/176399
sample:
function Ember(x, y, s /*radius*/ , p /*num points*/ ) {
this.x = x;
this.y = y;
this.s = s;
this.p = p;
this.img = document.createElement('canvas');
var context = this.img.getContext('2d'),
len = this.s / 1.45;
this.img.height = this.img.width = this.s * 2;
context.translate(this.s, this.s);
context.rotate((Math.PI * 1 / 10));
context.beginPath();
for (var i = 0; i < p; i++) {
context.lineTo(0, -s);
context.rotate((Math.PI * 2 / (p * 2)));
context.lineTo(0, s);
context.rotate((Math.PI * 2 / (p * 2)));
}
context.closePath();
context.shadowBlur = this.s / 3;
context.shadowColor = 'rgba(174, 12, 1, 0.9)';
context.fillStyle = 'rgba(133,80,33,.45)';
context.fill();
}
Just need to reverse the "fall" to bottom to top.
Update:
following off of Jared's suggestion
Changed:
embers[i].y += embers[i].vy;
to:
embers[i].y -= embers[i].vy;
However, I only get one animation cycle would like to have it continually animate new embers on the screen
Take a look at this line where you update the ember's Y position:
embers[i].y = -embers[i].s;
Try changing this to something like this:
embers[i].y = embers[i].s;
<canvas id="canvas"></canvas>
<script>
function Ember(x, y, s /*radius*/ , p /*num points*/ ) {
this.x = x;
this.y = y;
this.s = s;
this.p = p;
this.img = document.createElement('canvas');
var context = this.img.getContext('2d'),
len = this.s / 1.45;
this.img.height = this.img.width = this.s * 2;
context.translate(this.s, this.s);
context.rotate((Math.PI * 1 / 10));
context.beginPath();
for (var i = 0; i < p; i++) {
context.lineTo(0, -s);
context.rotate((Math.PI * 2 / (p * 2)));
context.lineTo(0, s);
context.rotate((Math.PI * 2 / (p * 2)));
}
context.closePath();
context.shadowBlur = this.s / 3;
context.shadowColor = 'rgba(174, 12, 1, 0.9)';
context.fillStyle = 'rgba(133,80,33,.45)';
context.fill();
}
window.requestAnimationFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var canvas, context, height, width, embers;
setTimeout(init, 10);
function init() {
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
height = canvas.height = document.body.offsetHeight;
width = canvas.width = document.body.offsetWidth;
embers = [];
for (var i = 0; i < 150; i++) {
var x = Math.random() * width,
y = Math.random() * height,
s = Math.random() * 5 + 5,
p = Math.random() * 8 + 8;
var s = new Ember(x, y, s, p);
s.vx = Math.random() * 2 - 1;
s.vy = Math.random() * 2 + 1;
s.r = Math.random() * 360;
embers.push(s);
}
update();
render();
}
function update() {
for (var i = 0, l = embers.length; i < l; i++) {
embers[i].r += embers[i].vx / 10;
embers[i].x += embers[i].vx;
embers[i].y -= embers[i].vy;
if (embers[i].y < 0) {
embers[i].y = Math.random()*height;
embers[i].vx = Math.random() * 2 - 1;
embers[i].vy = Math.random() * 2 + 1;
}
}
setTimeout(update, 1000 / 30);
}
function render() {
context.clearRect(0, 0, width, height);
for (var i = 0, l = embers.length; i < l; i++) {
context.save();
context.translate(embers[i].x, embers[i].y);
context.rotate(embers[i].r);
context.drawImage(embers[i].img, 0, 0);
context.restore();
}
requestAnimationFrame(render);
}
</script>
Wrong if condition in update function, change it to check if v(embers[i].y < 0), ans set appropriate new y position
if (embers[i].y < 0) {
embers[i].y = Math.random()*height;

Resizing a <canvas> Element

I have the following canvas. I'm trying to make it smaller using the width and height attributes, but it doesn't work. This is my code:
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<canvas id="canvas" width="200" height="50"></canvas>
<script>
//set the variables
var a = document.getElementById('canvas'),
c = a.getContext('2d'),
w = a.width = window.innerWidth,
h = a.height = window.innerHeight,
area = w * h,
particleNum = 300,
ANIMATION;
var particles = [];
//create the particles
function Particle(i) {
this.id = i;
this.hue = rand(50, 0, 1);
this.active = false;
}
Particle.prototype.build = function() {
this.x = w / 2;
this.y = h / 2;
this.r = rand(7, 2, 1);
this.vx = Math.random() * 10 - 5;
this.vy = Math.random() * 10 - 5;
this.gravity = .01;
this.opacity = Math.random() + .5;
this.active = true;
c.beginPath();
c.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
c.fillStyle = "hsla(" + this.hue + ",100%,50%,1)";
c.fill();
};
Particle.prototype.draw = function() {
this.active = true;
this.x += this.vx;
this.y += this.vy;
this.vy += this.gravity;
this.hue -= 0.5;
this.r = Math.abs(this.r - .05);
c.beginPath();
c.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
c.fillStyle = "hsla(" + this.hue + ",100%,50%,1)";
c.fill();
// reset particle
if(this.r <= .05) {
this.active = false;
}
};
//functionality
function drawScene() {
c.fillStyle = "black";
c.fillRect(0,0,w,h);
for(var i = 0; i < particles.length; i++) {
if(particles[i].active === true) {
particles[i].draw();
} else {
particles[i].build();
}
}
ANIMATION = requestAnimationFrame(drawScene);
}
function initCanvas() {
var s = getComputedStyle(a);
if(particles.length) {
particles = [];
cancelAnimationFrame(ANIMATION);
ANIMATION;
console.log(ANIMATION);
}
w = a.width = window.innerWidth;
h = a.height = window.innerHeight;
for(var i = 0; i < particleNum; i++) {
particles.push(new Particle(i));
}
drawScene();
console.log(ANIMATION);
}
//init
(function() {
initCanvas();
addEventListener('resize', initCanvas, false);
})();
//helper functions
function rand(max, min, _int) {
var max = (max === 0 || max)?max:1,
min = min || 0,
gen = min + (max - min) * Math.random();
return (_int) ? Math.round(gen) : gen;
};
</script>
</body>
</html>
Pay more attention here:
var a = document.getElementById('canvas'),
c = a.getContext('2d'),
w = a.width = window.innerWidth,
h = a.height = window.innerHeight,
area = w * h,
As you can see, w is the width of the window and h is the height of the window. Try to edit w and h variable with custom values and tell me if it worked ;)
EDIT:
Simply replace h and w with this in your script tag:
a.style.width = '500px'; //random value, insert custom here
a.style.height = '500px';

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

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

How to make canvas particles follow mouse with JS?

I want to make the particles follow the mouse and I am not sure on how to do that.
I figured I can replace the x and y with the mouses position but I can figure that out either.
I would appreciate an almost exact answer and not examples please.
window.onload = function() {
var canvas = document.createElement("canvas"),
c = canvas.getContext("2d"),
particles = {}
particleIndex = 0,
particleNum = Math.random() * 2;
canvas.width = 400;
canvas.height = 400;
document.body.appendChild(canvas);
c.fillStyle = "black";
c.fillRect(0, 0, canvas.width, canvas.height);
function Particle() {
this.x = canvas.width / 10;
this.y = canvas.height / 2;
this.vx = Math.random() * 10 - 5;
this.vy = Math.random() * 10 - 5;
this.gravity = .2;
particleIndex++;
particles[particleIndex] = this;
this.id = particleIndex;
this.life = 0;
this.maxLife = Math.random() * 30 + 10;
this.color = "rgb(" + parseInt(Math.random() * 255, 10) + ",0,0)";
this.color2 = "hsl(" + parseInt(Math.random() * 255, 10) + ",50%,50%)";
}
Particle.prototype.draw = function() {
this.x += this.vx;
this.y += this.vy;
if (Math.random() < 0.1) {
this.vx = Math.random() * 10 - 5;
this.vy = Math.random() * 10 - 5;
}
this.vy += this.gravity;
this.life++;
if (this.Life >= this.maxLife) {
delete particles[this.id];
}
c.fillStyle = this.color2;
c.fillRect(this.x, this.y, 10, 10);
};
//var p = new Particle();
setInterval(function() {
c.fillStyle = "rgba(0,0,0,0.5)";
c.fillRect(0, 0, canvas.width, canvas.height);
for (var i in particles) {
particles[i].draw();
}
for (var i = 0; i < particleNum; i++) {
new Particle();
}
}, 30);
};

Categories

Resources