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

124 regels
2.6 KiB

  1. var renderer = {
  2. canvas: null,
  3. ctx: null,
  4. screen: {
  5. w: 0,
  6. h: 0
  7. },
  8. pos: {
  9. x: 0,
  10. y: 0
  11. },
  12. dirty: false,
  13. init: function () {
  14. this.canvas = $('canvas')[0];
  15. this.screen.w = this.canvas.width = $('body').width();
  16. this.screen.h = this.canvas.height = $('body').height();
  17. this.ctx = this.canvas.getContext('2d');
  18. $(this.canvas)
  19. .on('mousedown', this.events.onClick.bind(this))
  20. .on('contextmenu', function () {
  21. return false;
  22. });
  23. this.update();
  24. },
  25. center: function (node) {
  26. this.pos.x = node.pos.x + (constants.blockSize / 2) - (this.screen.w / 2);
  27. this.pos.y = node.pos.y + (constants.blockSize / 2) - (this.screen.h / 2);
  28. this.ctx.translate(-this.pos.x, -this.pos.y);
  29. this.makeDirty();
  30. },
  31. makeDirty: function () {
  32. this.dirty = true;
  33. },
  34. render: function (nodes) {
  35. var nodes = nodes || generator.nodes;
  36. nodes.forEach(function (n) {
  37. var x = n.pos.x;
  38. var y = n.pos.y;
  39. if (n.parent) {
  40. var childIndex = n.parent.children.findIndex(c => (c == n));
  41. n.pos.x = x = n.parent.pos.x + (Math.cos(n.angle * childIndex) * n.distance);
  42. n.pos.y = y = n.parent.pos.y + (Math.sin(n.angle * childIndex) * n.distance);
  43. }
  44. if (n.children.length > 0)
  45. this.render(n.children);
  46. n.children.forEach(function (c) {
  47. this.renderers.line.call(this, n, c);
  48. }, this);
  49. }, this);
  50. nodes.forEach(function (n) {
  51. if (n.children.length > 0)
  52. this.render(n.children);
  53. this.renderers.node.call(this, n, n.pos.x, n.pos.y);
  54. }, this);
  55. },
  56. update: function () {
  57. if (this.dirty) {
  58. this.dirty = false;
  59. this.renderers.clear.call(this);
  60. this.render();
  61. }
  62. window.requestAnimationFrame(this.update.bind(this));
  63. },
  64. renderers: {
  65. clear: function () {
  66. this.ctx.clearRect(this.pos.x, this.pos.y, this.screen.w, this.screen.h);
  67. },
  68. node: function (node, x, y) {
  69. this.ctx.fillStyle = '#c0c3cf';
  70. this.ctx.fillRect(x, y, constants.blockSize, constants.blockSize)
  71. },
  72. line: function (fromNode, toNode) {
  73. var ctx = this.ctx;
  74. var halfSize = constants.blockSize / 2;
  75. ctx.strokeStyle = '#69696e';
  76. ctx.beginPath();
  77. ctx.moveTo(~~(fromNode.pos.x + halfSize) + 0.5, ~~(fromNode.pos.y + halfSize) + 0.5);
  78. ctx.lineTo(~~(toNode.pos.x + halfSize) + 0.5, ~~(toNode.pos.y + halfSize) + 0.5);
  79. ctx.closePath();
  80. ctx.stroke();
  81. }
  82. },
  83. events: {
  84. onClick: function (e) {
  85. generator.onClick(e.button, e.clientX + this.pos.x, e.clientY + this.pos.y);
  86. e.preventDefault();
  87. return false;
  88. }
  89. }
  90. };
  91. var constants = {
  92. lineWidth: 5,
  93. blockSize: 40,
  94. defaultDistance: 100,
  95. defaultDistanceInc: 50,
  96. defaultAngle: Math.PI / 2,
  97. defaultAngleInc: Math.PI / 8
  98. };