Created
April 21, 2011 02:03
-
-
Save tingletech/933535 to your computer and use it in GitHub Desktop.
chaotic graph visualization
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" | |
"http://www.w3.org/TR/html4/strict.dtd"> | |
<html lang="en"> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | |
<title>arbor.js project template</title> | |
<link rel="stylesheet" href="style.css" type="text/css"> | |
</head> | |
<body> | |
<canvas id="viewport" width="800" height="600"></canvas> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script> | |
<!-- run from the original source files: --> | |
<!-- <script src="../../src/etc.js"></script> | |
<script src="../../src/kernel.js"></script> | |
<script src="../../src/graphics/colors.js"></script> | |
<script src="../../src/graphics/primitives.js"></script> | |
<script src="../../src/graphics/graphics.js"></script> | |
<script src="../../src/tween/easing.js"></script> | |
<script src="../../src/tween/tween.js"></script> | |
<script src="../../src/physics/atoms.js"></script> | |
<script src="../../src/physics/physics.js"></script> | |
<script src="../../src/physics/system.js"></script> | |
<script src="../../src/dev.js"></script> --> | |
<!-- run from the minified library file: --> | |
<script src="../../lib/arbor.js"></script> | |
<script src="main.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// main.js | |
// | |
// A project template for using arbor.js | |
// | |
(function($){ | |
var Renderer = function(canvas){ | |
var canvas = $(canvas).get(0) | |
var ctx = canvas.getContext("2d"); | |
var particleSystem | |
var that = { | |
init:function(system){ | |
// | |
// the particle system will call the init function once, right before the | |
// first frame is to be drawn. it's a good place to set up the canvas and | |
// to pass the canvas size to the particle system | |
// | |
// save a reference to the particle system for use in the .redraw() loop | |
particleSystem = system | |
// inform the system of the screen dimensions so it can map coords for us. | |
// if the canvas is ever resized, screenSize should be called again with | |
// the new dimensions | |
particleSystem.screenSize(canvas.width, canvas.height) | |
particleSystem.screenPadding(80) // leave an extra 80px of whitespace per side | |
// set up some event handlers to allow for node-dragging | |
that.initMouseHandling() | |
}, | |
redraw:function(){ | |
// | |
// redraw will be called repeatedly during the run whenever the node positions | |
// change. the new positions for the nodes can be accessed by looking at the | |
// .p attribute of a given node. however the p.x & p.y values are in the coordinates | |
// of the particle system rather than the screen. you can either map them to | |
// the screen yourself, or use the convenience iterators .eachNode (and .eachEdge) | |
// which allow you to step through the actual node objects but also pass an | |
// x,y point in the screen's coordinate system | |
// | |
ctx.fillStyle = "white" | |
ctx.fillRect(0,0, canvas.width, canvas.height) | |
particleSystem.eachEdge(function(edge, pt1, pt2){ | |
// edge: {source:Node, target:Node, length:#, data:{}} | |
// pt1: {x:#, y:#} source position in screen coords | |
// pt2: {x:#, y:#} target position in screen coords | |
// draw a line from pt1 to pt2 | |
ctx.strokeStyle = "rgba(0,0,0, .333)" | |
ctx.lineWidth = 1 | |
ctx.beginPath() | |
ctx.moveTo(pt1.x, pt1.y) | |
ctx.lineTo(pt2.x, pt2.y) | |
ctx.stroke() | |
}) | |
particleSystem.eachNode(function(node, pt){ | |
// node: {mass:#, p:{x,y}, name:"", data:{}} | |
// pt: {x:#, y:#} node position in screen coords | |
// determine the box size and round off the coords if we'll be | |
// drawing a text label (awful alignment jitter otherwise...) | |
var w = ctx.measureText(node.name||"").width + 6 | |
var label = node.name | |
if (!(label||"").match(/^[ \t]*$/)){ | |
pt.x = Math.floor(pt.x) | |
pt.y = Math.floor(pt.y) | |
}else{ | |
label = null | |
} | |
// clear any edges below the text label | |
// ctx.fillStyle = 'rgba(255,255,255,.6)' | |
// ctx.fillRect(pt.x-w/2, pt.y-7, w,14) | |
ctx.clearRect(pt.x-w/2, pt.y-7, w,14) | |
// draw the text | |
if (label){ | |
ctx.font = "bold 11px Arial" | |
ctx.textAlign = "center" | |
// if (node.data.region) ctx.fillStyle = palette[node.data.region] | |
// else ctx.fillStyle = "#888888" | |
ctx.fillStyle = "#888888" | |
// ctx.fillText(label||"", pt.x, pt.y+4) | |
ctx.fillText(label||"", pt.x, pt.y+4) | |
} | |
}) | |
}, | |
initMouseHandling:function(){ | |
// no-nonsense drag and drop (thanks springy.js) | |
var dragged = null; | |
// set up a handler object that will initially listen for mousedowns then | |
// for moves and mouseups while dragging | |
var handler = { | |
clicked:function(e){ | |
var pos = $(canvas).offset(); | |
_mouseP = arbor.Point(e.pageX-pos.left, e.pageY-pos.top) | |
dragged = particleSystem.nearest(_mouseP); | |
if (dragged && dragged.node !== null){ | |
// while we're dragging, don't let physics move the node | |
dragged.node.fixed = true | |
} | |
$(canvas).bind('mousemove', handler.dragged) | |
$(window).bind('mouseup', handler.dropped) | |
return false | |
}, | |
dragged:function(e){ | |
var pos = $(canvas).offset(); | |
var s = arbor.Point(e.pageX-pos.left, e.pageY-pos.top) | |
if (dragged && dragged.node !== null){ | |
var p = particleSystem.fromScreen(s) | |
dragged.node.p = p | |
} | |
return false | |
}, | |
dropped:function(e){ | |
if (dragged===null || dragged.node===undefined) return | |
if (dragged.node !== null) dragged.node.fixed = false | |
dragged.node.tempMass = 1000 | |
dragged = null | |
$(canvas).unbind('mousemove', handler.dragged) | |
$(window).unbind('mouseup', handler.dropped) | |
_mouseP = null | |
return false | |
} | |
} | |
// start listening | |
$(canvas).mousedown(handler.clicked); | |
}, | |
} | |
return that | |
} | |
$(document).ready(function(){ | |
var sys = arbor.ParticleSystem( { repelsion: 1, stiffness: 6000, friction: 50 } ) // create the system with sensible repulsion/stiffness/friction | |
sys.parameters({gravity:true}) // use center-gravity to make the graph settle nicely (ymmv) | |
sys.renderer = Renderer("#viewport") // our newly created renderer will have its .init() method called shortly by sys... | |
// add some nodes to the graph and watch it go... | |
associatedWith = { } | |
correspondedWith = { } | |
indicesUrl = 'http://archive1.village.virginia.edu:8080/rex/snac/indices/name-idx?key=identity&value=' | |
// identity = encodeURIComponent("Sierra Club.") | |
identity = "Eisenhower, Dwight D. (Dwight David), 1890-1969." | |
// look up node id | |
$.getJSON( indicesUrl + encodeURIComponent(identity) , function(data) { | |
nodeId = data.results[0]._id | |
edges = 'http://archive1.village.virginia.edu:8080/rex/snac/vertices/' + nodeId + '/inE' | |
// nested inside for scope... do a second request to grab the edges | |
$.getJSON(edges, function(data) { | |
arr = data.results // loop through rexster results array | |
for(var i=0,len=arr.length; value=arr[i], i<len; i++) { | |
sys.addEdge(value.from_name, value.to_name, { arcrole: value._label }); | |
} | |
}); | |
}) | |
}) | |
})(this.jQuery) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment