summaryrefslogtreecommitdiff
path: root/main.js
diff options
context:
space:
mode:
authoremkael <emkael@tlen.pl>2015-02-19 10:46:55 +0100
committeremkael <emkael@tlen.pl>2015-02-19 10:46:55 +0100
commit407d07723df7d2e472d0928f79227ed4cb5dc218 (patch)
tree400c7208e933bebe90ae37bb75ba529c72fa8786 /main.js
* initial commit
Diffstat (limited to 'main.js')
-rw-r--r--main.js252
1 files changed, 252 insertions, 0 deletions
diff --git a/main.js b/main.js
new file mode 100644
index 0000000..bc488f4
--- /dev/null
+++ b/main.js
@@ -0,0 +1,252 @@
+//
+// 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(50) // 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)
+
+ // JESTEM BOGIEM PRZEKSZTAŁCEŃ 2D :O
+ var drawArrow = function(pt1, pt2, length, style) {
+ var angle = Math.atan2(pt2.y - pt1.y, pt2.x - pt1.x);
+ ctx.fillStyle = style;
+ ctx.setLineDash([]);
+ ctx.lineWidth = 1;
+ ctx.beginPath();
+ ctx.moveTo(pt2.x, pt2.y);
+ ctx.lineTo(pt2.x - length * Math.cos(angle - Math.PI/6), pt2.y - length * Math.sin(angle - Math.PI/6));
+ ctx.lineTo(pt2.x - length * (Math.cos(angle + Math.PI/6) + Math.cos(angle - Math.PI/6))/3,
+ pt2.y - length * (Math.sin(angle - Math.PI/6) + Math.sin(angle + Math.PI/6))/3);
+ ctx.lineTo(pt2.x - length * Math.cos(angle + Math.PI/6), pt2.y - length * Math.sin(angle + Math.PI/6));
+ ctx.lineTo(pt2.x, pt2.y);
+ ctx.stroke();
+ ctx.fill();
+ }
+
+ 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
+
+ ctx.strokeStyle = edge.data.style || "rgba(0,0,0, .333)"
+ ctx.lineWidth = edge.data.width || 1
+ ctx.setLineDash(edge.data.dash || [])
+
+ // draw a line from pt1 to pt2
+ ctx.beginPath()
+ ctx.moveTo(pt1.x, pt1.y)
+
+ if (edge.data.arrow) {
+ if (edge.target.data.imageObject) {
+ var destination = {};
+ var intersectingSegment = undefined;
+ if (pt1.x != pt2.x) {
+ var lineSlope = (pt1.y - pt2.y) / (pt1.x - pt2.x);
+ var width = edge.target.data.imageObject.width;
+ var height = edge.target.data.imageObject.height;
+ if ((-height / 2 <= lineSlope * width / 2)
+ && (lineSlope * width / 2 <= height / 2)) {
+ if (pt1.x > pt2.x) {
+ intersectingSegment = [
+ { x: pt2.x + width / 2,
+ y: pt2.y - height / 2 },
+ { x: pt2.x + width / 2,
+ y: pt2.y + height / 2 }
+ ];
+ }
+ else {
+ intersectingSegment = [
+ { x: pt2.x - width / 2,
+ y: pt2.y - height / 2 },
+ { x: pt2.x - width / 2,
+ y: pt2.y + height / 2 }
+ ];
+ }
+ }
+ if ((-width / 2 <= (height / 2) / lineSlope)
+ && ((height / 2) / lineSlope <= width / 2)) {
+ if (pt1.y > pt2.y) {
+ intersectingSegment = [
+ { x: pt2.x - width / 2,
+ y: pt2.y + height / 2 },
+ { x: pt2.x + width / 2,
+ y: pt2.y + height / 2 }
+ ];
+ }
+ else {
+ intersectingSegment = [
+ { x: pt2.x - width / 2,
+ y: pt2.y - height / 2 },
+ { x: pt2.x + width / 2,
+ y: pt2.y - height / 2 }
+ ];
+ }
+ }
+ }
+ else {
+ intersectingSegment = (pt1.y > pt2.y) ? [
+ { x: pt2.x - width / 2,
+ y: pt2.y - height / 2 },
+ { x: pt2.x + width / 2,
+ y: pt2.y - height / 2 }
+ ] : [
+ { x: pt2.x - width / 2,
+ y: pt2.y + height / 2 },
+ { x: pt2.x + width / 2,
+ y: pt2.y + height / 2 }
+ ];
+ }
+ if (intersectingSegment) {
+ var intersectAngle = ((intersectingSegment[1].y - intersectingSegment[0].y) * (pt2.x - pt1.x))
+ - ((intersectingSegment[1].x - intersectingSegment[0].x) * (pt2.y - pt1.y));
+ var aSlope = pt1.y - intersectingSegment[0].y;
+ var bSlope = pt1.x - intersectingSegment[0].x;
+ var numerator1 = ((intersectingSegment[1].x - intersectingSegment[0].x) * aSlope)
+ - ((intersectingSegment[1].y - intersectingSegment[0].y) * bSlope);
+ var intersectSlope = numerator1 / intersectAngle;
+ destination = { x: pt1.x + (intersectSlope * (pt2.x - pt1.x)),
+ y: pt1.y + (intersectSlope * (pt2.y - pt1.y)) };
+ }
+ }
+ }
+
+ if (destination) {
+ pt2 = destination;
+ }
+ ctx.lineTo(pt2.x, pt2.y);
+ ctx.stroke();
+ if (edge.data.arrow) {
+ drawArrow(pt1, pt2, edge.data.arrow, ctx.strokeStyle);
+ }
+ })
+
+ var drawImage = function(image, coords) {
+ ctx.drawImage(image,
+ coords.x - image.width / 2,
+ coords.y - image.height / 2);
+ };
+
+
+ particleSystem.eachNode(function(node, pt){
+ // node: {mass:#, p:{x,y}, name:"", data:{}}
+ // pt: {x:#, y:#} node position in screen coords
+
+
+ if (node.data.imageObject) {
+ drawImage(node.data.imageObject, pt);
+ }
+ else {
+ var img = new Image();
+ img.onload = function() {
+ node.data.imageObject = img;
+ drawImage(node.data.imageObject, pt);
+ };
+ img.src = '_img/' + node.data.image;
+ }
+ })
+ },
+
+ 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(500, 2000, 0.7); // 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...
+
+ $.getJSON('graph.json', function(graph) {
+ sys.graft(graph);
+ });
+ })
+
+})(this.jQuery)