Skip to content

Instantly share code, notes, and snippets.

@jrosskopf
Created May 19, 2013 16:22
Show Gist options
  • Save jrosskopf/5608145 to your computer and use it in GitHub Desktop.
Save jrosskopf/5608145 to your computer and use it in GitHub Desktop.
marker {
stroke: #666;
fill: #666;
overflow: visible;
}
path.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
.node circle {
stroke: #ccc;
}
.node circle.State {
fill: green;
}
.node circle.Event {
fill: red;
}
.node text {
pointer-events: none;
font: 10px sans-serif;
}
var width = 1024,
height = 480
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var force = d3.layout.force()
.gravity(0.05)
.linkDistance(function (n)
{
if (n.type == "State")
return 250;
else
return 50;
})
.charge(function (n) {
if (n.type == "State")
return -600;
else
return -300;
})
.size([width, height]);
d3.json("graph.json", function(error, json)
{
function firstIndexOrDefault(elements, comparator)
{
for (var i = 0; i < elements.length; i++) {
if (comparator(elements[i]))
return i;
}
return -1;
}
var graph = json.Graph;
var vertices = graph.Vertices.map(function (v) {
var n = {
name: v.Title,
type: v.VertexType
};
if (n.name == "Initial") {
n.x = 64;
n.y = height / 2;
n.fixed = true;
}
if (n.name == "Final") {
n.x = width - 64;
n.y = height / 2;
n.fixed = true;
}
return n;
});
var links = graph.Edges.map(function(e) {
var sourceIdx = firstIndexOrDefault(vertices, function(v) {
return v.name == e.From;
});
var targetIdx = firstIndexOrDefault(vertices, function(v) {
return v.name == e.To;
});
return {
source: sourceIdx,
target: targetIdx
};
});
force.nodes(vertices)
.links(links)
.start();
// build the arrow.
svg.append("svg:defs").selectAll("marker")
.data(["end"]) // Different link/path types can be defined here
.enter().append("svg:marker") // This section adds in the arrows
.attr("id", String)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 25)
.attr("refY", -2.0)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
// add the links and the arrows
var path = svg.append("svg:g").selectAll("path")
.data(links)
.enter().append("svg:path")
.attr("class", function(d) { return "link " + d.type; })
.attr("marker-end", "url(#end)");
var node = svg.selectAll(".node")
.data(vertices)
.enter().append("g")
.attr("class", "node")
.call(force.drag);
node.append("circle")
.attr("r", function(n) {
if (n.type == "State")
return 15;
else
return 10;
})
.attr("x", -8)
.attr("y", -8)
.attr("class", function(n) {
return n.type;
});
node.append("text")
.attr("dx", 18)
.attr("dy", ".35em")
.text(function(d) { return d.name });
force.on("tick", function()
{
path.attr("d", function(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" +
d.source.x + "," +
d.source.y + "A" +
dr + "," + dr + " 0 0,1 " +
d.target.x + "," +
d.target.y;
});
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
});
});
{"CorrelationId": "111bdb49f5b14dd8bc1eca80ace814e8", "CurrentState": "Initial", "Instance": {
"CorrelationId": "111bdb49f5b14dd8bc1eca80ace814e8"
}, "Graph": {
"Vertices": [
{
"Title": "Initial",
"VertexType": "State",
"TargetType": "State"
},
{
"Title": "Running",
"VertexType": "State",
"TargetType": "State"
},
{
"Title": "Failed",
"VertexType": "State",
"TargetType": "State"
},
{
"Title": "Final",
"VertexType": "State",
"TargetType": "State"
},
{
"Title": "Suspended",
"VertexType": "State",
"TargetType": "State"
},
{
"Title": "Initialized",
"VertexType": "Event",
"TargetType": "Event"
},
{
"Title": "Exception",
"VertexType": "Event",
"TargetType": "Exception"
},
{
"Title": "Finished",
"VertexType": "Event",
"TargetType": "Event"
},
{
"Title": "Suspend",
"VertexType": "Event",
"TargetType": "Event"
},
{
"Title": "Resume",
"VertexType": "Event",
"TargetType": "Event"
},
{
"Title": "Restart",
"VertexType": "Event",
"TargetType": "RestartData"
}
],
"Edges": [
{
"Title": "Initialized",
"To": "Initialized",
"From": "Initial"
},
{
"Title": "Initialized",
"To": "Running",
"From": "Initialized"
},
{
"Title": "Exception",
"To": "Exception",
"From": "Initialized"
},
{
"Title": "Exception",
"To": "Failed",
"From": "Exception"
},
{
"Title": "Finished",
"To": "Finished",
"From": "Running"
},
{
"Title": "Finished",
"To": "Final",
"From": "Finished"
},
{
"Title": "Suspend",
"To": "Suspend",
"From": "Running"
},
{
"Title": "Suspend",
"To": "Suspended",
"From": "Suspend"
},
{
"Title": "Resume",
"To": "Resume",
"From": "Suspended"
},
{
"Title": "Resume",
"To": "Running",
"From": "Resume"
},
{
"Title": "Restart",
"To": "Restart",
"From": "Failed"
},
{
"Title": "Restart",
"To": "Running",
"From": "Restart"
}
]
}, "CreatedAt": "2013-01-18T05:34:11.4203136+01:00", "ChangedAt": "2013-01-20T13:10:37.8164608+01:00", "FinishedAt": "2013-05-19T00:00:00.0000000+02:00"}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>d3.js StateMachine visualization</title>
<link rel="stylesheet" href="app.css">
</head>
<body>
</body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="app.js"></script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment