You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
11 KiB

5 years ago

<!DOCTYPE html>
<meta charset="utf-8">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<link rel="canonical" href="http://d3js.org/">
<title>cola.js: Constraint-based Layout in the Browser</title>
<style>
@import url(style.css);
#examples {
width: 960px;
height: 189px;
margin-bottom: 2em;
}
.examplecontainer {
width: 226px;
height: 180px;
float: left
}
.example img {
margin-left: auto;
margin-right: auto;
margin-top: auto;
margin-bottom: auto;
max-width: 90%;
max-height: 90%;
height: auto;
border: solid 2px #fff;
}
.example:hover img {
border-color: steelblue;
}
.example:not(:nth-child(4n)) img {
margin-right: 13px;
}
#left {
float: right;
width: 50%;
}
#right {
margin-right: 50%;
}
</style>
<div id="body">
<header>
<b><a href="./">Overview</a></b>
<a style="margin-left:1em;" href="https://github.com/tgdwyer/WebCola/wiki">Wiki</a>
<a style="margin-left:1em;" href="http://marvl.infotech.monash.edu/webcola/doc/index.html">API</a>
<a style="margin-left:1em;" href="https://github.com/tgdwyer/WebCola">Source</a>
</header>
<h1>cola.js</h1>
<h2>Constraint-Based Layout in the Browser</h2>
<div id="examples"></div>
<script src="extern/d3.v3.min.js?3.0.0rc1"></script>
<link rel="stylesheet" href="extern/hljs/styles/github.css">
<script src="extern/hljs/highlight.pack.js"></script>
<script>
hljs.initHighlightingOnLoad();
var examples = [
"downwardedges",
"unconstrained",
"unconstrainedsmallworld",
"nonoverlapping",
"smallnonoverlappinggraph",
"modifyinggraph",
"onlinebrowse",
"alignment",
"smallgroups",
"browsemovies.gif",
"SucroseBreakdown",
"unix",
"ariel",
"egonetwork",
"disconnected_graphs",
"powergraph",
"3dLayout.gif",
"dotpowergraph",
"gridifiedSmallGroups",
"3dtree.gif",
"cygenegene.gif",
"pageBoundsConstraints",
"smallworldwithgroups",
"brainnetwork2.gif"
];
function shuffle(array) {
var m = array.length, t, i;
// While there remain elements to shuffle.
while (m) {
// Pick a remaining element.
i = Math.floor(Math.random() * m--);
// And swap it with the current element.
t = array[m];
array[m] = array[i];
array[i] = t;
}
return array;
}
d3.select("#examples").selectAll(".example")
.data(shuffle(examples).slice(0, 24))
.enter()
.append('div')
.attr('class', 'examplecontainer')
.append("a")
.attr("class", "example")
.attr("href", function (d) {
return "examples/" + (d.match(/\.gif/) ? d.slice(0, -4) : d) + ".html"
})
.append("img")
.attr("src", function (d) {
return "examples/" + d + (d.match(/\.gif/) ? '' : ".png")
});
</script>
<!--<p><aside>See <a href="https://github.com/mbostock/d3/wiki/Gallery">more examples</a>.</aside>-->
<p><b>cola.js</b> (A.K.A. "WebCoLa") is an <a href="https://raw.github.com/tgdwyer/WebCola/master/LICENSE">open-source</a> JavaScript library for arranging your HTML5 documents and diagrams using constraint-based optimization techniques.
<p>
It works well with libraries like <a href="http://d3js.org">D3.js</a>, <a href="http://www.svgjs.com">svg.js</a>, and <a href="http://js.cytoscape.org">Cytoscape.js</a>.
The core layout is based on a complete rewrite in Javascript of the C++ <a href="http://adaptagrams.org">libcola</a> library.
</p>
<aside>
<p>
<b>cola.js</b> is developed by <br /><a href="http://marvl.infotech.monash.edu/~dwyer">Tim Dwyer</a> at the <a href="http://marvl.infotech.monash.edu">
Monash Adaptive Visualisation Lab.
<img src="http://marvl.infotech.monash.edu.au/wp-content/themes/marvl/marvl.png" width="155px" alt="MArVL Logo" />
</a>
</p>
<p>
Additional contributions gratefully received from:
<ul> <li>Maxim Shishmarev</li>
<li>Nicholas Smith</li>
<li><a href="https://github.com/bollwyvl">bollwyvl</a></li>
<li><a href="https://github.com/Craxic">Matt Ready</a></li>
<li><a href="https://github.com/maxkfranz">Max Franz</a></li>
</ul>
</p>
</aside>
<p>
It also has an adaptor for d3.js that allows you to use cola as a drop-in replacement for the <a href="https://github.com/mbostock/d3/wiki/Force-Layout">D3 force layout</a>.
The layout converges to a local optimum unlike the D3 force layout, which forces convergence through a simple annealing strategy.
Thus, compared to D3 force layout:
<ul>
<li>CoLa achieves higher quality layout;</li>
<li>is much more stable in <a href="examples/browsemovies.html">interactive applications</a> (no "jitter");</li>
<li>it allows user specified constraints such as <a href="examples/alignment.html">alignments</a> and <a href="examples/smallgroups.html">grouping</a>;</li>
<li>it can automatically generate constraints to:
<ul>
<li><a href="examples/smallnonoverlappinggraph.html">avoid overlapping nodes</a>; or</li>
<li> provide <a href="examples/unix.html">flow layout for directed graphs</a>;</li>
</ul> </li>
<li>it may be less scalable to very large graphs.</li>
</ul>
However, it works well on an average machine on graphs with fewer than 100 nodes.
</p>
<aside><b>&#8656; NEW! NUOVO! NOUVEAU!</b>
</aside> <p>
cola.js can now (optionally) <a href="examples/unix.html">route edges to avoid intersections with node boundaries</a>.
</p>
<h2>Getting Started with D3</h2>
<p>
Replacing D3 force layout with cola.js is easy. Include the following in your html:
<pre><code class="html">&lt;script src="http://marvl.infotech.monash.edu/webcola/cola.v3.min.js"&gt;&lt;/script&gt;</code></pre>
</p>
<p>Or, if you don't like your javascript files being loaded from Australia, then host the cola.v3.min.js file locally.</p>
<p>Then replace D3 force with cola as follows:</p>
<table>
<tr>
<td>D3 force setup:</td>
<td>cola setup:</td>
</tr>
<tr>
<td>
<pre><code>var force = d3.layout.force()
.charge(-120)
.linkDistance(30)
.size([width, height]);
</code></pre>
</td>
<td>
<pre><code>var d3cola = cola.d3adaptor()
.linkDistance(30)
.size([width, height]);
</code></pre>
</td>
</tr>
</table>
<p>You then use <code>cola</code> as you would <code>force</code> (or just continue to call it <code>force</code> if you don't care what it's actually doing as much as me).</p>
<p>
Note that while with D3 force layout you may have had to mess with parameters like "charge" to get reasonable node separation,
cola should do a much better job of respecting the specified link distance in the final layout.
This is because cola is directly trying to minimize the variance between ideal link distance and the actual distance in the drawing.
In other words, just set linkDistance to something reasonable for the size of your nodes (in the same coordinate system).
</p>
<p>
There are some other optional parameters available. In the <a href="examples/downwardedges.html">downward pointing edges example</a>
we kick off layout like so:
</p>
<pre><code>d3cola
.nodes(graph.nodes)
.links(graph.links)
.constraints(graph.constraints)
.symmetricDiffLinkLengths(5)
.avoidOverlaps(true)
.start(10,15,20);
</code></pre>
<p>We specify nodes and links exactly as in D3 force layout. However, <code>constraints</code> is a new parameter. It is an array containing constraints specified like so:<p>
<p><pre><code>{"axis":"y", "left":0, "right":1, "gap":25}</code></pre></p>
<p>This says that the center of <code>graph.nodes[0]</code> must be at least 25 pixels above the center of <code>graph.nodes[1]</code>. To be more precise, it is an inequality constraint that requires: <pre><code>graph.nodes[0].y + gap <= graph.nodes[1].y</code></pre></p>
<p><code>avoidOverlaps(true)</code> dynamically generates constraints while layout progresses in order to prevent the bounding boxes of nodes from sliding over one another (see <a href="examples/smallnonoverlappinggraph.html">this example</a>).</p>
<p><code>symmetricDiffLinkLengths(5)</code> computes ideal lengths on each link to make extra space around high-degree nodes, using 5 as the basic length.
Alternately, you can pass your own function <code>f</code> into <code>linkDistance(f)</code> that returns a specific length for each link (e.g. based on your data).</p>
<p>
The <code>start()</code> method now includes up to three integer arguments. In the example above, start will initially apply 10 iterations of layout with no constraints, 15 iterations with only structural (user-specified) constraints and 20 iterations of layout with all constraints including anti-overlap constraints.
Specifying such a schedule is useful to allow the graph to untangle before making it relatively "rigid" with constraints.
</p>
<p>Click through the examples above to see other cola.js features in action.</p>
<p>I'm currently working hard to add more options and to support more classes of constraints, so please watch this space - and don't be shy about <a href="http://marvl.infotech.monash.edu/~dwyer">sending me feedback</a>.</p>
</div>
<h2>Using cola.js in cytoscape.js</h2>
<p>
<a href="http://js.cytoscape.org">Cytoscape.js</a> has <a href="https://github.com/cytoscape/cytoscape.js-cola">full support for Cola.js via an extension</a>. Cytoscape.js has a full graph
theory model, highly customisable styling, gesture support, and layouts &mdash; such that Cola.js can be run in Cytoscape.js
in a single line of code:
</p>
<pre><code>cy.layout({ name: 'cola' /* and maybe some other options */ });</code></pre>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-63535113-1', 'auto');
ga('send', 'pageview');
</script>