Move your MOUSE over any symbol to highlight that element. CLICK anywhere to shift the sort order of the elements - by mass, by year of discovery, or by melting point.
xxxxxxxxxx
//For the #WCCChallenge, theme: "chemistry"
let table;
let chosen;
let elements = [];
let mode = 0;
let modes = ['Group', 'Atomic Mass (AMU)', 'Year of Discovery', 'Melting Point (°K)'];
let dim;
let shift, starget;
let yaxis, tyaxis;
let num;
function preload() {
//table = loadJSON('https://periodic-table-elements-info.herokuapp.com/elements');
table = loadJSON('data.json');
}
function setup() {
createCanvas(windowWidth, windowHeight);
dim = width / 24;
rectMode(CENTER);
textAlign(CENTER, CENTER);
textSize(dim / 2);
makeElements();
starget = createVector(0, -dim / 2);
shift = createVector(0, -dim / 2);
yaxis = -3 * dim / 2;
tyaxis = 3 * dim / 2;
}
function makeElements() {
let num = Object.keys(table).length;
for (let i = 0; i < num; i += 1) {
let tpos = createVector(5 * dim / 2 + table[i].group * dim, table[i].period * dim);
if (table[i].name == 'Boron') tpos.y += dim;
if (i > 56 && i < 71) tpos.y += 2 * dim;
if (i > 88 && i < 103) tpos.y += 2 * dim;
if (i > 56 && i < 71) tpos.x += (table[i].atomicNumber - 57) * dim;
if (i > 88 && i < 103) tpos.x += (table[i].atomicNumber - 89) * dim;
if (i==26) tpos.x -= 10*dim;
let sym = table[i].symbol;
let no = table[i].atomicNumber;
let group = table[i].group;
let row = table[i].period;
let name = table[i].name;
let wt = atwt[i];
let bp = table[i].boilingPoint;
let mp = table[i].meltingPoint;
let ss = table[i].standardState;
let year = table[i].yearDiscovered;
let gb = table[i].groupBlock;
let c = '#' + table[i].cpkHexColor;
let ar = table[i].atomicRadius;
elements.push(new Element(tpos, sym, no, group, row, name, wt, i, year, bp, mp, ss, gb, c, ar));
}
elements[1].mp = 1; //helium
elements[86].mp = 300; //francium
}
function draw() {
background(0);
drawAxes();
for (let e of elements) {
e.show(1);
}
fill(255);
textSize(dim / 2.5);
text('Elements Sorted by ' + modes[mode], width / 2, dim / 4);
if (chosen) chosen.show(1.25);
if (chosen && mode > 0) {
noFill();
stroke(255);
line(chosen.pos.x, chosen.pos.y + 1.25 * (dim / 2), chosen.pos.x, height - 3 * dim / 4);
noStroke();
fill(255);
ellipse(chosen.pos.x, height - 3 * dim / 4, dim / 8, dim / 8);
}
shift.lerp(starget, 0.1);
yaxis = lerp(yaxis, tyaxis, 0.1);
highlightChosen();
}
function highlightChosen() {
if (chosen) {
noStroke();
fill(255);
textSize(dim / 3);
textAlign(LEFT, TOP);
translate(shift);
text('Element: ' + chosen.name, dim * 5.5, dim);
text('Atomic Number: ' + chosen.no, dim * 5.5, 4 * dim / 3);
text('Atomic Mass: ' + chosen.atwt.toFixed(2) + ' amu', dim * 5.5, 5 * dim / 3);
text('Year of Discovery: ' + chosen.year, dim * 5.5, 6 * dim / 3);
text('Melting Point: ' + chosen.mp + '°K', dim * 5.5, 7 * dim / 3);
text('Boiling Point: ' + chosen.bp + '°K', dim * 5.5, 8 * dim / 3);
text('Standard State: ' + chosen.ss, dim * 5.5, 9 * dim / 3);
text('Group Block: ' + chosen.gb, dim * 5.5, 10 * dim / 3);
}
}
function mousePressed() {
//chosen = null;
frameCount = 0;
mode = (mode + 1) % modes.length;
switch (mode) {
case 0: //group
starget.x = 0;
starget.y = -dim / 2;
setTimeout(restoreY, 2000);
for (let e of elements) {
e.tpos.x = e.otpx;
}
break;
case 1: //mass
starget.x = 5 * dim;
starget.y = -dim / 2;
tyaxis = 0;
for (let e of elements) {
e.tpos.x = map(e.atwt, 0, 300, 2 * dim, 22 * dim);
}
break;
case 2: //year
starget.x = 12 * dim;
starget.y = -dim / 2;
tyaxis = 0;
for (let e of elements) {
if (e.year == 'Ancient') e.tpos.x = map(e.no, 6, 83, 2 * dim, 3 * dim);
else e.tpos.x = map(e.year, 1620, 2020, 2 * dim, 22 * dim);
}
break;
case 3: //melting point
starget.x = 7 * dim;
starget.y = -dim / 2;
tyaxis = 0;
for (let e of elements) {
if (e.mp == 'unknown') e.tpos.x = map(e.no, 100, 120, 19 * dim, 23 * dim);
else e.tpos.x = map(e.mp, 0, 4000, 2 * dim, 18 * dim);
}
break;
}
}
function mouseMoved() {
chosen = null;
for (let e of elements) {
if (e.contains(mouseX, mouseY)) {
chosen = e;
}
}
}
function drawAxes() {
let per = 1;
push();
textAlign(CENTER, CENTER);
translate(yaxis, 0);
stroke(255);
noFill();
line(dim, dim / 2, dim, 19 * dim / 2);
for (let y = dim / 2; y <= 19 * dim / 2; y += dim) {
stroke(255);
noFill();
line(3 * dim / 4, y, dim, y);
fill(255);
noStroke();
textSize(dim / 4);
if (per < 8) text(per, dim / 2, y + dim / 2);
else if (per == 8) text('6*', dim / 2, y + dim / 2);
else if (per == 9) text('7**', dim / 2, y + dim / 2);
per += 1;
}
pop();
switch (mode) {
case 0: //group
stroke(255);
noFill();
line(3 * dim, height - 3 * dim / 4, 21 * dim, height - 3 * dim / 4);
let grp = 1;
for (let x = 3 * dim; x < 22 * dim; x += dim) {
stroke(255);
noFill();
line(x, height - dim / 2, x, height - 3 * dim / 4);
noStroke();
fill(255);
textSize(dim / 4);
textAlign(CENTER, CENTER);
if (grp < 19) text(grp, x + dim / 2, height - dim / 4);
grp += 1
}
break;
case 1: //mass
stroke(255);
noFill();
line(2 * dim, height - 3 * dim / 4, width - 2 * dim, height - 3 * dim / 4);
let wt = 0;
for (let x = 2 * dim; x <= 22 * dim; x += dim) {
stroke(255);
noFill();
line(x, height - dim / 2, x, height - 3 * dim / 4);
noStroke();
fill(255);
textSize(dim / 4);
textAlign(CENTER, CENTER);
text(wt, x, height - dim / 4);
wt += 15;
}
break;
case 2: //year
stroke(255);
noFill();
line(dim, height - 3 * dim / 4, width - dim, height - 3 * dim / 4);
textSize(dim / 4);
textAlign(CENTER, CENTER);
noStroke();
fill(255);
text('Ancient', 1.5 * dim, height - dim / 4);
let year = 1660;
for (let x = 2 * dim; x <= 22 * dim; x += dim) {
if (x >= 4 * dim) {
stroke(255);
noFill();
line(x, height - dim / 2, x, height - 3 * dim / 4);
noStroke();
fill(255);
textSize(dim / 4);
textAlign(CENTER, CENTER);
text(year, x, height - dim / 4);
year += 20;
}
}
break;
case 3: //melting point
stroke(255);
noFill();
line(2 * dim, height - 3 * dim / 4, width - dim, height - 3 * dim / 4);
textSize(dim / 4);
textAlign(CENTER, CENTER);
noStroke();
fill(255);
text('Unknown', 21.25 * dim, height - dim / 4);
let temp = 0;
for (let x = 2 * dim; x <= 22 * dim; x += dim) {
if (x <= 19 * dim) {
stroke(255);
noFill();
line(x, height - dim / 2, x, height - 3 * dim / 4);
noStroke();
fill(255);
textSize(dim / 4);
textAlign(CENTER, CENTER);
text(temp, x, height - dim / 4);
temp += 4000 / 16;
}
}
break;
}
noStroke();
}
function restoreY() {
tyaxis = 3 * dim / 2;
}
let atwt = [1.008, 4.003, 6.968, 9.012, 10.81, 12.01, 14.01, 16, 19, 20.18, 22.99, 24.31, 26.98, 28.09, 30.97, 32.07, 35.45, 39.95, 39.1, 40.08, 44.96, 47.87, 50.94, 52, 54.94, 55.85, 58.93, 58.69, 63.55, 65.38, 69.72, 72.63, 74.92, 78.97, 79.9, 83.8, 85.47, 87.62, 88.91, 91.22, 92.91, 95.95, 98, 101.1, 102.9, 106.4, 107.9, 112.4, 114.8, 118.7, 121.8, 127.6, 126.9, 131.3, 132.9, 137.3, 138.9, 140.1, 140.9, 144.2, 145, 150.4, 152, 157.3, 158.9, 162.5, 164.9, 167.3, 168.9, 173.1, 175, 178.5, 180.9, 183.8, 186.2, 190.2, 192.2, 195.1, 197, 200.6, 204.4, 207.2, 209, 209, 210, 222, 223, 226, 227, 232, 231, 238, 237, 244, 243, 247, 247, 251, 252, 257, 258, 259, 262, 267, 268, 271, 272, 270, 276, 281, 280, 285, 284, 289, 288, 293, 292, 294];