shape-library.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. ;(function(undefined) {
  2. 'use strict';
  3. var shapes = [];
  4. var register = function(name,drawShape,drawBorder) {
  5. shapes.push({
  6. 'name': name,
  7. 'drawShape': drawShape,
  8. 'drawBorder': drawBorder
  9. });
  10. }
  11. var enumerateShapes = function() {
  12. return shapes;
  13. }
  14. /**
  15. * For the standard closed shapes - the shape fill and border are drawn the
  16. * same, with some minor differences for fill and border. To facilitate this we
  17. * create the generic draw functions, that take a shape drawing func and
  18. * return a shape-renderer/border-renderer
  19. * ----------
  20. */
  21. var genericDrawShape = function(shapeFunc) {
  22. return function(node,x,y,size,color,context) {
  23. context.fillStyle = color;
  24. context.beginPath();
  25. shapeFunc(node,x,y,size,context);
  26. context.closePath();
  27. context.fill();
  28. };
  29. }
  30. var genericDrawBorder = function(shapeFunc) {
  31. return function(node,x,y,size,color,context) {
  32. context.strokeStyle = color;
  33. context.lineWidth = size / 5;
  34. context.beginPath();
  35. shapeFunc(node,x,y,size,context);
  36. context.closePath();
  37. context.stroke();
  38. };
  39. }
  40. /**
  41. * We now proced to use the generics to define our standard shape/border
  42. * drawers: square, diamond, equilateral (polygon), and star
  43. * ----------
  44. */
  45. var drawSquare = function(node,x,y,size,context) {
  46. var rotate = Math.PI*45/180; // 45 deg rotation of a diamond shape
  47. context.moveTo(x+size*Math.sin(rotate), y-size*Math.cos(rotate)); // first point on outer radius, dwangle 'rotate'
  48. for(var i=1; i<4; i++) {
  49. context.lineTo(x+Math.sin(rotate+2*Math.PI*i/4)*size, y-Math.cos(rotate+2*Math.PI*i/4)*size);
  50. }
  51. }
  52. register("square",genericDrawShape(drawSquare),genericDrawBorder(drawSquare));
  53. var drawCircle = function(node,x,y,size,context) {
  54. context.arc(x,y,size,0,Math.PI*2,true);
  55. }
  56. register("circle",genericDrawShape(drawCircle),genericDrawBorder(drawCircle));
  57. var drawDiamond = function(node,x,y,size,context) {
  58. context.moveTo(x-size, y);
  59. context.lineTo(x, y-size);
  60. context.lineTo(x+size, y);
  61. context.lineTo(x, y+size);
  62. }
  63. register("diamond",genericDrawShape(drawDiamond),genericDrawBorder(drawDiamond));
  64. var drawCross = function(node,x,y,size,context) {
  65. var lineWeight = (node.cross && node.cross.lineWeight) || 5;
  66. context.moveTo(x-size, y-lineWeight);
  67. context.lineTo(x-size, y+lineWeight);
  68. context.lineTo(x-lineWeight, y+lineWeight);
  69. context.lineTo(x-lineWeight, y+size);
  70. context.lineTo(x+lineWeight, y+size);
  71. context.lineTo(x+lineWeight, y+lineWeight);
  72. context.lineTo(x+size, y+lineWeight);
  73. context.lineTo(x+size, y-lineWeight);
  74. context.lineTo(x+lineWeight, y-lineWeight);
  75. context.lineTo(x+lineWeight, y-size);
  76. context.lineTo(x-lineWeight, y-size);
  77. context.lineTo(x-lineWeight, y-lineWeight);
  78. }
  79. register("cross",genericDrawShape(drawCross),genericDrawBorder(drawCross));
  80. var drawEquilateral = function(node,x,y,size,context) {
  81. var pcount = (node.equilateral && node.equilateral.numPoints) || 5;
  82. var rotate = ((node.equilateral && node.equilateral.rotate) || 0)*Math.PI/180;
  83. var radius = size;
  84. context.moveTo(x+radius*Math.sin(rotate), y-radius*Math.cos(rotate)); // first point on outer radius, angle 'rotate'
  85. for(var i=1; i<pcount; i++) {
  86. context.lineTo(x+Math.sin(rotate+2*Math.PI*i/pcount)*radius, y-Math.cos(rotate+2*Math.PI*i/pcount)*radius);
  87. }
  88. }
  89. register("equilateral",genericDrawShape(drawEquilateral),genericDrawBorder(drawEquilateral));
  90. var starShape = function(node,x,y,size,context) {
  91. var pcount = (node.star && node.star.numPoints) || 5,
  92. inRatio = (node.star && node.star.innerRatio) || 0.5,
  93. outR = size,
  94. inR = size*inRatio,
  95. angleOffset = Math.PI/pcount;
  96. context.moveTo(x, y-size); // first point on outer radius, top
  97. for(var i=0; i<pcount; i++) {
  98. context.lineTo(x+Math.sin(angleOffset+2*Math.PI*i/pcount)*inR,
  99. y-Math.cos(angleOffset+2*Math.PI*i/pcount)*inR);
  100. context.lineTo(x+Math.sin(2*Math.PI*(i+1)/pcount)*outR,
  101. y-Math.cos(2*Math.PI*(i+1)/pcount)*outR);
  102. }
  103. }
  104. register("star",genericDrawShape(starShape),genericDrawBorder(starShape));
  105. /**
  106. * An example of a non standard shape (pacman). Here we WILL NOT use the
  107. * genericDraw functions, but rather register a full custom node renderer for
  108. * fill, and skip the border renderer which is irrelevant for this shape
  109. * ----------
  110. */
  111. var drawPacman = function(node,x,y,size,color,context) {
  112. context.fillStyle = 'yellow';
  113. context.beginPath();
  114. context.arc(x,y,size,1.25*Math.PI,0,false);
  115. context.arc(x,y,size,0,0.75*Math.PI,false);
  116. context.lineTo(x,y);
  117. context.closePath();
  118. context.fill();
  119. context.fillStyle = 'white';
  120. context.strokeStyle = 'black';
  121. context.beginPath();
  122. context.arc(x+size/3,y-size/3,size/4,0,2*Math.PI,false);
  123. context.closePath();
  124. context.fill();
  125. context.stroke();
  126. context.fillStyle = 'black';
  127. context.beginPath();
  128. context.arc(x+4*size/9,y-size/3,size/8,0,2*Math.PI,false);
  129. context.closePath();
  130. context.fill();
  131. }
  132. register("pacman",drawPacman,null);
  133. /**
  134. * Exporting
  135. * ----------
  136. */
  137. this.ShapeLibrary = {
  138. // Functions
  139. enumerate: enumerateShapes,
  140. // add: addShape,
  141. // Version
  142. version: '0.1'
  143. };
  144. }).call(this);