dagre-d3 & HTML label
by lborgman
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div class="live map">
<svg><g/></svg>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.tipsy/1.0.3/jquery.tipsy.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dagre-d3/0.6.1/dagre-d3.min.js"></script>
</body>
</html>
CSS
body {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 0;
padding: 0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
background: #333;
}
@-webkit-keyframes flash {
0%,
50%,
100% {
opacity: 1;
}
25%,
75% {
opacity: 0.2;
}
}
@keyframes flash {
0%,
50%,
100% {
opacity: 1;
}
25%,
75% {
opacity: 0.2;
}
}
.warn {
-webkit-animation-duration: 5s;
animation-duration: 5s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
-webkit-animation-iteration-count: 1;
animation-iteration-count: 1;
}
.live.map {
width: 100%;
height: 100%;
}
svg {
width: 100%;
height: 100%;
overflow: hidden;
}
.live.map div.node {
width: 2.062726176115803rem;
height: 3.618817852834741rem;
display: grid;
grid-auto-columns: 8% 42% 42% 8%;
grid-auto-rows: 70% 30%;
font: 0.05em 'Courier New', Courier, monospace;
color: white;
}
.live.map .node rect {
stroke-width: 1.5px;
stroke: #bbb;
fill: #666;
}
.live.map .node>.run-status {
grid-column: 1;
grid-row: 1 / 3;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
.live.map .node>.name {
grid-column: 2 / 4;
grid-row: 1;
font-size: 16px;
}
.live.map .node>.start {
grid-column: 2;
grid-row: 2;
}
.live.map .node>.elapsed {
grid-column: 3;
grid-row: 2;
text-align: end;
}
.live.map .node>.quality-status {
grid-column: 4;
grid-row: 1 / 3;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
.live.map .node p {
margin: 0;
padding: 3px;
}
.live.map .r-completed .run-status,
.live.map .q-completed .quality-status {
background-color: #7f7;
}
.live.map .r-running .run-status,
.live.map .q-running .quality-status {
background-color: #ffed68;
}
.live.map .r-error .run-status,
.live.map .q-error .quality-status...
JavaScript
function FlowGenerator() {
var self = this;
var svg;
var inner;
var render;
var zoom;
var g;
var gNodes;
var transform = {
translateX: 0,
translateY: 0,
scale: 1
}
let allNodes = [];
let runningNodes = [];
let idCount = 6;
self.initChart = function () {
svg = d3.select("svg");
inner = svg.select("g");
render = new dagreD3.render();
g = new dagreD3.graphlib.Graph();
g.setGraph({
nodesep: 70,
ranksep: 50,
rankdir: "LR",
marginx: 20,
marginy: 20
});
g.setDefaultEdgeLabel(function () { return {}; });
zoom = d3.zoom().on("zoom", function () {
inner.attr("transform", d3.event.transform);
if (d3.event.sourceEvent != undefined) {
if (d3.event.sourceEvent instanceof WheelEvent) {
transform.translateX = d3.event.transform.x;
transform.translateY = d3.event.transform.y;
transform.scale = d3.event.transform.k;
}
if (d3.event.sourceEvent instanceof MouseEvent) {
transform.translateX = d3.event.transform.x;
transform.translateY = d3.event.transform.y;
}
}
});
svg.call(zoom);
}
self.updateChart = function (nodes) {
let node;
let html;
let className;
for (let i = 0, x = nodes.length; i < x; ++i) {
node = nodes[i];
g.setNode(node.id, createNodeObject(node));
allNodes.push(node);
}
for (let i = 0, x = nodes.length; i < x; ++i) {
node = nodes[i];
if (node.hasOwnProperty('prev_id')) {
g.setEdge(node.prev_id, node.id);
}
}
renderGraph(true);
}
function createNodeObject(node) {
let html;
...