vcanvas-canvas.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. VCanvas_canvas = createClass(VCanvas_base, {
  2. init: function (width, height, target, interact) {
  3. VCanvas_canvas._super.init.call(this, width, height, target);
  4. this.canvas = document.createElement('canvas');
  5. if (target[0]) {
  6. target = target[0];
  7. }
  8. $.data(target, '_jqs_vcanvas', this);
  9. $(this.canvas).css({ display: 'inline-block', width: width, height: height, verticalAlign: 'top' });
  10. this._insert(this.canvas, target);
  11. this._calculatePixelDims(width, height, this.canvas);
  12. this.canvas.width = this.pixelWidth;
  13. this.canvas.height = this.pixelHeight;
  14. this.interact = interact;
  15. this.shapes = {};
  16. this.shapeseq = [];
  17. this.currentTargetShapeId = undefined;
  18. $(this.canvas).css({width: this.pixelWidth, height: this.pixelHeight});
  19. },
  20. _getContext: function (lineColor, fillColor, lineWidth) {
  21. var context = this.canvas.getContext('2d');
  22. if (lineColor !== undefined) {
  23. context.strokeStyle = lineColor;
  24. }
  25. context.lineWidth = lineWidth === undefined ? 1 : lineWidth;
  26. if (fillColor !== undefined) {
  27. context.fillStyle = fillColor;
  28. }
  29. return context;
  30. },
  31. reset: function () {
  32. var context = this._getContext();
  33. context.clearRect(0, 0, this.pixelWidth, this.pixelHeight);
  34. this.shapes = {};
  35. this.shapeseq = [];
  36. this.currentTargetShapeId = undefined;
  37. },
  38. _drawShape: function (shapeid, path, lineColor, fillColor, lineWidth) {
  39. var context = this._getContext(lineColor, fillColor, lineWidth),
  40. i, plen;
  41. context.beginPath();
  42. context.moveTo(path[0][0] + 0.5, path[0][1] + 0.5);
  43. for (i = 1, plen = path.length; i < plen; i++) {
  44. context.lineTo(path[i][0] + 0.5, path[i][1] + 0.5); // the 0.5 offset gives us crisp pixel-width lines
  45. }
  46. if (lineColor !== undefined) {
  47. context.stroke();
  48. }
  49. if (fillColor !== undefined) {
  50. context.fill();
  51. }
  52. if (this.targetX !== undefined && this.targetY !== undefined &&
  53. context.isPointInPath(this.targetX, this.targetY)) {
  54. this.currentTargetShapeId = shapeid;
  55. }
  56. },
  57. _drawCircle: function (shapeid, x, y, radius, lineColor, fillColor, lineWidth) {
  58. var context = this._getContext(lineColor, fillColor, lineWidth);
  59. context.beginPath();
  60. context.arc(x, y, radius, 0, 2 * Math.PI, false);
  61. if (this.targetX !== undefined && this.targetY !== undefined &&
  62. context.isPointInPath(this.targetX, this.targetY)) {
  63. this.currentTargetShapeId = shapeid;
  64. }
  65. if (lineColor !== undefined) {
  66. context.stroke();
  67. }
  68. if (fillColor !== undefined) {
  69. context.fill();
  70. }
  71. },
  72. _drawPieSlice: function (shapeid, x, y, radius, startAngle, endAngle, lineColor, fillColor) {
  73. var context = this._getContext(lineColor, fillColor);
  74. context.beginPath();
  75. context.moveTo(x, y);
  76. context.arc(x, y, radius, startAngle, endAngle, false);
  77. context.lineTo(x, y);
  78. context.closePath();
  79. if (lineColor !== undefined) {
  80. context.stroke();
  81. }
  82. if (fillColor) {
  83. context.fill();
  84. }
  85. if (this.targetX !== undefined && this.targetY !== undefined &&
  86. context.isPointInPath(this.targetX, this.targetY)) {
  87. this.currentTargetShapeId = shapeid;
  88. }
  89. },
  90. _drawRect: function (shapeid, x, y, width, height, lineColor, fillColor) {
  91. return this._drawShape(shapeid, [[x, y], [x + width, y], [x + width, y + height], [x, y + height], [x, y]], lineColor, fillColor);
  92. },
  93. appendShape: function (shape) {
  94. this.shapes[shape.id] = shape;
  95. this.shapeseq.push(shape.id);
  96. this.lastShapeId = shape.id;
  97. return shape.id;
  98. },
  99. replaceWithShape: function (shapeid, shape) {
  100. var shapeseq = this.shapeseq,
  101. i;
  102. this.shapes[shape.id] = shape;
  103. for (i = shapeseq.length; i--;) {
  104. if (shapeseq[i] == shapeid) {
  105. shapeseq[i] = shape.id;
  106. }
  107. }
  108. delete this.shapes[shapeid];
  109. },
  110. replaceWithShapes: function (shapeids, shapes) {
  111. var shapeseq = this.shapeseq,
  112. shapemap = {},
  113. sid, i, first;
  114. for (i = shapeids.length; i--;) {
  115. shapemap[shapeids[i]] = true;
  116. }
  117. for (i = shapeseq.length; i--;) {
  118. sid = shapeseq[i];
  119. if (shapemap[sid]) {
  120. shapeseq.splice(i, 1);
  121. delete this.shapes[sid];
  122. first = i;
  123. }
  124. }
  125. for (i = shapes.length; i--;) {
  126. shapeseq.splice(first, 0, shapes[i].id);
  127. this.shapes[shapes[i].id] = shapes[i];
  128. }
  129. },
  130. insertAfterShape: function (shapeid, shape) {
  131. var shapeseq = this.shapeseq,
  132. i;
  133. for (i = shapeseq.length; i--;) {
  134. if (shapeseq[i] === shapeid) {
  135. shapeseq.splice(i + 1, 0, shape.id);
  136. this.shapes[shape.id] = shape;
  137. return;
  138. }
  139. }
  140. },
  141. removeShapeId: function (shapeid) {
  142. var shapeseq = this.shapeseq,
  143. i;
  144. for (i = shapeseq.length; i--;) {
  145. if (shapeseq[i] === shapeid) {
  146. shapeseq.splice(i, 1);
  147. break;
  148. }
  149. }
  150. delete this.shapes[shapeid];
  151. },
  152. getShapeAt: function (el, x, y) {
  153. this.targetX = x;
  154. this.targetY = y;
  155. this.render();
  156. return this.currentTargetShapeId;
  157. },
  158. render: function () {
  159. var shapeseq = this.shapeseq,
  160. shapes = this.shapes,
  161. shapeCount = shapeseq.length,
  162. context = this._getContext(),
  163. shapeid, shape, i;
  164. context.clearRect(0, 0, this.pixelWidth, this.pixelHeight);
  165. for (i = 0; i < shapeCount; i++) {
  166. shapeid = shapeseq[i];
  167. shape = shapes[shapeid];
  168. this['_draw' + shape.type].apply(this, shape.args);
  169. }
  170. if (!this.interact) {
  171. // not interactive so no need to keep the shapes array
  172. this.shapes = {};
  173. this.shapeseq = [];
  174. }
  175. }
  176. });