diff options
Diffstat (limited to 'static/src/_posts/2020-07-07-viz-3.md')
-rw-r--r-- | static/src/_posts/2020-07-07-viz-3.md | 155 |
1 files changed, 0 insertions, 155 deletions
diff --git a/static/src/_posts/2020-07-07-viz-3.md b/static/src/_posts/2020-07-07-viz-3.md deleted file mode 100644 index 7f5280d..0000000 --- a/static/src/_posts/2020-07-07-viz-3.md +++ /dev/null @@ -1,155 +0,0 @@ ---- -title: >- - Visualization 3 -description: >- - All the pixels. -series: viz -tags: tech art ---- - -<canvas id="canvas" style="padding-bottom: 2rem;"></canvas> - -This visualization is built from the ground up. On every frame a random set of -pixels is chosen. Each chosen pixel calculates the average of its color and the -color of a random neighbor. Some random color drift is added in as well. It -replaces its own color with that calculated color. - -Choosing a neighbor is done using the "asteroid rule", ie a pixel at the very -top row is considered to be the neighbor of the pixel on the bottom row of the -same column. - -Without the asteroid rule the pixels would all eventually converge into a single -uniform color, generally a light blue, due to the colors at the edge, the reds, -being quickly averaged away. With the asteroid rule in place the canvas has no -edges, thus no position on the canvas is favored and balance can be maintained. - -<script type="text/javascript"> -let rectSize = 12; - -function randn(n) { - return Math.floor(Math.random() * n); -} - -let canvas = document.getElementById("canvas"); -canvas.width = window.innerWidth - (window.innerWidth % rectSize); -canvas.height = window.innerHeight- (window.innerHeight % rectSize); -let ctx = canvas.getContext("2d"); - -let w = canvas.width / rectSize; -let h = canvas.height / rectSize; - -let matrices = new Array(2); -matrices[0] = new Array(w); -matrices[1] = new Array(w); -for (let x = 0; x < w; x++) { - matrices[0][x] = new Array(h); - matrices[1][x] = new Array(h); - for (let y = 0; y < h; y++) { - let el = { - h: 360 * (x / w), - s: "100%", - l: "50%", - }; - matrices[0][x][y] = el; - matrices[1][x][y] = el; - } -} - -// draw initial canvas, from here on out only individual rectangles will be -// filled as they get updated. -for (let x = 0; x < w; x++) { - for (let y = 0; y < h; y++) { - let el = matrices[0][x][y]; - ctx.fillStyle = `hsl(${el.h}, ${el.s}, ${el.l})`; - ctx.fillRect(x * rectSize, y * rectSize, rectSize, rectSize); - } -} - - -let requestAnimationFrame = - window.requestAnimationFrame || - window.mozRequestAnimationFrame || - window.webkitRequestAnimationFrame || - window.msRequestAnimationFrame; - -let neighbors = [ - [-1, -1], [0, -1], [1, -1], - [-1, 0], [1, 0], - [-1, 1], [0, 1], [1, 1], -]; - -function randNeighborAsteroid(matrix, x, y) { - let neighborCoord = neighbors[randn(neighbors.length)]; - let neighborX = x+neighborCoord[0]; - let neighborY = y+neighborCoord[1]; - neighborX = (neighborX + w) % w; - neighborY = (neighborY + h) % h; - return matrix[neighborX][neighborY]; -} - -function randNeighbor(matrix, x, y) { - while (true) { - let neighborCoord = neighbors[randn(neighbors.length)]; - let neighborX = x+neighborCoord[0]; - let neighborY = y+neighborCoord[1]; - if (neighborX < 0 || neighborX >= w || neighborY < 0 || neighborY >= h) { - continue; - } - return matrix[neighborX][neighborY]; - } -} - -let drift = 10; -function genChildH(elA, elB) { - // set the two h values, h1 <= h2 - let h1 = elA.h; - let h2 = elB.h; - if (h1 > h2) { - h1 = elB.h; - h2 = elA.h; - } - - // diff must be between 0 (inclusive) and 360 (exclusive). If it's greater - // than 180 then it's not the shortest path around, that must be the other - // way around the circle. - let hChild; - let diff = h2 - h1; - if (diff > 180) { - diff = 360 - diff; - hChild = h2 + (diff / 2); - } else { - hChild = h1 + (diff / 2); - } - - hChild += (Math.random() * drift * 2) - drift; - hChild = (hChild + 360) % 360; - return hChild; -} - -let tick = 0; -function doTick() { - tick++; - let currI = tick % 2; - let curr = matrices[currI]; - let lastI = (tick - 1) % 2; - let last = matrices[lastI]; - - for (let i = 0; i < (w * h / 2); i++) { - let x = randn(w); - let y = randn(h); - if (curr[x][y].lastTick == tick) continue; - - let neighbor = randNeighborAsteroid(last, x, y); - curr[x][y].h = genChildH(curr[x][y], neighbor); - curr[x][y].lastTick = tick; - ctx.fillStyle = `hsl(${curr[x][y].h}, ${curr[x][y].s}, ${curr[x][y].l})`; - ctx.fillRect(x * rectSize, y * rectSize, rectSize, rectSize); - } - - matrices[currI] = curr; - requestAnimationFrame(doTick); -} - -requestAnimationFrame(doTick); - -</script> |