Skip to content

Instantly share code, notes, and snippets.

@tonyhschu
Last active October 1, 2016 21:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tonyhschu/0071af4ae418ca57b5ba488bf65d97d4 to your computer and use it in GitHub Desktop.
Save tonyhschu/0071af4ae418ca57b5ba488bf65d97d4 to your computer and use it in GitHub Desktop.
Clock Screensaver Experiment
license: mit
<!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