How do I add new elements (by this I mean planets) to the below stellar system in the code snippet, based on JSON data such as this:
[{
"rowid": 1,
"Radius size": 3 ,
"Distance": 110 pixels,
},
{
"rowid": 2,
"Size": 2.5,
"Distance": 120 pixels,
}]
Each row ID is its own planet with its own size and position. The distance is of course based on the distance of the planet from the sun element, which is center of the page. The distance per planet needs to be in a different angle, otherwise they'd all line up perfectly (unrealistic). Any ideas on how this can be achieved?
var ball = {};
function makeBall(spec) {
// Create the element
var circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
// Set its various attributes
["id", "cx", "cy", "r", "class"].forEach(function(attrName) {
if (spec.element[attrName]) {
circle.setAttribute(attrName, spec.element[attrName]);
}
});
// Add it to the sun
document.getElementById("Sun2").appendChild(circle);
// Remember its animation settings in `ball`
ball[spec.element.id] = spec.animation;
}
function addObject() {
// Create a spec to use with makeBall from the fields
var spec = {
element: {
id: document.getElementById("new-id").value,
class: document.getElementById("new-class").value,
r: parseFloat(document.getElementById("new-r").value)
},
animation: {
speed: 2,
spin: 30,
side: 40
}
};
// Some minimal validation
if (!spec.element.id || !spec.element.r || !spec.animation.speed || !spec.animation.spin || isNaN(spec.animation.side)) {
alert("Need all values to add a ball");
} else if (ball[spec.element.id]) {
alert("There is already a ball '" + spec.element.id + "'");
} else {
// Do it!
makeBall(spec);
}
}
function rotation(coorX, coorY, object) {
object.side += (1.0 / object.speed);
var ang = object.side * 2.0 * Math.PI / 180.0;
var r = object.spin;
return {
x: Math.cos(ang) * r - Math.sin(ang) * r + coorX,
y: Math.sin(ang) * r + Math.cos(ang) * r + coorY
};
}
function rotationball(circle) {
var x, y, x_black, y_black, e, newpos, black;
// We always rotate around black
black = document.getElementById("black");
// Get this circle and update its position
e = document.getElementById(circle);
x_black = parseFloat(black.getAttribute("cx"));
y_black = parseFloat(black.getAttribute("cy"));
newpos = rotation(x_black, y_black, ball[circle]);
e.setAttribute("cx", newpos.x);
e.setAttribute("cy", newpos.y);
}
function animate() {
Object.keys(ball).forEach(function(id) {
rotationball(id);
});
}
var animateInterval = setInterval(animate, 1000 / 60);
.st0 {
fill: yellow;
}
.st1 {
fill: orange;
}
<div>Add ball:
<label>
ID: <input type="text" id="new-id" value="newball">
</label>
<label>
R: <input type="text" id="new-r" value="10">
</label>
<label>
Speed: <input type="text" id="new-speed" value="1.2">
</label>
<label>
Spin: <input type="text" id="new-spin" value="80">
</label>
<label>
Side: <input type="text" id="new-side" value="0.0">
</label>
<label>
Class: <input type="text" id="new-class" value="st1">
</label>
<button type="button" onclick="addObject()">
Make Ball
</button>
</div>
<div class="spinning">
<svg xmlns="http://www.w3.org/2000/svg" id="solly" viewBox="0 0 1000 600">
<g id="Sun2">
<circle id="black" class="st0" cx="500" cy="300.8" r="10" />
</g>
</svg>
</div>
EDIT: Below are original examples of two records. As you can see it offers a lot more but redundant properties. All I really require from each record are the size (Planet Radius [Jupiter radii] and distance (Distance [pc]). Distance would need to be converted to pixels, size is trickier.
[{
"rowid": 1,
"Host name": "TrES-3",
"Number of Planets in System": 1,
"Planet Mass or M*sin(i)[Jupiter mass]": 1.91,
"Planet Radius [Jupiter radii]": 1.336,
"Planet Density [g": {
"cm**3]": 0.994
},
"Distance [pc]": 228,
"Effective Temperature [K]": 5650,
"Date of Last Update": "5/14/2014"
},
{
"rowid": 2,
"Host name": "UZ For",
"Number of Planets in System": 2,
"Planet Mass or M*sin(i)[Jupiter mass]": 6.3,
"Planet Radius [Jupiter radii]": null,
"Planet Density [g": {
"cm**3]": null
},
"Distance [pc]": null,
"Effective Temperature [K]": null,
"Date of Last Update": "5/14/2014"
}]
It's actually pretty simple:
If you read through the HTML, you will notice that clicking the "Make Ball" button will call addObject(). So you go and check for that function in the JS code. addObject() simply parses the values from the input fields into an object called spec, then calls makeBall(spec).
What you need to do is to provide the exact same data object spec for the makeBall function, for each of your JSON data.
function addObjectsFromJson(json){
// using try catch block because JSON.parse will throw an error if the json is malformed
try{
var array = JSON.parse(json);
for(var i = 0; i < array.length; i++){
var planet = array[i];
// create a spec to use with makeBall from the json
var spec = {
element: {
id: planet.rowid,
// you don't provide a style class in your json yet, using yellow as default
class: 'st0',
// your json must have a standard property for radius,
// currently you have "Radius size" (is wrong since
// properties cannot have spaces) and "Size"
r: planet["Planet Radius [Jupiter radii]"]
},
animation: {
speed: 2,
spin: 30,
side: planet["Distance [pc]"]
}
};
makeBall(spec);
}
}catch(e){
console.log('error: ' + e);
}
}
I don't see a property for adding a distance in the makeBall() function though.
Handle JSON via ajax with jQuery:
// assuming your local server runs on port 8080
$.getJSON('localhost:8080/path/to/your/file', function (json) {
// since we use getJSON, it is already parsed and a javascript object
// additional parsing inside the addObjectsFromJson function is not necassary
// and would throw an error
addObjectsFromJson(json);
});
function addObjectsFromJson(json) {
for (var i = 0; i < json.length; i++) {
var planet = json[i];
// create a spec to use with makeBall from the json
var spec = {
element: {
id: planet.rowid,
// you don't provide a style class in your json yet, using yellow as default
class: 'st0',
// your json must have a standard property for radius,
// currently you have "Radius size" (is wrong since properties cannot have spaces) and "Size"
r: planet["Planet Radius [Jupiter radii]"]
},
animation: {
speed: 2,
spin: 30,
side: planet["Distance [pc]"]
};
makeBall(spec);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With