Skip to content

Instantly share code, notes, and snippets.

@tzellman
Last active August 29, 2015 14:15
Show Gist options
  • Save tzellman/4456d09c7fcc0fb26cbc to your computer and use it in GitHub Desktop.
Save tzellman/4456d09c7fcc0fb26cbc to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
svg circle {
cursor: pointer;
fill-opacity: 0.2;
}
svg text {
fill: darkgreen;
font-size: 30px;
font-weight: 700;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.1.0/lodash.min.js"></script>
<script src="http://marak.com/faker.js/js/faker.min.js"></script>
<script>
// assume these are passed in from somewhere (e.g in an Ember component)
var width = 1024,
data = [
{label: "1", value: 10},
{label: "2", value: 20},
{label: "3", value: 15},
{label: "4", value: 5},
{label: "5", value: 5},
{label: "5", value: 5},
{label: "5", value: 5},
{label: "5", value: 5},
{label: "5", value: 5}
],
height = 800,
rows = 1,
strokeWidth = 3;
data.forEach(function (d) {
d.terms = faker.lorem.words(5);
});
var bound = Math.min(width, height),
nodes = [],
foci = [],
fill = d3.scale.category10(),
_id = 0,
padding = 5,
cols = Math.ceil((data.length) / rows),
radius = ((width - (padding * data.length + 1)) / data.length) / 2;
var svg = d3.select("body").append("svg")
.attr("height", height)
.attr("width", width);
data.forEach(function (d, i) {
d.foci = i;
d._id = _id++;
nodes.push(d);
var row = Math.floor(i / cols),
col = Math.floor(i % cols),
yCenter = (row * (radius * 2 + padding)) + radius + padding,
xCenter = (col * (radius * 2 + padding)) + radius + padding;
var point = {x: xCenter, y: yCenter};
foci.push(point);
d.x = foci[d.foci].x;
d.y = foci[d.foci].y;
});
var node = svg.selectAll('g.entity')
.data(nodes)
.enter()
.append('g')
.attr('class', 'entity')
.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")";
});
function updateCircle() {
d3.select(this)
.transition().duration(300)
.ease("linear")
.attr("r", function (d) {
return radius;
});
}
node.append('circle')
.style("stroke", function (d) {
return d3.rgb(fill(d.foci)).darker(2);
})
.style("fill", function (d) {
return d3.rgb(fill(d.foci));
})
.style("stroke-width", function (d) {
return strokeWidth;
})
.each(updateCircle);
// Suppose the image is square, and is centered in a circle with radius r.
// Then, the square image should hit at 45 degrees, meaning that the width
// and height should be 2*sin(tao/8) * r
var imageWH = function (d) {
return 2 * Math.sin(6.28 / 8) * (radius - strokeWidth);
};
function updateImage() {
d3.select(this).transition().duration(300)
.ease("linear")
.attr("x", function (d) {
return -imageWH(d) / 2;
})
.attr("y", function (d) {
return -imageWH(d) / 2;
})
.attr("width", imageWH)
.attr("height", imageWH);
}
node.append("image")
.attr("xlink:href", function (d) {
return faker.internet.avatar();
}).each(updateImage);
node.on('click', function (n) {
selectNode(n._id);
});
var currentId = -1;
function selectNode(id) {
currentId = id;
// first move old center back
var others = d3.selectAll("g.entity")
.filter(function (d) {
return d._id !== id;
});
others.each(function (d, i) {
d.x = foci[d.foci].x;
d.y = foci[d.foci].y;
d3.select(this)
.transition().duration(300).ease("linear")
.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")";
});
}).each(function (d, i) {
d3.select(this).select("circle")
.transition().duration(300).ease("linear")
.attr("r", radius);
});
others.select("text").remove();
// now, move to the center
var selected = d3.selectAll("g.entity")
.filter(function (d) {
return d._id === id;
});
selected.each(function (d, i) {
d.x = width / 2 - radius;
d.y = height / 2 - radius;
d3.select(this)
.transition().duration(300).ease("linear")
.attr("transform", function (d) {
return "translate(" + d.x + "," + d.y + ")";
});
}).each(function (d, i) {
d3.select(this).select("circle")
.transition().duration(300).ease("linear")
.attr("r", radius * 1.5);
});
// add text
var text = selected.append('text')
.text(function (d) {
return d.terms.join(" ");
})
.each(function (d) {
// need to get the text width
var box = this.getBBox();
d3.select(this)
.attr("x", -box.width / 2)
.attr("y", radius * 1.5 + box.height);
});
}
setInterval(function () {
selectNode((currentId + 1) % data.length);
}, 2000);
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment