Skip to content

Instantly share code, notes, and snippets.

@adambowles
Last active October 16, 2015 10:24
Show Gist options
  • Save adambowles/73cb5052fbcfbb95d737 to your computer and use it in GitHub Desktop.
Save adambowles/73cb5052fbcfbb95d737 to your computer and use it in GitHub Desktop.
Solar system model and graphical view in HTML canvas / JS. Live demo: http://jsfiddle.net/cwshg3qh/3/
<html>
<body>
<canvas id="canvas" width="512" height="512"></canvas>
<script>
/**
* Celestial body class
*/
var CelestialBody = function (name, x, y, radius, bodyColour, strokeColour) {
this.name = name;
this.x = x;
this.y = y;
this.radius = radius; // in km
this.bodyColour = bodyColour;
this.strokeColour = strokeColour;
bodies.push(this);
};
CelestialBody.prototype.render = function (context) {
// Orbit path
if(this.orbitRadius) {
x = this.primary.x;
y = this.primary.y;
radius = this.orbitRadius + this.radius + this.primary.radius;
context.beginPath();
context.lineWidth = 1;
context.arc(x, y, radius, 0, 2 * Math.PI);
context.strokeStyle = "#656D78"; // Light grey
context.stroke();
}
// Body
x = this.x;
y = this.y;
radius = this.radius;
//console.log(x, y, radius);
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI);
context.fillStyle = this.bodyColour;
context.fill();
context.strokeStyle = this.strokeColour;
context.lineWidth = this.radius/8;
context.stroke();
};
CelestialBody.prototype.toString = function () {
return JSON.stringify(this);
};
/**
* Star class
*/
var Star = function (name, radius, bodyColour, strokeColour) {
CelestialBody.call(this, name, canvas.width/2, canvas.height/2, radius, bodyColour, strokeColour);
};
Star.prototype = Object.create(CelestialBody.prototype);
Star.prototype.constructor = Star;
Star.prototype.toString = function () {
return JSON.stringify(this);
};
/**
* Satellite class (planets, moons)
*/
var Satellite = function (name, primary, orbitRadius, orbitPeriod, radius, bodyColour, strokeColour) {
CelestialBody.call(this, name, 0, 0, radius, bodyColour, strokeColour);
this.currentAngle = 0;
this.primary = primary;
this.orbitRadius = orbitRadius; // in km
this.orbitPeriod = orbitPeriod; // in earth days
satellites.push(this);
};
Satellite.prototype = Object.create(CelestialBody.prototype);
Satellite.prototype.constructor = Satellite;
Satellite.prototype.updateLocation = function (delta) {
this.currentAngle = (this.currentAngle + (delta/(this.orbitPeriod * (16 * Math.PI/2)))) % (Math.PI*2);
this.x = this.primary.x + ((this.orbitRadius + this.primary.radius + this.radius) * Math.sin(this.currentAngle));
this.y = this.primary.y - ((this.orbitRadius + this.primary.radius + this.radius) * Math.cos(this.currentAngle));
};
Satellite.prototype.toString = function () {
return JSON.stringify(this);
};
var canvas;
var context;
var currentFrame; // Unix ms time of current frame
var bodies; // Holds all bodies
var satellites; // Holds all moving bodies (satellites)
var init = function()
{
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
currentFrame = Date.now();
bodies = [];
satellites = [];
var sun = new Star("The Sun", 24, '#FFCE54', '#F6BB42');
// Inner planets
// i.e. new Satellite(name, primary, orbit radius, orbit period, radius, colour, border colour):
var mercury = new Satellite("Mercury", sun, 32, 87.9691, 4, '#CCD1D9', '#AAB2BD');
var venus = new Satellite("Venus", sun, 64, 224.701, 12, '#5D9CEC', '#4A89DC');
var earth = new Satellite("Earth", sun, 128, 365.256363004, 12, '#4FC1E9', '#3BAFDA');
var moon = new Satellite("The Moon", earth, 8, 27.321582, 2, '#CCD1D9', '#AAB2BD');
var mars = new Satellite("Mars", sun, 192, 686.971, 6, '#FC6E51', '#E9573F');
var phobos = new Satellite("Phobos", mars, 3, 0.31891023, 1.5, '#CCD1D9', '#AAB2BD');
var deimos = new Satellite("Deimos", mars, 9, 1.263, 0.75, '#CCD1D9', '#AAB2BD');
window.requestAnimationFrame(draw);
}(); //IIFE
function draw()
{
/* Update model */
// Calculate elapsed milliseconds since last frame
previousFrame = currentFrame;
currentFrame = Date.now();
delta = currentFrame - previousFrame;
// Calculate satellites new positions
satellites.forEach(function(item){
item.updateLocation(delta);
});
/* Update view */
// Clear canvas
canvas.width = canvas.width;
// Draw background
context.fillStyle = '#434A54'; // Dark grey
context.fillRect(0, 0, canvas.width, canvas.height);
// Draw the celestial bodies
bodies.forEach(function(item){
item.render(context);
});
/* Re-call controller on next frame */
window.requestAnimationFrame(draw);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment