Built with blockbuilder.org
Last active
October 1, 2016 21:34
-
-
Save tonyhschu/0071af4ae418ca57b5ba488bf65d97d4 to your computer and use it in GitHub Desktop.
Clock Screensaver Experiment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: mit |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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 style="background: grey"> | |
<div> | |
<canvas id="typesetting" width="150" height="150" style="opacity: 0"></canvas> | |
<svg id="svg" style="position: absolute; top: 0; left: 0;" /> | |
</div> | |
<script> | |
// Feel free to change or delete any of the code you see in this editor! | |
console.clear() | |
let WIDTH, HEIGHT | |
let c = d3.select("#typesetting") | |
let svg = d3.select("#svg") | |
var t = d3.transition() | |
.duration(750); | |
let search = function(quadtree, x0, y0, x3, y3) { | |
let results = [] | |
quadtree.visit(function(node, x1, y1, x2, y2) { | |
let p = node.data | |
if (p && (p.x >= x0) && (p.x < x3) && (p.y >= y0) && (p.y < y3)) { | |
results.push(p) | |
} | |
return x1 >= x3 || y1 >= y3 || x2 < x0 || y2 < y0; | |
}); | |
return results | |
} | |
let reset = function(displayText) { | |
WIDTH = window.innerWidth | |
HEIGHT = window.innerHeight | |
let FONTSIZE = Math.min(WIDTH, HEIGHT) / 1.5 | |
c.attr('width', WIDTH).attr('height', HEIGHT) | |
svg.attr('width', WIDTH).attr('height', HEIGHT) | |
let ctx = c.node().getContext('2d'); | |
ctx.clearRect(0, 0, WIDTH, HEIGHT) | |
ctx.font = FONTSIZE + "px Georgia"; | |
ctx.textAlign = "center" | |
ctx.fillText(displayText, WIDTH / 2, (HEIGHT + FONTSIZE / 2) / 2 ); | |
let imageData = ctx.getImageData(0, 0, WIDTH, HEIGHT) | |
let darkPixels = d3.range(WIDTH * HEIGHT).map(function(pk) { | |
return { | |
key: pk, | |
x: pk % WIDTH, | |
y: Math.floor(pk / WIDTH), | |
opacity: imageData.data[pk * 4 + 3] | |
} | |
}).filter(function(c) { | |
return c.opacity > 0 | |
}) | |
let edgeCoordinates = d3.range(WIDTH * HEIGHT).map(function(pk) { | |
let s = pk * 4 | |
let e = (pk + 1) * 4 | |
let d = (pk + WIDTH) * 4 | |
let p1 = imageData.data[s + 3] | |
let p2 = imageData.data[e + 3] | |
let p3 = imageData.data[d + 3] | |
return { | |
x: pk % WIDTH, | |
y: Math.floor(pk / WIDTH), | |
delta: Math.max(Math.abs(p1 - p2), Math.abs(p1 - p3)) | |
} | |
}).filter(function(coordinate) { | |
return coordinate.delta > 0 | |
}).filter(function(coordinate, i) { | |
return i % 8 == 0 | |
}) | |
let edgeQuadTree = d3.quadtree() | |
.x(function(d) { return d.x }) | |
.y(function(d) { return d.y }) | |
.addAll(edgeCoordinates) | |
let maxRadius = 40 | |
let circles = [] | |
let circleQuadTree = d3.quadtree() | |
.extent([[0, 0], [WIDTH, HEIGHT]]) | |
.x(function(d) { return d.x }) | |
.y(function(d) { return d.y }) | |
d3.shuffle(d3.range(darkPixels.length)).forEach(function(key) { | |
let pixel = darkPixels[key] | |
let radius = maxRadius | |
let closestEdge = edgeQuadTree.find(pixel.x, pixel.y, maxRadius) | |
let inRangeCircles = search(circleQuadTree, pixel.x - maxRadius, pixel.y - maxRadius, pixel.x + maxRadius, pixel.y + maxRadius) | |
let d = inRangeCircles.map(function(point) { | |
let dx = pixel.x - point.x | |
let dy = pixel.y - point.y | |
return Math.max(0, Math.sqrt(dx * dx + dy * dy) - point.r) | |
}) | |
if (d.length > 0) { | |
let minPossibleRadius = d3.min(d) | |
if(minPossibleRadius < 5) { | |
return | |
} else { | |
radius = minPossibleRadius | |
} | |
} | |
if (closestEdge) { | |
let dx = pixel.x - closestEdge.x | |
let dy = pixel.y - closestEdge.y | |
radius = Math.min(Math.sqrt(dx * dx + dy * dy), radius) | |
} | |
let newCircle = { | |
key: pixel.pk, | |
x: pixel.x, | |
y: pixel.y, | |
r: radius | |
} | |
circles.push(newCircle) | |
circleQuadTree.add(newCircle) | |
}) | |
let edgeIndicators = svg.selectAll('circle') | |
.data(circles, function(d) { return d.key; }) | |
edgeIndicators.exit() | |
.transition(t) | |
.attr("r", 0) | |
.remove() | |
edgeIndicators.enter() | |
.append('circle') | |
.attr('fill', '#fff') | |
.attr('r', 0) | |
.attr('cx', function(d) { | |
return d.x | |
}) | |
.attr('cy', function(d) { | |
return d.y | |
}) | |
.merge(edgeIndicators) | |
.transition(t) | |
.attr('r', function(d) { | |
return d.r | |
}) | |
} | |
let number = 1234 | |
window.resize = reset | |
reset(number) | |
setTimeout(function() { | |
number += 1 | |
console.log(number) | |
reset(number) | |
}, 3000) | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment