Skip to content

Instantly share code, notes, and snippets.

@jwilber
Created January 29, 2019 06:23
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 jwilber/3f232ede82169fe439681647b144d6af to your computer and use it in GitHub Desktop.
Save jwilber/3f232ede82169fe439681647b144d6af to your computer and use it in GitHub Desktop.
apply pack layout to existing nodes
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>
<svg style="width:600px;height:600px;" ></svg>
<body>
<script>
const width = 600;
const height = 600;
const svgD3 = d3.select('svg')
let sampleData = d3.range(250).map((d,i) => (
{r: 40 - i * 0.5,
value: width/2 + d3.randomNormal(0, 1.5)() * 50,
nodeGroup: i <= 23 ? 'llama' : i <= 39 ? 'resp' : 'dsn',
dotValue: i % 2 === 0 ?
d3.randomNormal(7, 2.5)().toFixed(1):
d3.randomNormal(4.5, .75)().toFixed(1),
'permDsn': d3.randomNormal(0, 1)().toFixed(1)
}));
const x = d3.scaleLinear()
.domain(d3.extent(sampleData.filter(d => d.nodeGroup === 'dsn'), d => +d.permDsn))
.rangeRound([width/4, width/1.5]); // hist width(left, right)
const nbins = 18;
function update(){
let data = sampleData.filter(d => d.nodeGroup === 'dsn')
//histogram binning
const histogram = d3.histogram()
.domain(x.domain())
.thresholds(x.ticks(nbins))
.value(d => d.permDsn);
//binning data and filtering out empty bins
const bins = histogram(data);
//g container for each bin
let binContainer = svgD3.append('g')
.attr('transform', `translate({x(d.x0)}, ${-height/8})`)
.selectAll(".gBin")
.data(bins);
// binContainer.exit().remove()
let binContainerEnter = binContainer.enter()
.append("g")
.attr("class", "gBin")
.attr("transform", d => `translate(${x(d.x0)}, ${height})`)
//need to populate the bin containers with data the first time
binContainerEnter.selectAll(".preHistPosit")
.data((d,i) => d.map((p, j) => {
return {idx: j,
dataIndex: i,
value: p.Value,
radius: (x(d.x1)-x(d.x0))/1.9
// permDsn: d.permDsn
}
}))
.enter()
.append("circle")
.attr('class', 'histCirc')
.attr('testStatValue', d => d.permDsn)
.attr('', function(d,i) {
if (i < 1 && d.dataIndex == 20) {
d3.select(this).classed('response1', true)
} else if (i < 1 && d.dataIndex == 9) {
d3.select(this).classed('response2', true)
} else if (i < 1 && d.dataIndex == 5) {
d3.select(this).classed('response3', true)
} else if (i < 1 && d.dataIndex == 11) {
d3.select(this).classed('response4', true)
} else if (i < 1 && d.dataIndex == 7) {
d3.select(this).classed('response5', true)
} else if (i < 1 && d.dataIndex == 6) {
d3.select(this).classed('response6', true)
} else if (i < 1 && d.dataIndex == 13) {
d3.select(this).classed('response7', true)
} else if (i < 1 && d.dataIndex == 8) {
d3.select(this).classed('response8', true)
} else if (i < 1 && d.dataIndex == 2) {
d3.select(this).classed('response9', true)
} else {
d3.select(this).classed('histogramNode', true)
}
})
.attr('', function(d) {
if (d.dataIndex > 19) { // determine which test-stat nodes to highlight
d3.select(this).classed('extreme', true)
} else {
d3.select(this).classed('notExtreme', true)
}
})
.transition()
.attr("cx", 0) //g element already at correct x pos
.attr("cy", d => - d.idx * 2 * d.radius - d.radius - (height/8)) // control height here
.attr("r", 0)
.transition()
.duration(800)
.attr('r', d => 0)
.style('opacity', 1)
.attr('fill' ,'pink')
.transition()
.attr('stroke-width', .3)
.attr('stroke', 'black')
binContainerEnter.merge(binContainer)
.attr("transform", d => `translate(${x(d.x0)}, ${height})`)
//enter/update/exit for circles, inside each container
let dots = binContainer.selectAll("circle")
.data(d => d.map((p, i) => {
return {idx: i,
value: p.Value,
radius: (x(d.x1)-x(d.x0))/2
}
}))
//UPDATE old elements present in new data.
//ENTER new elements present in new data.
dots.enter()
.append("circle")
.attr("class", "enter")
.attr("cx", 0) //g element already at correct x pos
.attr("cy", function(d) {
return - d.idx * 2 * d.radius - d.radius; })
.attr("r", 10)
.merge(dots)
.transition()
.duration(500)
.attr("r", function(d) {
return (d.length==0) ? 10 : d.radius; })
};//update
update();
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment