Use d3.js to draw some circles. When circles are at same location there may be other attributes which are interesting about the overlapping circles. This is a method to separate those circles on the user interface to give the user separate handling.
Last active
November 5, 2017 20:46
-
-
Save louking/5362898bf5ed4388fdd4120518d77a95 to your computer and use it in GitHub Desktop.
circles explode
This file contains 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: apache-2.0 | |
height: 500 | |
scrolling: no | |
border: yes |
This file contains 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
circle { | |
fill: steelblue; | |
stroke: black; | |
stroke-width: 1.5px; | |
} | |
circle.handle { | |
fill: red; | |
} |
This file contains 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
var rcircle = 10, // r for circle | |
dexp = rcircle * 4, // distance for explosion | |
durt = 500, // transition duration (msec) | |
pi = Math.PI; | |
var t = d3.transition(durt); | |
var svg = d3.select("svg"); | |
d3.json( | |
"circles.json", | |
function(error, data) { | |
if (error) throw error; | |
// showing general pattern from https://bl.ocks.org/mbostock/3808218 but in this case only enter() will be executed | |
// data join | |
var circle = svg.selectAll("circle").data(data); | |
// update | |
// nothing to do here | |
// enter | |
circle | |
.enter() | |
.append("circle") | |
.merge(circle) | |
.attr("r", rcircle) | |
.attr("cx", function(d) { return d.x; }) | |
.attr("cy", function(d) { return d.y; }) | |
.attr("cid", function(d) { return d.id; }) | |
.attr("class", function(d) { return "c-loc-" + d.loc; }) | |
.on("click", explodeData); | |
// exit | |
circle.exit().remove(); | |
} | |
); | |
function explodeData(d, i) { | |
// Use D3 to select element and also all at same location | |
var thisc = d3.select(this); | |
var theselocs = d3.selectAll(".c-loc-" + d.loc) | |
var numlocs = theselocs.size(); | |
// if only one at location, maybe there is some special processing | |
if (numlocs == 1) { | |
// handle single selection click | |
// multiple at location, explode | |
} else { | |
// if not selected yet, explode all in same loc | |
if (!thisc.attr("exploded")) { | |
theselocs.attr("exploded", true); | |
var cx = Number(thisc.attr("cx")); | |
var cy = Number(thisc.attr("cy")); | |
// create lines now so they're underneath | |
// x1 = x2, y1 = y2 initially because we'll be transitioning | |
theselocs.each(function (d,i) { | |
svg.append('line') | |
.attr("class", "l-loc-" + d.loc) | |
.attr("x1", cx) | |
.attr("y1", cy) | |
.attr("x2", cx) | |
.attr("y2", cy) | |
.attr("stroke-width", 1.5) | |
.attr("stroke", "black") | |
.transition(durt) | |
.attr("x2", cx + dexp * Math.cos((2*pi/numlocs)*i)) | |
.attr("y2", cy + dexp * Math.sin((2*pi/numlocs)*i)) | |
}); | |
// create handle for original location | |
svg.append("circle") | |
.attr("id", "exploded-" + d.loc) | |
.attr("class", "handle") | |
.attr("c-loc", d.loc) | |
.attr("r", rcircle) | |
.attr("cx", cx) | |
.attr("cy", cy) | |
.on("click", unexplodeData); | |
// explode | |
theselocs | |
.each(function(d, i){ | |
thisc = d3.select(this); | |
// move to end to obsure line | |
thisc.raise(); | |
// transition to new location | |
thisc.transition(t) | |
.attr("cx", cx + dexp * Math.cos((2*pi/numlocs)*i)) | |
.attr("cy", cy + dexp * Math.sin((2*pi/numlocs)*i)); | |
}); | |
// if exploded and individual selected, maybe there is some special processing | |
} else { | |
// handle single selection click | |
} | |
} // multiple at location | |
}; | |
function unexplodeData(d, i) { | |
// Use D3 to select element | |
var thisc = d3.select(this); | |
var loc = thisc.attr("c-loc"); | |
var cx = thisc.attr("cx"); | |
var cy = thisc.attr("cy"); | |
// set exploded circles to original state | |
d3.selectAll(".c-loc-" + loc) | |
.transition(t) | |
.attr("selected", null) | |
.attr("cx", cx) | |
.attr("cy", cy) | |
.attr("exploded", null); | |
// shrink lines | |
d3.selectAll(".l-loc-" + loc) | |
.transition(t) | |
.attr("x2", cx) | |
.attr("y2", cy) | |
.remove() | |
// remove handle | |
d3.select("#exploded-" + loc).remove(); | |
}; |
This file contains 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
[ | |
{ "id":1, "loc":1, "x":140, "y":180 }, | |
{ "id":2, "loc":1, "x":140, "y":180 }, | |
{ "id":3, "loc":1, "x":140, "y":180 }, | |
{ "id":4, "loc":1, "x":140, "y":180 }, | |
{ "id":5, "loc":2, "x":520, "y":70 }, | |
{ "id":6, "loc":2, "x":520, "y":70 }, | |
{ "id":7, "loc":2, "x":520, "y":70 }, | |
{ "id":8, "loc":2, "x":520, "y":70 }, | |
{ "id":9, "loc":2, "x":520, "y":70 }, | |
{ "id":10, "loc":2, "x":520, "y":70 } | |
] |
This file contains 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
<link href="circles.css" rel="stylesheet"> | |
<svg width=720 height=250></svg> | |
<script src="//d3js.org/d3.v4.min.js"></script> | |
<script src="circles.js"></script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment