D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
wwymak
Full window
Github gist
simple cellular automata
Built with
blockbuilder.org
<!DOCTYPE html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v4.min.js"></script> <style> body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } </style> </head> <body> <div id="canvas"></div> <script> const cellsize = 10; const cellNumberX = 100; const cellNumberY = 100; let cellArray = []; for (let i = 0; i< cellNumberX; i++) { for (let j = 0; j< cellNumberY; j++) { let cell = { x: i, y: j, alive: 0, above: j -1, below: j + 1, left: i -1, right: i+1, aliveNext: 0 }; if(cell.above < 0) { cell.above = cellNumberY - 1; } if(cell.below > cellNumberY - 1) { cell.below = 0; } if(cell.left < 0) { cell.left = cellNumberX -1 } if(cell.right > cellNumberX - 1) { cell.right = 0 } cellArray.push(cell) } } cellArray.forEach(d => { if(Math.random() > 0.5) { d.alive = 1 } d.neighbours = []; d.neighbours.push(cellArray.filter(j => j.x ===d.x && j.y === d.above)[0]) d.neighbours.push(cellArray.filter(j => j.x ===d.x && j.y === d.below)[0]) d.neighbours.push(cellArray.filter(j => j.x ===d.left && j.y === d.y )[0]) d.neighbours.push(cellArray.filter(j => j.x ===d.right&& j.y === d.above)[0]) d.neighbours.push(cellArray.filter(j => j.x ===d.left && j.y === d.above)[0]) d.neighbours.push(cellArray.filter(j => j.x ===d.left && j.y === d.below)[0]) d.neighbours.push(cellArray.filter(j => j.x ===d.right&& j.y === d.above)[0]) d.neighbours.push(cellArray.filter(j => j.x ===d.right&& j.y === d.below)[0]) }); let canvasObj = d3.select('#canvas') .append('canvas') .attr('width', cellsize * cellNumberX) .attr('height', cellsize * cellNumberY); let context = canvasObj.node().getContext('2d'); // databinding let dataHolder = d3.select(document.createElement('dataHolder')); function dataBind(data){ let join = dataHolder.selectAll('dataRect.rect').data(data); let enterSelection = join.enter().append('dataRect') .attr('class', 'rect') .attr('width', cellsize) .attr('height', cellsize) .attr('x', d => d.x * cellsize) .attr('y', d => d.y * cellsize) // .attr('stroke-style', 'black') let mergeSelection = join.merge(enterSelection) // .transition() .attr('width', cellsize) .attr('height', cellsize) .attr('fillStyle', d => d.alive ===1? 'black': 'white'); let exitSelection = join.exit().remove()//.transition().attr('width', 0).attr('height', 0).remove(); } function draw() { context.clearRect(0, 0, cellsize * cellNumberX, cellsize * cellNumberY); let elements = dataHolder.selectAll('dataRect.rect'); elements.each(function (d, i) { let cell = d3.select(this); context.fillStyle = cell.attr('fillStyle'); context.fillRect(cell.attr('x'), cell.attr('y'), cellsize, cellsize) }) } function updateCells(cellArray) { cellArray.forEach(cell => { let numberOfLiveNeighbours = cell.neighbours.filter(d => d.alive ===1).length; if(cell.alive ===1 ) { if (numberOfLiveNeighbours === 2 || numberOfLiveNeighbours === 3){ cell.aliveNext = 1; } else { cell.aliveNext = 0 } } if(cell.alive === 0) { if(numberOfLiveNeighbours === 3) { cell.aliveNext = 1; } } }); cellArray.forEach(cell => { cell.alive = cell.aliveNext; }) return cellArray; } setInterval(() => { updateCells(cellArray); dataBind(cellArray); draw(); }, 1000); // dataBind(cellArray); // draw(); </script> </body>
https://d3js.org/d3.v4.min.js