Skip to content

Instantly share code, notes, and snippets.

@eesur
Last active May 23, 2017 11:03
Show Gist options
  • Save eesur/aacf4b225a450faeece98ad26901ccdf to your computer and use it in GitHub Desktop.
Save eesur/aacf4b225a450faeece98ad26901ccdf to your computer and use it in GitHub Desktop.
d3 | circle movement with voronoi overlay
var svg = d3.select('svg'),
width = +svg.attr('width'),
height = +svg.attr('height'),
radius = 32
var circles = d3.range(9).map(function () {
return {
x: Math.round(Math.random() * (width - radius * 2) + radius),
y: Math.round(Math.random() * (height - radius * 2) + radius)
}
})
var color = d3.scaleOrdinal()
.range(d3.schemeCategory10)
var voronoi = d3.voronoi()
.x(function (d) { return d.x; })
.y(function (d) { return d.y; })
.extent([
[-1, -1],
[width + 1, height + 1]
])
var circle = svg.selectAll('g')
.data(circles)
.enter().append('g')
.attr('class', function (d, i) { return 'g g-' + i; })
.on('click', function (d) { return console.log(d); })
var cell = circle.append('path')
.data(voronoi.polygons(circles))
.attr('d', renderCell)
.attr('id', function (d, i) { return 'cell-' + i; })
circle.append('clipPath')
.attr('id', function (d, i) { return 'clip-' + i; })
.append('use')
.attr('xlink:href', function (d, i) { return '#cell-' + i; })
circle.append('circle')
.attr('clip-path', function (d, i) { return 'url(#clip-' + i + ')'; })
.attr('cx', function (d) { return d.x; })
.attr('cy', function (d) { return d.y; })
.attr('r', radius)
.style('fill', function (d, i) { return color(i); })
function renderCell(d) {
return d == null ? null : 'M' + d.join('L') + 'Z'
}
function move(sel) {
d3.select(sel)
.raise()
.select('circle')
.transition()
.ease(d3.easeLinear)
.duration(200)
.attr('cx', function (d) { return d.x = Math.round(Math.random() * (width - radius * 2) + radius); })
.attr('cy', function (d) { return d.y = Math.round(Math.random() * (height - radius * 2) + radius); })
cell = cell.data(voronoi.polygons(circles))
.attr('d', renderCell)
d3.select('span.x-value').text(d3.select(sel).datum().x)
d3.select('span.y-value').text(d3.select(sel).datum().y)
}
d3.interval(function () { return move('.g-3'); }, 1000)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- http://www.basscss.com/ -->
<link href="//npmcdn.com/basscss@8.0.2/css/basscss.min.css" rel="stylesheet">
<style>
body {
font-family: Consolas, monaco, monospace;
background: #130C0E;
color: #FDBB30;
}
path {
pointer-events: all;
fill: none;
stroke: #666;
stroke-opacity: 0.2;
}
.g:hover { opacity: 0.4;}
span { letter-spacing: 4px; }
</style>
</head>
<body>
<header class="fixed top-0 left-0 m2">
<p>red circle x: <span class="x-value"></span> : y: <span class="y-value"></span></p>
</header>
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js" charset="utf-8"></script>
<!-- d3 code -->
<script src=".script-compiled.js" charset="utf-8"></script>
</body>
</html>
const svg = d3.select('svg'),
width = +svg.attr('width'),
height = +svg.attr('height'),
radius = 32
const circles = d3.range(9).map(() => {
return {
x: Math.round(Math.random() * (width - radius * 2) + radius),
y: Math.round(Math.random() * (height - radius * 2) + radius)
}
})
const color = d3.scaleOrdinal()
.range(d3.schemeCategory10)
const voronoi = d3.voronoi()
.x(d => d.x)
.y(d => d.y)
.extent([
[-1, -1],
[width + 1, height + 1]
])
const circle = svg.selectAll('g')
.data(circles)
.enter().append('g')
.attr('class', (d, i) => 'g g-' + i)
.on('click', d => console.log(d))
let cell = circle.append('path')
.data(voronoi.polygons(circles))
.attr('d', renderCell)
.attr('id', (d, i) => 'cell-' + i)
circle.append('clipPath')
.attr('id', (d, i) => 'clip-' + i)
.append('use')
.attr('xlink:href', (d, i) => '#cell-' + i)
circle.append('circle')
.attr('clip-path', (d, i) => 'url(#clip-' + i + ')')
.attr('cx', d => d.x)
.attr('cy', d => d.y)
.attr('r', radius)
.style('fill', (d, i) => color(i))
function renderCell(d) {
return d == null ? null : 'M' + d.join('L') + 'Z'
}
function move(sel) {
d3.select(sel)
.raise()
.select('circle')
.transition()
.ease(d3.easeLinear)
.duration(200)
.attr('cx', d => d.x = Math.round(Math.random() * (width - radius * 2) + radius))
.attr('cy', d => d.y = Math.round(Math.random() * (height - radius * 2) + radius))
cell = cell.data(voronoi.polygons(circles))
.attr('d', renderCell)
d3.select('span.x-value').text(d3.select(sel).datum().x)
d3.select('span.y-value').text(d3.select(sel).datum().y)
}
d3.interval(() => move('.g-3'), 1000)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment