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

112 lines
4.5 KiB
HTML

5 years ago
<!doctype html>
<html>
<head>
<script type="text/javascript" src="../../pattern/canvas.js"></script>
</head>
<body>
<script type="text/canvas">
function setup(canvas) {
canvas.size(800, 500);
// Import the graph.js module asynchronously.
// Import the commonsense.js data asynchronously.
include("http://www.clips.ua.ac.be/media/canvas/graph.js");
include("http://www.clips.ua.ac.be/media/canvas/data/commonsense.js");
// Using include() in the setup() function ensures that
// everything will be done loading at the first draw().
// We can think of many interesting ways to import extra JavaScript modules.
try {
g.clear(); halo.clear(); // Clear previous run (if any).
} catch(e) {}
}
function draw(canvas) {
if (canvas.frame == 1) {
// The first frame is a good time to initialize the graph.
// At this point we are certain that the module has finished loading.
// Create a new Graph object:
g = new Graph();
// Traverse the relations in the common sense dataset.
// Loading commonsense.js defines a list of relations named "commonsense".
// Each relation has the form: [concept1, relation, concept2, context].
// For example, ["red", "is-property-of", "rose", "nature"].
// Add each relation as an edge (connection) to the graph.
Array.enumerate(commonsense, function(i, r) {
g.addEdge(r[0], r[2], {type:r[1], context:r[3]});
});
// Graph.node() retrieves a Node object by id.
// Node.flatten() returns a list with the Node (depth=0),
// each node connected to it (depth=1), and so on.
// We call this the concept "halo":
// the latent concepts that reinforce the concept itself.
// Create a subgraph of the node's halo:
halo = g.copy(canvas.element, g.node('rocket').flatten(2));
// Note how we pass Canvas.element, the drawing context.
// Calculcate Graph.eigenvectorCentrality().
// This is a measure of each node's importance,
// based on the (indirect) incoming connections.
// Once calculated we can then use Node.weight.
halo.eigenvectorCentrality();
// Similarly, Graph.betweennessCentrality() is a
// measure of node importance based on passing traffic.
// Once calculted we can use Node.centrality.
halo.betweennessCentrality();
// Traverse all the nodes in the halo.
// Each node will have an associated text label displaying its id.
// The text label is stored in a <div class="node-label"> element,
// for which we can define CSS styles.
Array.enumerate(halo.nodes, function(i, n) {
n.radius = 4 + 6 * n.weight;
n.text.style.marginLeft = n.radius + 2 + "px";
n.text.style.marginTop = -n.radius - 2 + "px";
n.text.style.fontFamily = "Arial";
n.text.style.fontSize = "9px";
n.text.style.textTransform = "uppercase";
});
// Some nodes have a lot of "leaf" nodes, that is,
// nodes that only connect to this node.
// We want to prune some of them to avoid cluttering the visualization.
Array.enumerate(halo.nodes, function(i, n1) {
Array.enumerate(n1.links, function(j, n2) {
if (n1.links.length > 10 && n2.links.length == 1) {
halo.remove(n2);
}
});
});
// Graph.shortestPath() takes two nodes and returns
// the shortest path between them as a list of nodes.
// To get the edges connecting these nodes, we can use the edges() function.
var p = halo.shortestPath("expensive", "rocket");
Array.enumerate(edges(p), function(i, e) {
e.stroke = color(0, 0.2, 1);
e.strokewidth = 1.25;
});
// We could also highlight the nodes along the path:
Array.enumerate(p, function(i, n) {
n.fill = color(0, 0.2, 1, 0.5);
n.text.style.background = "#000";
n.text.style.color = "#fff";
});
}
// The Graph.layout.iterations increments each time Graph.update() is called.
// Graph.update() calculates the attractive and repulsive forces between nodes.
// We set a limit to the number of updates + redraws,
// so the CPU doesn't start overheating.
if (halo.layout.iterations < 1000) {
canvas.clear();
//shadow(); // Looks nice but slow.
background(1);
fill(0, 0.2, 1, 0.2);
stroke(0, 0.5);
strokewidth(1);
halo.update();
halo.draw(false, true); // weighted=false, directed=true (arrowheads)
}
// When the user drags the mouse on a node,
// Graph.layout.iterations is reset to 0, so the graph is redrawn.
halo.drag(canvas.mouse);
}
function stop(canvas) {
halo.clear();
}
</script>
</body>
</html>