Skip to content

Instantly share code, notes, and snippets.

@jwilber
Last active October 14, 2018 06:01
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/1e0963096e8bdf634a637d647056b4bc to your computer and use it in GitHub Desktop.
Save jwilber/1e0963096e8bdf634a637d647056b4bc to your computer and use it in GitHub Desktop.
roughjs force diagram (click to move)
license: mit

Click to switch between spreading the circles / sending them to a histogram.

<!DOCTYPE html>
<html>
<head>
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rough.js/2.2.5/rough.min.js"></script>
</head>
<button id="clickMe" type="button">Move Nodes</button>
<body>
<svg id="svg" width="1200" height="500"></svg>
<script>
const width = 500
const height = 500
const radius = 25;
const svgd3 = d3.select("svg")
const trtCenter = width / 5
const cntrlCenter = width / 1.5
var rc = rough.svg(svg)
const sampleData = d3.range(50).map(() => ({r: radius,
value: width/2 + d3.randomNormal(0, 1.5)() * 50}))
var headPath = "M251.249,127.907c17.7,0,32.781-6.232,45.254-18.7c12.467-12.467,18.699-27.554,18.699-45.253 c0-17.705-6.232-32.783-18.699-45.255C284.029,6.233,268.948,0,251.249,0c-17.705,0-32.79,6.23-45.254,18.699 c-12.465,12.469-18.699,27.55-18.699,45.255c0,17.703,6.23,32.789,18.699,45.253C218.462,121.671,233.549,127.907,251.249,127.907 z";
// define force
let force = d3.forceSimulation()
.force('charge', d3.forceManyBody().strength(1))
force.force('x', d3.forceX().strength(.3).x( width / 2))
force.force('y', d3.forceY().strength(.3).y(height / 3.5))
.force('collision', d3.forceCollide(d => 12))
.nodes(sampleData)
.on('tick', changeNetwork)
let dots = svgd3.selectAll('.dot')
.data(sampleData)
.enter()
.append('g')
.attr('class', 'dot')
.attr('group', (d,i) => i % 2 == 0 ? 'trt' : 'ctrl')
function nodeTreatmentPos(d) {
return d.index % 2 == 0 ? trtCenter : cntrlCenter;
}
function changeNetwork() {
d3.selectAll('g.dot')
.attr('transform', d=> `translate(${d.x}, ${d.y})`)
}
d3.selectAll('.dot').append('g').attr('class', 'testStat').each(function(d,i) {
d3.select(this).node().appendChild( rc.path(headPath, {
stroke: 'black',
fillStyle: 'hachure',
strokeWidth: 2.25,
fill: 'pink',
roughness: 5.85,
})
)
})
d3.selectAll('.dot').selectAll('path').attr("transform", "scale(0.15,0.15)")
//
function moveNodes() {
d3.selectAll('.dot').select('path').attr('visibility', 'visibile')
force.force('center', null)
.force('collision', d3.forceCollide(d => 12))
.alphaDecay(.0005)
.velocityDecay(0.6)
force.force('x', d3.forceX().strength(1).x(nodeTreatmentPos))
force.force('y', d3.forceY().strength(1).y(height / 3.5))
force.alpha(.1).restart();
}
// force for center
function moveCenter() {
force//.force('center', null)
.force('collision', d3.forceCollide(d => 20))
.alphaDecay(.0005)
.velocityDecay(0.6)
force.force('x', d3.forceX().strength(1).x( width / 2))
force.force('y', d3.forceY().strength(1).y(height / 3.5))
force.alpha(.1).restart();
}
function moveHist(){
force.force('center', null)
.force('collision', d3.forceCollide(d => 15).strength(1.5))
.alphaDecay(.0005)
.velocityDecay(0.3)
.force('x', d3.forceX((d,i) => d.value).strength(1.3))
.force('y', d3.forceY(height/2 - radius).strength(0.03))
.on('tick', changeNetwork2)
force.alpha(.2).restart()
}
function changeNetwork2() {
d3.selectAll('.dot')
.attr('transform', d => `translate(${d.x}, ${Math.min(d.y, height/2 - radius - 1)})`)
}
// resolve locations of node on cliks
let toCenter = true;
d3.select('#clickMe')
.on('click', function() {
toCenter === true ? moveNodes() : moveHist()
toCenter = !toCenter
})
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment