<table>
<tr>
<th colspan=2></th>
<td id="10.0"></td>
<td id="11.0"></td>
<td id="12.0"></td>
<td id="13.0"></td>
<td id="14.0"></td>
<td id="15.0"></td>
<td id="16.0"></td>
<td id="17.0"></td>
<td id="18.0"></td>
<td id="19.0"></td>
<th colspan=2></th>
</tr>
<tr>
<th colspan=2></th>
<td id="10.1"></td>
<td id="11.1"></td>
<td id="12.1"></td>
<td id="13.1"></td>
<td id="14.1"></td>
<td id="15.1"></td>
<td id="16.1"></td>
<td id="17.1"></td>
<td id="18.1"></td>
<td id="19.1"></td>
<th colspan=2></th>
</tr>
<tr>
<td id="9.0"></td>
<td id="9.1"></td>
<th colspan=10></th>
<td id="20.1"></td>
<td id="20.0"></td>
</tr>
<tr>
<td id="8.0"></td>
<td id="8.1"></td>
<th colspan=10></th>
<td id="21.1"></td>
<td id="21.0"></td>
</tr>
<tr>
<td id="7.0"></td>
<td id="7.1"></td>
<th colspan=10></th>
<td id="22.1"></td>
<td id="22.0"></td>
</tr>
<tr>
<td id="6.0"></td>
<td id="6.1"></td>
<th colspan=10></th>
<td id="23.1"></td>
<td id="23.0"></td>
</tr>
<tr>
<td id="5.0"></td>
<td id="5.1"></td>
<th colspan=10></th>
<td id="24.1"></td>
<td id="24.0"></td>
</tr>
<tr>
<td id="4.0"></td>
<td id="4.1"></td>
<th colspan=10></th>
<td id="25.1"></td>
<td id="25.0"></td>
</tr>
<tr>
<td id="3.0"></td>
<td id="3.1"></td>
<th colspan=10></th>
<td id="26.1"></td>
<td id="26.0"></td>
</tr>
<tr>
<td id="2.0"></td>
<td id="2.1"></td>
<th colspan=10></th>
<td id="27.1"></td>
<td id="27.0"></td>
</tr>
<tr>
<td id="1.0"></td>
<td id="1.1"></td>
<th colspan=10></th>
<td id="28.1"></td>
<td id="28.0"></td>
</tr>
<tr>
<td id="0.0"></td>
<td id="0.1"></td>
<th colspan=10></th>
<td id="29.1"></td>
<td id="29.0"></td>
</tr>
<tr>
<th colspan=2></th>
<td id="39.1"></td>
<td id="38.1"></td>
<td id="37.1"></td>
<td id="36.1"></td>
<td id="35.1"></td>
<td id="34.1"></td>
<td id="33.1"></td>
<td id="32.1"></td>
<td id="31.1"></td>
<td id="30.1"></td>
<th colspan=2></th>
</tr>
<tr>
<th colspan=2></th>
<td id="39.0"></td>
<td id="38.0"></td>
<td id="37.0"></td>
<td id="36.0"></td>
<td id="35.0"></td>
<td id="34.0"></td>
<td id="33.0"></td>
<td id="32.0"></td>
<td id="31.0"></td>
<td id="30.0"></td>
<th colspan=2></th>
</tr>
</table>
td {
width: 20px;
height: 20px;
background: #111;
}
body {
background: #000;
}
// ------------------------------------
// Framework code - scroll down
// ------------------------------------
const totalCols = 40;
const totalRows = 2;
const lights = [];
for (let x = 0; x < totalCols; x++) {
for (let y = 0; y < totalRows; y++) {
lights.push({ id: `${x}.${y}`, color: null });
}
}
setInterval(() => {
const time = Date.now() / 1e3;
for (const light of lights) {
light.color = null;
}
update(lights, time);
d3.select('table')
.selectAll('td')
.data(lights, (d, i, nodes) => d ? d.id : nodes[i].id)
.style('background', d => d.color);
}, 60);
// ------------------------------------
// Custom code
// ------------------------------------
const nodes = [];
for (let i = 0; i < 50; i++) {
nodes.push({});
}
const forceX = d3.forceX(totalCols / 2, 0);
const simulation = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(1))
.force("forceX", forceX);
simulation.stop();
const randomise = () => {
simulation.alpha(Math.random() * 0.3 + 0.7);
forceX.x(Math.random() * totalCols);
setTimeout(randomise, Math.random() * 6000)
};
setTimeout(randomise, 3000);
function update(lights, time) {
simulation.tick();
const color = `hsl(${(time * 200) % 360}, 100%, 50%)`;
for (const node of nodes) {
let x = (Math.round(node.x) - (totalCols / 2)) % totalCols;
x = x >= 0 ? x : (totalCols + x);
lights[x * 2].color = node.y >= 0 ? color : null;
lights[x * 2 + 1].color = node.y <= 0 ? color : null;
}
}
View Compiled
This Pen doesn't use any external CSS resources.