From 798ff4b0f923ce41c91393c96545dc9e5b0727d9 Mon Sep 17 00:00:00 2001 From: Michael Wayne Goodman Date: Thu, 8 Jan 2015 12:52:46 +0800 Subject: [PATCH 1/3] Add arcDiagram. --- arcdiagram/README.md | 7 ++ arcdiagram/arcdiagram.js | 158 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 arcdiagram/README.md create mode 100644 arcdiagram/arcdiagram.js diff --git a/arcdiagram/README.md b/arcdiagram/README.md new file mode 100644 index 0000000..3f0e6c8 --- /dev/null +++ b/arcdiagram/README.md @@ -0,0 +1,7 @@ +# d3.arcdiagram + +A plugin for rendering +[Arc Diagrams](http://en.wikipedia.org/wiki/Arc_diagram). +Example: + +http://bl.ocks.org/goodmami/fd03b250588e1e1143bd diff --git a/arcdiagram/arcdiagram.js b/arcdiagram/arcdiagram.js new file mode 100644 index 0000000..4ec43fc --- /dev/null +++ b/arcdiagram/arcdiagram.js @@ -0,0 +1,158 @@ +(function() { + d3.arcDiagram = function() { + var sortNodes, + sortLinks = arcDiagramSortLinks, + linkLevel = arcDiagramLinkLevelCompact, + nodeWidth = 0, + separation = 1, + nodeXOffset = 0, + levelHeight = arcDiagramLevelHeight, + nodes = [], + links = []; + + function arc() { + var levelIndex = d3.range(nodes.length).map(function() { return []; }), + nw = typeof nodeWidth === "function" ? nodeWidth : function() { return nodeWidth; }, + sep = typeof separation === "function" ? separation : function() { return separation; }, + nxo = typeof nodeXOffset === "function" ? nodeXOffset : function() { return nodeXOffset; }, + lh = typeof levelHeight === "function" ? levelHeight : function() { return levelHeight; }, + curX = 0, + nodeIndexMap, idx1, idx2; + + // node calculations + nodes.forEach(function(n, i) { n.index = i; }); + // if sorting nodes, do it here and create a mapping from old to + // new positions + nodeIndexMap = {}; + if (sortNodes) nodes.sort(sortNodes); + nodes.forEach(function(n, i) { + nodeIndexMap[n.index] = i; n.index = i; + // while we're iterating, we can set the x, dx, and y values + n.x = curX; + n.dx = nxo(n); + curX += nw(n) + nxo(n) + sep(n); + n.y = 0; + }); + + // link calculations + // first, reassign source and index, if necessary. + links.forEach(function(link) { + link.source = nodeIndexMap[link.source] || link.source; + link.target = nodeIndexMap[link.target] || link.target; + // also set distance, which is useful for sorting. + link.distance = Math.abs(link.source - link.target); + }); + if (sortLinks) links.sort(sortLinks); + + // now we can find the level of each link + links.forEach(function(link) { + link.level = linkLevel(link, levelIndex); + arcDiagramUpdateLevelIndex(link, levelIndex); + // and while we're iterating, set the position values + link.x1 = (nodes[link.source] || {}).x; + link.x2 = (nodes[link.target] || {}).x; + link.height = lh(link); + }); + } + + arc.sortNodes = function(x) { + if (!arguments.length) return sortNodes; + sortNodes = x; + return arc; + } + + arc.sortLinks = function(x) { + if (!arguments.length) return sortLinks; + sortLinks = x; + return arc; + } + + arc.linkLevel = function(x) { + if (!arguments.length) return linkLevel; + if (x.toLowerCase() == "compact") + linkLevel = arcDiagramLinkLevelCompact; + else if (x.toLowerCase() == "distance") + linkLevel = arcDiagramLinkLevelDistance; + else + linkLevel = x; + return arc; + } + + arc.nodeWidth = function(x) { + if (!arguments.length) return nodeWidth; + nodeWidth = typeof x === "function" ? x : +x; + return arc; + } + + arc.separation = function(x) { + if (!arguments.length) return separation; + separation = typeof x === "function" ? x : +x; + return arc; + } + + arc.nodeXOffset = function(x) { + if (!arguments.length) return nodeXOffset; + nodeXOffset = typeof x === "function" ? x : +x; + return arc; + } + + arc.levelHeight = function(x) { + if (!arguments.length) return levelHeight; + levelHeight = typeof x === "function" ? x : +x; + return arc; + } + + arc.nodes = function(x) { + if (!arguments.length) return nodes; + nodes = x; + return arc; + } + + arc.links = function(x) { + if (!arguments.length) return links; + links = x; + return arc; + } + + return arc; + } + + function arcDiagramSortLinks(a, b) { return a.distance - b.distance; } + + function arcDiagramLinkLevelCompact(link, levelIndex) { + var level = 1, idx1, idx2; + + if (link.source <= link.target) { + idx1 = link.source; idx2 = link.target; + } else { + idx1 = link.target; idx2 = link.source; + } + + for (var i = idx1; i < idx2; i++) { + if (levelIndex[i][level]) { + level += 1; + i = idx1 - 1; // restart the for-loop + continue; + } + } + return level; + } + + function arcDiagramLinkLevelDistance(link, levelIndex) { + return link.distance; + } + + function arcDiagramLevelHeight(link) { + return link.level; + } + + function arcDiagramUpdateLevelIndex(link, levelIndex) { + var idx1, idx2; + if (link.source <= link.target) { + idx1 = link.source; idx2 = link.target; + } else { + idx1 = link.target; idx2 = link.source; + } + d3.range(idx1, idx2).forEach(function(i) { levelIndex[i][link.level] = true; }); + } +})(); \ No newline at end of file From 34914e6fa55b18305a9d7e4112c2ec4fbf844da6 Mon Sep 17 00:00:00 2001 From: Michael Wayne Goodman Date: Thu, 8 Jan 2015 14:23:52 +0800 Subject: [PATCH 2/3] Fix node spacing bug in arcdiagram.js; add another example. --- arcdiagram/README.md | 3 ++- arcdiagram/arcdiagram.js | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arcdiagram/README.md b/arcdiagram/README.md index 3f0e6c8..681e428 100644 --- a/arcdiagram/README.md +++ b/arcdiagram/README.md @@ -2,6 +2,7 @@ A plugin for rendering [Arc Diagrams](http://en.wikipedia.org/wiki/Arc_diagram). -Example: +Examples: http://bl.ocks.org/goodmami/fd03b250588e1e1143bd +http://bl.ocks.org/goodmami/41d4ecc7520b73c21538 diff --git a/arcdiagram/arcdiagram.js b/arcdiagram/arcdiagram.js index 4ec43fc..b27f703 100644 --- a/arcdiagram/arcdiagram.js +++ b/arcdiagram/arcdiagram.js @@ -28,9 +28,8 @@ nodes.forEach(function(n, i) { nodeIndexMap[n.index] = i; n.index = i; // while we're iterating, we can set the x, dx, and y values - n.x = curX; - n.dx = nxo(n); - curX += nw(n) + nxo(n) + sep(n); + n.x = curX + nxo(n); + curX += nw(n) + sep(n); n.y = 0; }); @@ -155,4 +154,4 @@ } d3.range(idx1, idx2).forEach(function(i) { levelIndex[i][link.level] = true; }); } -})(); \ No newline at end of file +})(); From 4c4db95663c400bbba6186ec522b941428a2bfb3 Mon Sep 17 00:00:00 2001 From: Michael Wayne Goodman Date: Thu, 8 Jan 2015 14:25:25 +0800 Subject: [PATCH 3/3] Better markdown for arcdiagram README.md --- arcdiagram/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arcdiagram/README.md b/arcdiagram/README.md index 681e428..b51b488 100644 --- a/arcdiagram/README.md +++ b/arcdiagram/README.md @@ -4,5 +4,5 @@ A plugin for rendering [Arc Diagrams](http://en.wikipedia.org/wiki/Arc_diagram). Examples: -http://bl.ocks.org/goodmami/fd03b250588e1e1143bd -http://bl.ocks.org/goodmami/41d4ecc7520b73c21538 +* http://bl.ocks.org/goodmami/fd03b250588e1e1143bd +* http://bl.ocks.org/goodmami/41d4ecc7520b73c21538