Pastebin is 300% more awesome when you are logged in. Sign Up, it's FREE!
Guest

Untitled

By: a guest on Mar 22nd, 2012  |  syntax: JavaScript  |  size: 7.69 KB  |  hits: 1,106  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. (function(){
  2.  
  3.   Renderer = function(canvas){
  4.     var canvas = $(canvas).get(0)
  5.     var ctx = canvas.getContext("2d");
  6.     var gfx = arbor.Graphics(canvas)
  7.     var particleSystem = null
  8.     var imagepath = './graphics/';
  9.  
  10.     var that = {
  11.       init:function(system){
  12.         particleSystem = system
  13.         particleSystem.screenSize(canvas.width, canvas.height)
  14.         particleSystem.screenPadding(40)
  15.  
  16.         that.initMouseHandling()
  17.        
  18.       },
  19.  
  20.       redraw:function(){
  21.         if (!particleSystem) return
  22.  
  23.         gfx.clear() // convenience ƒ: clears the whole canvas rect
  24.  
  25.         // draw the nodes & save their bounds for edge drawing
  26.         var nodeBoxes = {}
  27.         particleSystem.eachNode(function(node, pt){
  28.           // node: {mass:#, p:{x,y}, name:"", data:{}}
  29.           // pt:   {x:#, y:#}  node position in screen coords
  30.          
  31.           // Load extra info
  32.           var image = node.data.image
  33.           var imageH = node.data.image_h
  34.           var imageW = node.data.image_w
  35.           var radius = parseInt(node.data.radius)
  36.  
  37.           // determine the box size and round off the coords if we'll be
  38.           // drawing a text label (awful alignment jitter otherwise...)
  39.           var label = node.data.label||""
  40.           var w = ctx.measureText(""+label).width + 10
  41.           if(w < radius) {
  42.             w = radius;
  43.           }
  44.           if (!(""+label).match(/^[ \t]*$/)){
  45.             pt.x = Math.floor(pt.x)
  46.             pt.y = Math.floor(pt.y)
  47.           }else{
  48.             label = null
  49.           }
  50.  
  51.           // draw a rectangle centered at pt
  52.           if (node.data.color) ctx.fillStyle = node.data.color
  53.           else ctx.fillStyle = "rgba(0,0,0,.2)"
  54.           if (node.data.color=='none') ctx.fillStyle = "white"
  55.  
  56.           if (node.data.shape=='dot'){
  57.             gfx.oval(pt.x-w/2, pt.y-w/2, w,w, {fill:ctx.fillStyle})
  58.             nodeBoxes[node.name] = [pt.x-w/2, pt.y-w/2, w,w]
  59.           }else{
  60.             gfx.rect(pt.x-w/2, pt.y-10, w,20, 4, {fill:ctx.fillStyle})
  61.             nodeBoxes[node.name] = [pt.x-w/2, pt.y-11, w, 22]
  62.           }
  63.  
  64.           // draw the text
  65.           if (label){
  66.             ctx.font = "12px Helvetica"
  67.             ctx.textAlign = "center"
  68.             ctx.fillStyle = "white"
  69.             if (node.data.color=='none') ctx.fillStyle = '#333333'
  70.             ctx.fillText(label||"", pt.x, pt.y+4)
  71.             ctx.fillText(label||"", pt.x, pt.y+4)
  72.           }
  73.          
  74.           if (image){
  75.             // Custom image loading function
  76.             var pic = new Image()
  77.             pic.onload = function() {
  78.               ctx.drawImage(pic, pt.x-(imageW/2), pt.y+(imageH/2), imageW, imageH)
  79.             }
  80.             pic.src = imagepath + node.data.image
  81.           }
  82.         })                     
  83.  
  84.  
  85.         // draw the edges
  86.         particleSystem.eachEdge(function(edge, pt1, pt2){
  87.           // edge: {source:Node, target:Node, length:#, data:{}}
  88.           // pt1:  {x:#, y:#}  source position in screen coords
  89.           // pt2:  {x:#, y:#}  target position in screen coords
  90.  
  91.           var weight = edge.data.weight
  92.           var color = edge.data.color
  93.  
  94.           if (!color || (""+color).match(/^[ \t]*$/)) color = null
  95.  
  96.           // find the start point
  97.           var tail = intersect_line_box(pt1, pt2, nodeBoxes[edge.source.name])
  98.           var head = intersect_line_box(tail, pt2, nodeBoxes[edge.target.name])
  99.  
  100.           ctx.save()
  101.             ctx.beginPath()
  102.             ctx.lineWidth = (!isNaN(weight)) ? parseFloat(weight) : 1
  103.             ctx.strokeStyle = (color) ? color : "#cccccc"
  104.             ctx.fillStyle = null
  105.  
  106.             ctx.moveTo(tail.x, tail.y)
  107.             ctx.lineTo(head.x, head.y)
  108.             ctx.stroke()
  109.           ctx.restore()
  110.  
  111.           // draw an arrowhead if this is a -> style edge
  112.           if (edge.data.directed){
  113.             ctx.save()
  114.               // move to the head position of the edge we just drew
  115.               var wt = !isNaN(weight) ? parseFloat(weight) : 1
  116.               var arrowLength = 6 + wt
  117.               var arrowWidth = 2 + wt
  118.               ctx.fillStyle = (color) ? color : "#cccccc"
  119.               ctx.translate(head.x, head.y);
  120.               ctx.rotate(Math.atan2(head.y - tail.y, head.x - tail.x));
  121.  
  122.               // delete some of the edge that's already there (so the point isn't hidden)
  123.               ctx.clearRect(-arrowLength/2,-wt/2, arrowLength/2,wt)
  124.  
  125.               // draw the chevron
  126.               ctx.beginPath();
  127.               ctx.moveTo(-arrowLength, arrowWidth);
  128.               ctx.lineTo(0, 0);
  129.               ctx.lineTo(-arrowLength, -arrowWidth);
  130.               ctx.lineTo(-arrowLength * 0.8, -0);
  131.               ctx.closePath();
  132.               ctx.fill();
  133.             ctx.restore()
  134.           }
  135.         })
  136.  
  137.  
  138.  
  139.       },
  140.       initMouseHandling:function(){
  141.         // no-nonsense drag and drop (thanks springy.js)
  142.         selected = null;
  143.         nearest = null;
  144.         var dragged = null;
  145.         var oldmass = 1
  146.  
  147.         // set up a handler object that will initially listen for mousedowns then
  148.         // for moves and mouseups while dragging
  149.         var handler = {
  150.           clicked:function(e){
  151.             var pos = $(canvas).offset();
  152.             _mouseP = arbor.Point(e.pageX-pos.left, e.pageY-pos.top)
  153.             selected = nearest = dragged = particleSystem.nearest(_mouseP);
  154.  
  155.             if (dragged.node !== null) dragged.node.fixed = true
  156.  
  157.             $(canvas).bind('mousemove', handler.dragged)
  158.             $(window).bind('mouseup', handler.dropped)
  159.  
  160.             return false
  161.           },
  162.           dragged:function(e){
  163.             var old_nearest = nearest && nearest.node._id
  164.             var pos = $(canvas).offset();
  165.             var s = arbor.Point(e.pageX-pos.left, e.pageY-pos.top)
  166.  
  167.             if (!nearest) return
  168.             if (dragged !== null && dragged.node !== null){
  169.               var p = particleSystem.fromScreen(s)
  170.               dragged.node.p = p
  171.             }
  172.  
  173.             return false
  174.           },
  175.  
  176.           dropped:function(e){
  177.             if (dragged===null || dragged.node===undefined) return
  178.             if (dragged.node !== null) dragged.node.fixed = false
  179.             dragged.node.tempMass = 1000
  180.             dragged = null
  181.             selected = null
  182.             $(canvas).unbind('mousemove', handler.dragged)
  183.             $(window).unbind('mouseup', handler.dropped)
  184.             _mouseP = null
  185.             return false
  186.           }
  187.         }
  188.         $(canvas).mousedown(handler.clicked);
  189.  
  190.       }
  191.  
  192.     }
  193.  
  194.     // helpers for figuring out where to draw arrows (thanks springy.js)
  195.     var intersect_line_line = function(p1, p2, p3, p4)
  196.     {
  197.       var denom = ((p4.y - p3.y)*(p2.x - p1.x) - (p4.x - p3.x)*(p2.y - p1.y));
  198.       if (denom === 0) return false // lines are parallel
  199.       var ua = ((p4.x - p3.x)*(p1.y - p3.y) - (p4.y - p3.y)*(p1.x - p3.x)) / denom;
  200.       var ub = ((p2.x - p1.x)*(p1.y - p3.y) - (p2.y - p1.y)*(p1.x - p3.x)) / denom;
  201.  
  202.       if (ua < 0 || ua > 1 || ub < 0 || ub > 1)  return false
  203.       return arbor.Point(p1.x + ua * (p2.x - p1.x), p1.y + ua * (p2.y - p1.y));
  204.     }
  205.  
  206.     var intersect_line_box = function(p1, p2, boxTuple)
  207.     {
  208.       var p3 = {x:boxTuple[0], y:boxTuple[1]},
  209.           w = boxTuple[2],
  210.           h = boxTuple[3]
  211.  
  212.       var tl = {x: p3.x, y: p3.y};
  213.       var tr = {x: p3.x + w, y: p3.y};
  214.       var bl = {x: p3.x, y: p3.y + h};
  215.       var br = {x: p3.x + w, y: p3.y + h};
  216.  
  217.       return intersect_line_line(p1, p2, tl, tr) ||
  218.             intersect_line_line(p1, p2, tr, br) ||
  219.             intersect_line_line(p1, p2, br, bl) ||
  220.             intersect_line_line(p1, p2, bl, tl) ||
  221.             false
  222.     }
  223.  
  224.     return that
  225.   }    
  226.  
  227. })()