Skip to content

Instantly share code, notes, and snippets.

@kenpenn
Last active August 13, 2016 01:59
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 kenpenn/268878b410ddb1201277be3f0305d566 to your computer and use it in GitHub Desktop.
Save kenpenn/268878b410ddb1201277be3f0305d566 to your computer and use it in GitHub Desktop.
force simulation using translate
license: gpl-3.0
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>v4 fd test</title>
<style>
body {
font-family: sans-serif;
margin: 0;
min-height: 500px;
}
line {
stroke: goldenrod;
stroke-width: 1.5px;
}
circle.node {
cursor: pointer;
fill: #000;
stroke: none;
}
</style>
</head>
<body>
<svg></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var width = 960;
var height = 500;
var svg = d3.select('svg')
.attr('width', width)
.attr('height', height);
var randRange = function (min, max) {
return Math.round(min + Math.random() * (max - min));
};
var parts = {
bod: { ld : 10 },
head: { ld : 50, r : 24 },
arm: { ld : 40 },
elbow: { ld : 50 },
hand: { ld : 50, r : 12 },
hips: { ld : 70 },
leg: { ld : 10 },
knee: { ld : 60 },
foot: { ld : 100, r : 15 }
};
var bod = {
nodes: [
{ id: 'bod', part: 'bod', req: { x: 0, y: -125 }},
{ id: 'hips', part: 'hips', req: { x: 0, y: -26 }},
{ id: 'lLeg', part: 'leg', req: { x: -17, y: 3 }},
{ id: 'lKnee', part: 'knee', req: { x: -46, y: 72 }},
{ id: 'lFoot', part: 'foot', req: { x: -37, y: 180 }, outer: true },
{ id: 'rLeg', part: 'leg', req: { x: 20, y: 7 }},
{ id: 'rKnee', part: 'knee', req: { x: 46, y: 72 }},
{ id: 'rFoot', part: 'foot', req: { x: 37, y: 180 }, outer: true },
{ id: 'head', part: 'head', req: { x: 0, y: -180 }, outer: true },
{ id: 'lArm', part: 'arm', req: { x: -45, y: -120 }},
{ id: 'lElbow', part: 'elbow', req: { x: -70, y: -60 }},
{ id: 'lHand', part: 'hand', req: { x: -45, y: 11 }, outer: true },
{ id: 'rArm', part: 'arm', req: { x: 45, y: -120 }},
{ id: 'rElbow', part: 'elbow', req: { x: 70, y: -60 }},
{ id: 'rHand', part: 'hand', req: { x: 45, y: 11 }, outer: true }
],
links: [
{ source: 'bod', target: 'hips'},
{ source: 'bod', target: 'head'},
{ source: 'bod', target: 'lArm'},
{ source: 'lArm', target: 'lElbow'},
{ source: 'lElbow', target: 'lHand'},
{ source: 'bod', target: 'rArm'},
{ source: 'rArm', target: 'rElbow'},
{ source: 'rElbow', target: 'rHand'},
{ source: 'hips', target: 'lLeg'},
{ source: 'lLeg', target: 'lKnee'},
{ source: 'lKnee', target: 'lFoot'},
{ source: 'hips', target: 'rLeg'},
{ source: 'rLeg', target: 'rKnee'},
{ source: 'rKnee', target: 'rFoot'},
]
};
// set random x,y vals so you get that crazy flying together behavior like d3 v3
bod.nodes.forEach(function(node) {
node.x = randRange(10, width - 10);
node.y = randRange(10, height - 10);
bod.links.forEach(function(link) {
if ( link.source == node.id ){
link.x1 = node.x;
link.y1 = node.y;
} else if ( link.target == node.id ) {
link.x2 = node.x;
link.y2 = node.y;
}
});
});
var fdGrp = svg.append('g');
var linkGrp = fdGrp.append('g')
.attr('class', 'links');
var links = linkGrp
.selectAll('line.link')
.data(bod.links)
.enter()
.append('line')
.attr('class', function(d) {
return 'line src-' + d.source + ' trg-' + d.target;
})
.attr('x1', function(d) {
return d.x1;
})
.attr('y1', function(d) {
return d.y1;
})
.attr('x2', function(d) {
return d.x2;
})
.attr('y2', function(d) {
return d.y2;
});
var nodeGrp = fdGrp.append('g')
.attr('class', 'nodes');
var nodes = nodeGrp
.selectAll('circle.node')
.data(bod.nodes)
.enter()
.append('circle')
.attr('class', function(d) {
var outer = d.outer ? ' outer' : '';
return 'node ' + d.id + outer;
})
.attr('transform', function(d) {
return 'translate(' + d.x + ',' + d.y + ')';
})
.attr('r', function (d) {
return parts[d.part].r ? parts[d.part].r : 4;
})
.call(d3.drag()
.on("start", dragstart)
.on("drag", dragging)
.on("end", dragend));
var sim = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter( width / 2, height / 2 ));
sim
.nodes(bod.nodes)
.on("tick", function() {
nodes.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
links
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
});
sim.force("link")
.links(bod.links)
.distance(function (d) {
return parts[d.target.part].ld;
});
function dragstart(d) {
if (!d3.event.active) { sim.alphaTarget(0.3).restart(); }
d.fx = d.x;
d.fy = d.y;
}
function dragging(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragend(d) {
if (!d3.event.active) sim.alphaTarget(0);
if (!d.outer) {
d.fx = null;
d.fy = null;
}
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment