Built with blockbuilder.org
Last active
January 30, 2019 07:10
-
-
Save jwilber/c80548a912b03d6dafdef40305efd291 to your computer and use it in GitHub Desktop.
apply pack layout to existing nodes
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: mit |
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
<!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 = 500; | |
const height = 400; | |
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 | |
//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))/2 | |
} | |
})) | |
.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", 10) | |
.transition() | |
.duration(800) | |
.attr('r', 8) | |
.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