CCDrawingPrimitivesCanvas.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /****************************************************************************
  2. Copyright (c) 2008-2010 Ricardo Quesada
  3. Copyright (c) 2011-2012 cocos2d-x.org
  4. Copyright (c) 2013-2014 Chukong Technologies Inc.
  5. http://www.cocos2d-x.org
  6. Permission is hereby granted, free of charge, to any person obtaining a copy
  7. of this software and associated documentation files (the "Software"), to deal
  8. in the Software without restriction, including without limitation the rights
  9. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the Software is
  11. furnished to do so, subject to the following conditions:
  12. The above copyright notice and this permission notice shall be included in
  13. all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. THE SOFTWARE.
  21. ****************************************************************************/
  22. /**
  23. * @const
  24. * @type {number}
  25. */
  26. cc.PI2 = Math.PI * 2;
  27. /**
  28. * Canvas of DrawingPrimitive implement version use for canvasMode
  29. * @class
  30. * @extends cc.Class
  31. * @param {CanvasRenderingContext2D} renderContext
  32. */
  33. cc.DrawingPrimitiveCanvas = cc.Class.extend(/** @lends cc.DrawingPrimitiveCanvas# */{
  34. _cacheArray:[],
  35. _renderContext:null,
  36. /**
  37. * Constructor of cc.DrawingPrimitiveCanvas
  38. * @param {CanvasRenderingContext2D} renderContext
  39. */
  40. ctor:function (renderContext) {
  41. this._renderContext = renderContext;
  42. },
  43. /**
  44. * draws a point given x and y coordinate measured in points
  45. * @override
  46. * @param {cc.Point} point
  47. * @param {Number} size
  48. */
  49. drawPoint:function (point, size) {
  50. if (!size) {
  51. size = 1;
  52. }
  53. var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
  54. var newPoint = cc.p(point.x * locScaleX, point.y * locScaleY);
  55. this._renderContext.beginPath();
  56. this._renderContext.arc(newPoint.x, -newPoint.y, size * locScaleX, 0, Math.PI * 2, false);
  57. this._renderContext.closePath();
  58. this._renderContext.fill();
  59. },
  60. /**
  61. * draws an array of points.
  62. * @override
  63. * @param {Array} points point of array
  64. * @param {Number} numberOfPoints
  65. * @param {Number} size
  66. */
  67. drawPoints:function (points, numberOfPoints, size) {
  68. if (points == null) {
  69. return;
  70. }
  71. if (!size) {
  72. size = 1;
  73. }
  74. var locContext = this._renderContext,locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
  75. locContext.beginPath();
  76. for (var i = 0, len = points.length; i < len; i++)
  77. locContext.arc(points[i].x * locScaleX, -points[i].y * locScaleY, size * locScaleX, 0, Math.PI * 2, false);
  78. locContext.closePath();
  79. locContext.fill();
  80. },
  81. /**
  82. * draws a line given the origin and destination point measured in points
  83. * @override
  84. * @param {cc.Point} origin
  85. * @param {cc.Point} destination
  86. */
  87. drawLine:function (origin, destination) {
  88. var locContext = this._renderContext, locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
  89. locContext.beginPath();
  90. locContext.moveTo(origin.x * locScaleX, -origin.y * locScaleY);
  91. locContext.lineTo(destination.x * locScaleX, -destination.y * locScaleY);
  92. locContext.closePath();
  93. locContext.stroke();
  94. },
  95. /**
  96. * draws a rectangle given the origin and destination point measured in points.
  97. * @param {cc.Point} origin
  98. * @param {cc.Point} destination
  99. */
  100. drawRect:function (origin, destination) {
  101. this.drawLine(cc.p(origin.x, origin.y), cc.p(destination.x, origin.y));
  102. this.drawLine(cc.p(destination.x, origin.y), cc.p(destination.x, destination.y));
  103. this.drawLine(cc.p(destination.x, destination.y), cc.p(origin.x, destination.y));
  104. this.drawLine(cc.p(origin.x, destination.y), cc.p(origin.x, origin.y));
  105. },
  106. /**
  107. * draws a solid rectangle given the origin and destination point measured in points.
  108. * @param {cc.Point} origin
  109. * @param {cc.Point} destination
  110. * @param {cc.Color} color
  111. */
  112. drawSolidRect:function (origin, destination, color) {
  113. var vertices = [
  114. origin,
  115. cc.p(destination.x, origin.y),
  116. destination,
  117. cc.p(origin.x, destination.y)
  118. ];
  119. this.drawSolidPoly(vertices, 4, color);
  120. },
  121. /**
  122. * draws a polygon given a pointer to cc.Point coordinates and the number of vertices measured in points.
  123. * @override
  124. * @param {Array} vertices a pointer to cc.Point coordinates
  125. * @param {Number} numOfVertices the number of vertices measured in points
  126. * @param {Boolean} closePolygon The polygon can be closed or open
  127. * @param {Boolean} [fill=] The polygon can be closed or open and optionally filled with current color
  128. */
  129. drawPoly:function (vertices, numOfVertices, closePolygon, fill) {
  130. fill = fill || false;
  131. if (vertices == null)
  132. return;
  133. if (vertices.length < 3)
  134. throw new Error("Polygon's point must greater than 2");
  135. var firstPoint = vertices[0], locContext = this._renderContext;
  136. var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
  137. locContext.beginPath();
  138. locContext.moveTo(firstPoint.x * locScaleX, -firstPoint.y * locScaleY);
  139. for (var i = 1, len = vertices.length; i < len; i++)
  140. locContext.lineTo(vertices[i].x * locScaleX, -vertices[i].y * locScaleY);
  141. if (closePolygon)
  142. locContext.closePath();
  143. if (fill)
  144. locContext.fill();
  145. else
  146. locContext.stroke();
  147. },
  148. /**
  149. * draws a solid polygon given a pointer to CGPoint coordinates, the number of vertices measured in points, and a color.
  150. * @param {Array} polygons
  151. * @param {Number} numberOfPoints
  152. * @param {cc.Color} color
  153. */
  154. drawSolidPoly:function (polygons, numberOfPoints, color) {
  155. this.setDrawColor(color.r, color.g, color.b, color.a);
  156. this.drawPoly(polygons, numberOfPoints, true, true);
  157. },
  158. /**
  159. * draws a circle given the center, radius and number of segments.
  160. * @override
  161. * @param {cc.Point} center center of circle
  162. * @param {Number} radius
  163. * @param {Number} angle angle in radians
  164. * @param {Number} segments
  165. * @param {Boolean} [drawLineToCenter=]
  166. */
  167. drawCircle: function (center, radius, angle, segments, drawLineToCenter) {
  168. drawLineToCenter = drawLineToCenter || false;
  169. var locContext = this._renderContext;
  170. var locScaleX = cc.view.getScaleX(), locScaleY = cc.view.getScaleY();
  171. locContext.beginPath();
  172. var endAngle = angle - Math.PI * 2;
  173. locContext.arc(0 | (center.x * locScaleX), 0 | -(center.y * locScaleY), radius * locScaleX, -angle, -endAngle, false);
  174. if (drawLineToCenter) {
  175. locContext.lineTo(0 | (center.x * locScaleX), 0 | -(center.y * locScaleY));
  176. }
  177. locContext.stroke();
  178. },
  179. /**
  180. * draws a quad bezier path
  181. * @override
  182. * @param {cc.Point} origin
  183. * @param {cc.Point} control
  184. * @param {cc.Point} destination
  185. * @param {Number} segments
  186. */
  187. drawQuadBezier:function (origin, control, destination, segments) {
  188. //this is OpenGL Algorithm
  189. var vertices = this._cacheArray;
  190. vertices.length =0;
  191. var t = 0.0;
  192. for (var i = 0; i < segments; i++) {
  193. var x = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x;
  194. var y = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y;
  195. vertices.push(cc.p(x, y));
  196. t += 1.0 / segments;
  197. }
  198. vertices.push(cc.p(destination.x, destination.y));
  199. this.drawPoly(vertices, segments + 1, false, false);
  200. },
  201. /**
  202. * draws a cubic bezier path
  203. * @override
  204. * @param {cc.Point} origin
  205. * @param {cc.Point} control1
  206. * @param {cc.Point} control2
  207. * @param {cc.Point} destination
  208. * @param {Number} segments
  209. */
  210. drawCubicBezier:function (origin, control1, control2, destination, segments) {
  211. //this is OpenGL Algorithm
  212. var vertices = this._cacheArray;
  213. vertices.length =0;
  214. var t = 0;
  215. for (var i = 0; i < segments; i++) {
  216. var x = Math.pow(1 - t, 3) * origin.x + 3.0 * Math.pow(1 - t, 2) * t * control1.x + 3.0 * (1 - t) * t * t * control2.x + t * t * t * destination.x;
  217. var y = Math.pow(1 - t, 3) * origin.y + 3.0 * Math.pow(1 - t, 2) * t * control1.y + 3.0 * (1 - t) * t * t * control2.y + t * t * t * destination.y;
  218. vertices.push(cc.p(x , y ));
  219. t += 1.0 / segments;
  220. }
  221. vertices.push(cc.p(destination.x , destination.y));
  222. this.drawPoly(vertices, segments + 1, false, false);
  223. },
  224. /**
  225. * draw a CatmullRom curve
  226. * @override
  227. * @param {Array} points
  228. * @param {Number} segments
  229. */
  230. drawCatmullRom:function (points, segments) {
  231. this.drawCardinalSpline(points, 0.5, segments);
  232. },
  233. /**
  234. * draw a cardinal spline path
  235. * @override
  236. * @param {Array} config
  237. * @param {Number} tension
  238. * @param {Number} segments
  239. */
  240. drawCardinalSpline:function (config, tension, segments) {
  241. //lazy_init();
  242. cc._renderContext.strokeStyle = "rgba(255,255,255,1)";
  243. var points = this._cacheArray;
  244. points.length = 0;
  245. var p, lt;
  246. var deltaT = 1.0 / config.length;
  247. for (var i = 0; i < segments + 1; i++) {
  248. var dt = i / segments;
  249. // border
  250. if (dt == 1) {
  251. p = config.length - 1;
  252. lt = 1;
  253. } else {
  254. p = 0 | (dt / deltaT);
  255. lt = (dt - deltaT * p) / deltaT;
  256. }
  257. // Interpolate
  258. var newPos = cc.CardinalSplineAt(
  259. cc.getControlPointAt(config, p - 1),
  260. cc.getControlPointAt(config, p - 0),
  261. cc.getControlPointAt(config, p + 1),
  262. cc.getControlPointAt(config, p + 2),
  263. tension, lt);
  264. points.push(newPos);
  265. }
  266. this.drawPoly(points, segments + 1, false, false);
  267. },
  268. /**
  269. * draw an image
  270. * @override
  271. * @param {HTMLImageElement|HTMLCanvasElement} image
  272. * @param {cc.Point} sourcePoint
  273. * @param {cc.Size} sourceSize
  274. * @param {cc.Point} destPoint
  275. * @param {cc.Size} destSize
  276. */
  277. drawImage:function (image, sourcePoint, sourceSize, destPoint, destSize) {
  278. var len = arguments.length;
  279. switch (len) {
  280. case 2:
  281. var height = image.height;
  282. this._renderContext.drawImage(image, sourcePoint.x, -(sourcePoint.y + height));
  283. break;
  284. case 3:
  285. this._renderContext.drawImage(image, sourcePoint.x, -(sourcePoint.y + sourceSize.height), sourceSize.width, sourceSize.height);
  286. break;
  287. case 5:
  288. this._renderContext.drawImage(image, sourcePoint.x, sourcePoint.y, sourceSize.width, sourceSize.height, destPoint.x, -(destPoint.y + destSize.height),
  289. destSize.width, destSize.height);
  290. break;
  291. default:
  292. throw new Error("Argument must be non-nil");
  293. break;
  294. }
  295. },
  296. /**
  297. * draw a star
  298. * @param {CanvasRenderingContext2D} ctx canvas context
  299. * @param {Number} radius
  300. * @param {cc.Color} color
  301. */
  302. drawStar:function (ctx, radius, color) {
  303. var context = ctx || this._renderContext;
  304. radius *= cc.view.getScaleX();
  305. var colorStr = "rgba(" + (0 | color.r) + "," + (0 | color.g) + "," + (0 | color.b);
  306. context.fillStyle = colorStr + ",1)";
  307. var subRadius = radius / 10;
  308. context.beginPath();
  309. context.moveTo(-radius, radius);
  310. context.lineTo(0, subRadius);
  311. context.lineTo(radius, radius);
  312. context.lineTo(subRadius, 0);
  313. context.lineTo(radius, -radius);
  314. context.lineTo(0, -subRadius);
  315. context.lineTo(-radius, -radius);
  316. context.lineTo(-subRadius, 0);
  317. context.lineTo(-radius, radius);
  318. context.closePath();
  319. context.fill();
  320. var g1 = context.createRadialGradient(0, 0, subRadius, 0, 0, radius);
  321. g1.addColorStop(0, colorStr + ", 1)");
  322. g1.addColorStop(0.3, colorStr + ", 0.8)");
  323. g1.addColorStop(1.0, colorStr + ", 0.0)");
  324. context.fillStyle = g1;
  325. context.beginPath();
  326. var startAngle_1 = 0;
  327. var endAngle_1 = cc.PI2;
  328. context.arc(0, 0, radius - subRadius, startAngle_1, endAngle_1, false);
  329. context.closePath();
  330. context.fill();
  331. },
  332. /**
  333. * draw a color ball
  334. * @param {CanvasRenderingContext2D} ctx canvas context
  335. * @param {Number} radius
  336. * @param {cc.Color} color
  337. */
  338. drawColorBall:function (ctx, radius, color) {
  339. var context = ctx || this._renderContext;
  340. radius *= cc.view.getScaleX();
  341. var colorStr = "rgba(" +(0|color.r) + "," + (0|color.g) + "," + (0|color.b);
  342. var subRadius = radius / 10;
  343. var g1 = context.createRadialGradient(0, 0, subRadius, 0, 0, radius);
  344. g1.addColorStop(0, colorStr + ", 1)");
  345. g1.addColorStop(0.3, colorStr + ", 0.8)");
  346. g1.addColorStop(0.6, colorStr + ", 0.4)");
  347. g1.addColorStop(1.0, colorStr + ", 0.0)");
  348. context.fillStyle = g1;
  349. context.beginPath();
  350. var startAngle_1 = 0;
  351. var endAngle_1 = cc.PI2;
  352. context.arc(0, 0, radius, startAngle_1, endAngle_1, false);
  353. context.closePath();
  354. context.fill();
  355. },
  356. /**
  357. * fill text
  358. * @param {String} strText
  359. * @param {Number} x
  360. * @param {Number} y
  361. */
  362. fillText:function (strText, x, y) {
  363. this._renderContext.fillText(strText, x, -y);
  364. },
  365. /**
  366. * set the drawing color with 4 unsigned bytes
  367. * @param {Number} r red value (0 to 255)
  368. * @param {Number} g green value (0 to 255)
  369. * @param {Number} b blue value (0 to 255)
  370. * @param {Number} a Alpha value (0 to 255)
  371. */
  372. setDrawColor:function (r, g, b, a) {
  373. this._renderContext.fillStyle = "rgba(" + r + "," + g + "," + b + "," + a / 255 + ")";
  374. this._renderContext.strokeStyle = "rgba(" + r + "," + g + "," + b + "," + a / 255 + ")";
  375. },
  376. /**
  377. * set the point size in points. Default 1.
  378. * @param {Number} pointSize
  379. */
  380. setPointSize:function (pointSize) {
  381. },
  382. /**
  383. * set the line width. Default 1.
  384. * @param {Number} width
  385. */
  386. setLineWidth:function (width) {
  387. this._renderContext.lineWidth = width * cc.view.getScaleX();
  388. }
  389. });