RGraph.cornergauge.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  1. /**
  2. * o------------------------------------------------------------------------------o
  3. * | This file is part of the RGraph package - you can learn more at: |
  4. * | |
  5. * | http://www.rgraph.net |
  6. * | |
  7. * | This package is licensed under the RGraph license. For all kinds of business |
  8. * | purposes there is a small one-time licensing fee to pay and for non |
  9. * | commercial purposes it is free to use. You can read the full license here: |
  10. * | |
  11. * | http://www.rgraph.net/license |
  12. * o------------------------------------------------------------------------------o
  13. */
  14. if (typeof(RGraph) == 'undefined') RGraph = {};
  15. /**
  16. * The constructor
  17. *
  18. * @param object id The canvas tag ID
  19. * @param array min The minimum value
  20. * @param array max The maximum value
  21. * @param array value The indicated value
  22. */
  23. RGraph.CornerGauge = function (id, min, max, value)
  24. {
  25. // Get the canvas and context objects
  26. this.id = id;
  27. this.canvas = document.getElementById(typeof id === 'object' ? id.id : id);
  28. this.context = this.canvas.getContext ? this.canvas.getContext("2d") : null;
  29. this.canvas.__object__ = this;
  30. this.type = 'cornergauge';
  31. this.min = min;
  32. this.max = max;
  33. this.value = value;
  34. this.angles = {};
  35. this.angles.needle = [];
  36. this.centerpin = {};
  37. this.isRGraph = true;
  38. this.currentValue = null;
  39. this.uid = RGraph.CreateUID();
  40. this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
  41. this.coordsText = [];
  42. /**
  43. * Range checking
  44. */
  45. if (typeof(this.value) == 'object') {
  46. for (var i=0; i<this.value.length; ++i) {
  47. if (this.value[i] > this.max) this.value[i] = max;
  48. if (this.value[i] < this.min) this.value[i] = min;
  49. }
  50. } else {
  51. if (this.value > this.max) this.value = max;
  52. if (this.value < this.min) this.value = min;
  53. }
  54. /**
  55. * Compatibility with older browsers
  56. */
  57. RGraph.OldBrowserCompat(this.context);
  58. // Various config type stuff
  59. this.properties =
  60. {
  61. 'chart.centerx': null,
  62. 'chart.centery': null,
  63. 'chart.radius': null,
  64. 'chart.gutter.left': 25,
  65. 'chart.gutter.right': 25,
  66. 'chart.gutter.top': 25,
  67. 'chart.gutter.bottom': 25,
  68. 'chart.strokestyle': 'black',
  69. 'chart.linewidth': 2,
  70. 'chart.title': '',
  71. 'chart.title.vpos': 0.5,
  72. 'chart.title.size': null,
  73. 'chart.title.x': null,
  74. 'chart.title.y': null,
  75. 'chart.title.bold': true,
  76. 'chart.text.font': 'Arial',
  77. 'chart.text.color': '#666',
  78. 'chart.text.size': 10,
  79. 'chart.background.gradient.color1': '#ddd',
  80. 'chart.background.gradient.color2': 'white',
  81. 'chart.shadow': true,
  82. 'chart.shadow.color': 'gray',
  83. 'chart.shadow.offsetx': 0,
  84. 'chart.shadow.offsety': 0,
  85. 'chart.shadow.blur': 15,
  86. 'chart.scale.decimals': 0,
  87. 'chart.scale.point': '.',
  88. 'chart.scale.thousand': ',',
  89. 'chart.units.pre': '',
  90. 'chart.units.post': '',
  91. 'chart.resizable': false,
  92. 'chart.chart.resize.handle.background': null,
  93. 'chart.adjustable': false,
  94. 'chart.annotatable': false,
  95. 'chart.annotate.color': 'black',
  96. 'chart.colors.ranges': null,
  97. 'chart.red.start': min + (0.9 * (this.max - min)),
  98. 'chart.green.end': min + (0.7 * (this.max - min)),
  99. 'chart.red.color': 'red',
  100. 'chart.yellow.color': 'yellow',
  101. 'chart.green.color': '#0f0',
  102. 'chart.value.text': true,
  103. 'chart.value.text.units.pre': '',
  104. 'chart.value.text.units.post': '',
  105. 'chart.value.text.boxed': true,
  106. 'chart.value.text.font': 'Arial',
  107. 'chart.value.text.size': 18,
  108. 'chart.value.text.bold': false,
  109. 'chart.value.text.decimals': 0,
  110. 'chart.centerpin.stroke': 'rgba(0,0,0,0)',
  111. 'chart.centerpin.fill': null, // Set in the DrawCenterpin function
  112. 'chart.centerpin.color': 'blue',
  113. 'chart.needle.colors': ['#ccc', '#D5604D', 'red', 'green', 'yellow'],
  114. 'chart.zoom.factor': 1.5,
  115. 'chart.zoom.fade.in': true,
  116. 'chart.zoom.fade.out': true,
  117. 'chart.zoom.hdir': 'right',
  118. 'chart.zoom.vdir': 'down',
  119. 'chart.zoom.frames': 25,
  120. 'chart.zoom.delay': 16.666,
  121. 'chart.zoom.shadow': true,
  122. 'chart.zoom.background': true
  123. }
  124. /*
  125. * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
  126. * done already
  127. */
  128. if (!this.canvas.__rgraph_aa_translated__) {
  129. this.context.translate(0.5,0.5);
  130. this.canvas.__rgraph_aa_translated__ = true;
  131. }
  132. ///////////////////////////////// SHORT PROPERTIES /////////////////////////////////
  133. var RG = RGraph;
  134. var ca = this.canvas;
  135. var co = ca.getContext('2d');
  136. var prop = this.properties;
  137. //////////////////////////////////// METHODS ///////////////////////////////////////
  138. /**
  139. * An all encompassing accessor
  140. *
  141. * @param string name The name of the property
  142. * @param mixed value The value of the property
  143. */
  144. this.Set = function (name, value)
  145. {
  146. name = name.toLowerCase();
  147. /**
  148. * This should be done first - prepend the property name with "chart." if necessary
  149. */
  150. if (name.substr(0,6) != 'chart.') {
  151. name = 'chart.' + name;
  152. }
  153. prop[name] = value;
  154. return this;
  155. }
  156. /**
  157. * An all encompassing accessor
  158. *
  159. * @param string name The name of the property
  160. */
  161. this.Get = function (name)
  162. {
  163. /**
  164. * This should be done first - prepend the property name with "chart." if necessary
  165. */
  166. if (name.substr(0,6) != 'chart.') {
  167. name = 'chart.' + name;
  168. }
  169. return prop[name];
  170. }
  171. /**
  172. * The function you call to draw the line chart
  173. */
  174. this.Draw = function ()
  175. {
  176. /**
  177. * Fire the onbeforedraw event
  178. */
  179. RG.FireCustomEvent(this, 'onbeforedraw');
  180. /**
  181. * Store the value (for animation primarily
  182. */
  183. this.currentValue = this.value;
  184. this.gutterLeft = prop['chart.gutter.left'];
  185. this.gutterRight = prop['chart.gutter.right'];
  186. this.gutterTop = prop['chart.gutter.top'];
  187. this.gutterBottom = prop['chart.gutter.bottom'];
  188. /**
  189. * Work out the radius first
  190. */
  191. this.radius = Math.min(
  192. (ca.width - this.gutterLeft - this.gutterRight),
  193. (ca.height - this.gutterTop - this.gutterBottom)
  194. );
  195. if (typeof(prop['chart.radius']) == 'number') this.radius = prop['chart.radius'];
  196. /**
  197. * Now use the radius in working out the centerX/Y
  198. */
  199. this.centerx = (ca.width / 2) - (this.radius / 2) + Math.max(30, this.radius * 0.1);
  200. this.centery = (ca.height / 2) + (this.radius / 2) - (this.radius * 0.1);
  201. if (typeof(prop['chart.centerx']) == 'number') this.centerx = prop['chart.centerx'];
  202. if (typeof(prop['chart.centery']) == 'number') this.centery = prop['chart.centery'];
  203. /**
  204. * Parse the colors for gradients. Its down here so that the center X/Y can be used
  205. */
  206. if (!this.colorsParsed) {
  207. this.parseColors();
  208. // Don't want to do this again
  209. this.colorsParsed = true;
  210. }
  211. /**
  212. * Start with the background
  213. */
  214. this.DrawBackGround();
  215. /**
  216. * Draw the tickmarks
  217. */
  218. this.DrawTickmarks();
  219. /**
  220. * Draw the color bands
  221. */
  222. this.DrawColorBands();
  223. /**
  224. * Draw the label/value in text
  225. */
  226. this.DrawLabel();
  227. /**
  228. * Start with the labels/scale
  229. */
  230. this.DrawLabels();
  231. /**
  232. * Draw the needle(s)
  233. */
  234. if (typeof(this.value) == 'object') {
  235. for (var i=0,len=this.value.length; i<len; ++i) {
  236. this.DrawNeedle(
  237. i,
  238. this.value[i],
  239. this.radius - 65
  240. );
  241. }
  242. } else {
  243. this.DrawNeedle(0, this.value, this.radius - 65);
  244. }
  245. /**
  246. * Draw the centerpin of the needle
  247. */
  248. this.DrawCenterpin();
  249. /**
  250. * Draw the title
  251. */
  252. var size = prop['chart.title.size'] ? prop['chart.title.size'] : prop['chart.text.size'] + 2
  253. prop['chart.title.y'] = this.centery + 20 - this.radius - ((1.5 * size) / 2);
  254. RGraph.DrawTitle(this,
  255. prop['chart.title'],
  256. this.guttertop,
  257. this.centerx + (this.radius / 2),
  258. size);
  259. /**
  260. * Setup the context menu if required
  261. */
  262. if (prop['chart.contextmenu']) {
  263. RGraph.ShowContext(this);
  264. }
  265. /**
  266. * This function enables resizing
  267. */
  268. if (prop['chart.resizable']) {
  269. RGraph.AllowResizing(this);
  270. }
  271. /**
  272. * This installs the event listeners
  273. */
  274. RGraph.InstallEventListeners(this);
  275. /**
  276. * Fire the RGraph ondraw event
  277. */
  278. RGraph.FireCustomEvent(this, 'ondraw');
  279. return this;
  280. }
  281. /**
  282. * Draw the background
  283. */
  284. this.DrawBackGround = function ()
  285. {
  286. if (prop['chart.shadow']) {
  287. RGraph.SetShadow(this, prop['chart.shadow.color'], prop['chart.shadow.offsetx'], prop['chart.shadow.offsety'], prop['chart.shadow.blur']);
  288. }
  289. co.strokeStyle = prop['chart.strokestyle'];
  290. co.lineWidth = prop['chart.linewidth'] ? prop['chart.linewidth'] : 0.0001;
  291. /**
  292. * Draw the corner circle first
  293. */
  294. co.beginPath();
  295. co.arc(this.centerx,this.centery,30,0,TWOPI,false);
  296. co.stroke();
  297. /**
  298. * Draw the quarter circle background
  299. */
  300. co.beginPath();
  301. co.moveTo(this.centerx - 20, this.centery + 20);
  302. co.arc(this.centerx - 20,this.centery + 20,this.radius,PI + HALFPI,TWOPI,false);
  303. co.closePath();
  304. co.fill();
  305. co.stroke();
  306. // ==================================================================================================================== //
  307. RG.NoShadow(this);
  308. co.strokeStyle = prop['chart.strokestyle'];
  309. co.lineWidth = prop['chart.linewidth'] ? prop['chart.linewidth'] : 0.0001;
  310. /**
  311. * Draw the quarter circle background
  312. */
  313. co.beginPath();
  314. co.moveTo(this.centerx - 20, this.centery + 20);
  315. co.arc(this.centerx - 20,this.centery + 20,this.radius,PI + HALFPI,TWOPI,false);
  316. co.closePath();
  317. co.stroke();
  318. // ==================================================================================================================== //
  319. /**
  320. * Draw the background background again but with no shadow on
  321. */
  322. RGraph.NoShadow(this);
  323. co.lineWidth = 0;
  324. co.fillStyle = RGraph.RadialGradient(this, this.centerx,this.centery, 0,
  325. this.centerx, this.centery, this.radius * 0.5,
  326. prop['chart.background.gradient.color1'],
  327. prop['chart.background.gradient.color2']);
  328. // Go over the bulge again in the gradient
  329. co.beginPath();
  330. co.moveTo(this.centerx, this.centery);
  331. co.arc(this.centerx,this.centery,30,0,TWOPI,0);
  332. co.closePath();
  333. co.fill();
  334. // Go over the main part of the gauge with just the fill
  335. co.beginPath();
  336. co.moveTo(this.centerx - 20, this.centery + 20);
  337. co.lineTo(this.centerx - 20, this.centery + 20 - this.radius);
  338. co.arc(this.centerx - 20,this.centery + 20,this.radius,PI + HALFPI,TWOPI,false);
  339. co.closePath();
  340. co.fill();
  341. // Draw the gray background lines.
  342. co.beginPath();
  343. co.lineWidth = 1;
  344. co.strokeStyle = '#eee';
  345. for (var i=0; i<=5; ++i) {
  346. var p1 = RG.getRadiusEndPoint(this.centerx, this.centery, (HALFPI / 5 * i) + PI + HALFPI, 30);
  347. var p2 = RG.getRadiusEndPoint(this.centerx, this.centery, (HALFPI / 5 * i) + PI + HALFPI, this.radius - 90);
  348. co.moveTo(p1[0], p1[1]);
  349. co.lineTo(p2[0], p2[1]);
  350. }
  351. co.stroke();
  352. }
  353. /**
  354. * Draw the needle
  355. */
  356. this.DrawNeedle = function (index, value, radius)
  357. {
  358. var grad = RG.RadialGradient(this, this.centerx, this.centery, 0,
  359. this.centerx, this.centery, 20,
  360. 'rgba(0,0,0,0)', prop['chart.needle.colors'][index])
  361. this.angles.needle[index] = (((value - this.min) / (this.max - this.min)) * HALFPI) + PI + HALFPI;
  362. co.lineWidth = 1
  363. co.strokeStyle = 'rgba(0,0,0,0)';
  364. co.fillStyle = grad;
  365. co.beginPath();
  366. co.moveTo(this.centerx, this.centery);
  367. co.arc(this.centerx,
  368. this.centery,
  369. 10,
  370. this.angles.needle[index] - HALFPI,
  371. this.angles.needle[index] - HALFPI + 0.000001,
  372. false);
  373. co.arc(this.centerx,
  374. this.centery,
  375. radius - 30,
  376. this.angles.needle[index],
  377. this.angles.needle[index] + 0.000001,
  378. false);
  379. co.arc(this.centerx,
  380. this.centery,
  381. 10,
  382. this.angles.needle[index] + HALFPI,
  383. this.angles.needle[index] + HALFPI + 0.000001,
  384. false);
  385. co.stroke();
  386. co.fill();
  387. }
  388. /**
  389. * Draw the centerpin for the needle
  390. */
  391. this.DrawCenterpin = function ()
  392. {
  393. if (!prop['chart.centerpin.fill']) {
  394. prop['chart.centerpin.fill'] = RG.RadialGradient(this, this.centerx + 5,
  395. this.centery - 5,
  396. 0,
  397. this.centerx + 5,
  398. this.centery - 5,
  399. 20,
  400. 'white',
  401. prop['chart.centerpin.color'])
  402. }
  403. co.strokeStyle = prop['chart.centerpin.stroke'];
  404. co.fillStyle = prop['chart.centerpin.fill'];
  405. co.beginPath();
  406. co.lineWidth = 2;
  407. co.arc(this.centerx,this.centery, 15,0,TWOPI,false);
  408. co.stroke();
  409. co.fill();
  410. }
  411. /**
  412. * Drawthe labels
  413. */
  414. this.DrawLabels = function ()
  415. {
  416. var numLabels = 5;
  417. co.fillStyle = prop['chart.text.color'];
  418. for (var i=0; i<numLabels; ++i) {
  419. co.beginPath();
  420. var num = Number(this.min + ((this.max - this.min) * (i / (numLabels - 1)))).toFixed(prop['chart.scale.decimals']);
  421. num = RG.number_format(this, num, prop['chart.units.pre'], prop['chart.units.post']);
  422. var angle = (i * 22.5) / (180 / PI);
  423. RG.Text2(this,{'font':prop['chart.text.font'],
  424. 'size':prop['chart.text.size'],
  425. 'x':this.centerx + Math.sin(angle) * (this.radius - 53),
  426. 'y':this.centery - Math.cos(angle) * (this.radius - 53),
  427. 'text':String(num),
  428. 'valign':'top',
  429. 'halign':'center',
  430. 'angle':90 * (i / (numLabels - 1)),
  431. 'tag': 'scale'
  432. });
  433. co.fill();
  434. }
  435. }
  436. /**
  437. * Drawthe tickmarks
  438. */
  439. this.DrawTickmarks = function ()
  440. {
  441. var bigTicks = 5;
  442. var smallTicks = 25;
  443. /**
  444. * Draw the smaller tickmarks
  445. */
  446. for (var i=0; i<smallTicks; ++i) {
  447. co.beginPath();
  448. var angle = (HALFPI / (smallTicks - 1)) * i
  449. co.lineWidth = 1;
  450. co.arc(this.centerx,
  451. this.centery,
  452. this.radius - 44,
  453. PI + HALFPI + angle,
  454. PI + HALFPI + angle + 0.0001,
  455. false);
  456. co.arc(this.centerx,
  457. this.centery,
  458. this.radius - 46,
  459. PI + HALFPI + angle,
  460. PI + HALFPI + angle + 0.0001,
  461. false);
  462. co.stroke();
  463. }
  464. /**
  465. * Now draw the larger tickmarks
  466. */
  467. for (var i=0; i<bigTicks; ++i) {
  468. co.beginPath();
  469. var angle = (HALFPI / (bigTicks - 1)) * i
  470. co.lineWidth = 1;
  471. co.arc(this.centerx,
  472. this.centery,
  473. this.radius - 43,
  474. PI + HALFPI + angle,
  475. PI + HALFPI + angle + 0.0001,
  476. false);
  477. co.arc(this.centerx,
  478. this.centery,
  479. this.radius - 47,
  480. PI + HALFPI + angle,
  481. PI + HALFPI + angle + 0.0001,
  482. false);
  483. co.stroke();
  484. }
  485. }
  486. /**
  487. * This draws the green background to the tickmarks
  488. */
  489. this.DrawColorBands = function ()
  490. {
  491. if (RG.is_array(prop['chart.colors.ranges'])) {
  492. var ranges = prop['chart.colors.ranges'];
  493. for (var i=0,len=ranges.length; i<len; ++i) {
  494. co.fillStyle = ranges[i][2];
  495. co.lineWidth = 0;
  496. co.beginPath();
  497. co.arc(this.centerx,
  498. this.centery,
  499. this.radius - 54 - (prop['chart.text.size'] * 1.5),
  500. (((ranges[i][0] - this.min) / (this.max - this.min)) * HALFPI) + (PI + HALFPI),
  501. (((ranges[i][1] - this.min) / (this.max - this.min)) * HALFPI) + (PI + HALFPI),
  502. false);
  503. co.arc(this.centerx,
  504. this.centery,
  505. this.radius - 54 - 10 - (prop['chart.text.size'] * 1.5),
  506. (((ranges[i][1] - this.min) / (this.max - this.min)) * HALFPI) + (PI + HALFPI),
  507. (((ranges[i][0] - this.min) / (this.max - this.min)) * HALFPI) + (PI + HALFPI),
  508. true);
  509. co.closePath();
  510. co.fill();
  511. }
  512. return;
  513. }
  514. /**
  515. * Draw the GREEN region
  516. */
  517. co.strokeStyle = prop['chart.green.color'];
  518. co.fillStyle = prop['chart.green.color'];
  519. var greenStart = PI + HALFPI;
  520. var greenEnd = greenStart + (TWOPI - greenStart) * ((prop['chart.green.end'] - this.min) / (this.max - this.min))
  521. co.beginPath();
  522. co.arc(this.centerx, this.centery, this.radius - 54 - (prop['chart.text.size'] * 1.5), greenStart, greenEnd, false);
  523. co.arc(this.centerx, this.centery, this.radius - 54 - (prop['chart.text.size'] * 1.5) - 10, greenEnd, greenStart, true);
  524. co.fill();
  525. /**
  526. * Draw the YELLOW region
  527. */
  528. co.strokeStyle = prop['chart.yellow.color'];
  529. co.fillStyle = prop['chart.yellow.color'];
  530. var yellowStart = greenEnd;
  531. var yellowEnd = (((prop['chart.red.start'] - this.min) / (this.max - this.min)) * HALFPI) + PI + HALFPI;
  532. co.beginPath();
  533. co.arc(this.centerx, this.centery, this.radius - 54 - (prop['chart.text.size'] * 1.5), yellowStart, yellowEnd, false);
  534. co.arc(this.centerx, this.centery, this.radius - 54 - (prop['chart.text.size'] * 1.5) - 10, yellowEnd, yellowStart, true);
  535. co.fill();
  536. /**
  537. * Draw the RED region
  538. */
  539. co.strokeStyle = prop['chart.red.color'];
  540. co.fillStyle = prop['chart.red.color'];
  541. var redStart = yellowEnd;
  542. var redEnd = TWOPI;
  543. co.beginPath();
  544. co.arc(this.centerx, this.centery, this.radius - 54 - (prop['chart.text.size'] * 1.5), redStart, redEnd, false);
  545. co.arc(this.centerx, this.centery, this.radius - 54 - (prop['chart.text.size'] * 1.5) - 10, redEnd, redStart, true);
  546. co.fill();
  547. }
  548. /**
  549. * Draw the value in text
  550. */
  551. this.DrawLabel = function ()
  552. {
  553. if (prop['chart.value.text']) {
  554. co.strokeStyle = prop['chart.text.color'];
  555. co.fillStyle = prop['chart.text.color'];
  556. var value = typeof(this.value) == 'number' ? this.value.toFixed(prop['chart.value.text.decimals']) : this.value;
  557. if (typeof(value) == 'object') {
  558. for (var i=0; i<value.length; ++i) {
  559. value[i] = Number(value[i]).toFixed(prop['chart.value.text.decimals']);
  560. }
  561. value = value.toString();
  562. }
  563. RG.Text2(this,{'font':prop['chart.value.text.font'],
  564. 'size':prop['chart.value.text.size'],
  565. 'x':this.centerx + (Math.cos((PI / 180) * 45) * (this.radius / 3)),
  566. 'y':this.centery - (Math.sin((PI / 180) * 45) * (this.radius / 3)),
  567. 'text':RG.number_format(this, String(value), prop['chart.value.text.units.pre'], prop['chart.value.text.units.post']),
  568. 'valign':'center',
  569. 'halign':'center',
  570. 'bounding':prop['chart.value.text.boxed'],
  571. 'boundingFill':'white',
  572. 'bold': prop['chart.value.text.bold'],
  573. 'tag': 'value.text'
  574. });
  575. }
  576. }
  577. /**
  578. * A placeholder function
  579. *
  580. * @param object The event object
  581. */
  582. this.getShape = function (e)
  583. {
  584. }
  585. /**
  586. * A getValue method
  587. *
  588. * @param object e An event object
  589. */
  590. this.getValue = function (e)
  591. {
  592. var mouseXY = RGraph.getMouseXY(e);
  593. var mouseX = mouseXY[0];
  594. var mouseY = mouseXY[1];
  595. var angle = RG.getAngleByXY(this.centerx, this.centery, mouseX, mouseY);
  596. if (angle > TWOPI && angle < (PI + HALFPI)) {
  597. return null;
  598. }
  599. var value = ((angle - (PI + HALFPI)) / (TWOPI - (PI + HALFPI))) * (this.max - this.min);
  600. value = value + this.min;
  601. if (value < this.min) {
  602. value = this.min
  603. }
  604. if (value > this.max) {
  605. value = this.max
  606. }
  607. // Special case for this chart
  608. if (mouseX > this.centerx && mouseY > this.centery) {
  609. value = this.max;
  610. }
  611. return value;
  612. }
  613. /**
  614. * The getObjectByXY() worker method. Don't call this call:
  615. *
  616. * RGraph.ObjectRegistry.getObjectByXY(e)
  617. *
  618. * @param object e The event object
  619. */
  620. this.getObjectByXY = function (e)
  621. {
  622. var mouseXY = RGraph.getMouseXY(e);
  623. if (
  624. mouseXY[0] > (this.centerx - 5)
  625. && mouseXY[0] < (this.centerx + this.radius)
  626. && mouseXY[1] > (this.centery - this.radius)
  627. && mouseXY[1] < (this.centery + 5)
  628. && RG.getHypLength(this.centerx, this.centery, mouseXY[0], mouseXY[1]) <= this.radius
  629. ) {
  630. return this;
  631. }
  632. }
  633. /**
  634. * This method handles the adjusting calculation for when the mouse is moved
  635. *
  636. * @param object e The event object
  637. */
  638. this.Adjusting_mousemove = function (e)
  639. {
  640. /**
  641. * Handle adjusting for the Bar
  642. */
  643. if (prop['chart.adjustable'] && RG.Registry.Get('chart.adjusting') && RG.Registry.Get('chart.adjusting').uid == this.uid) {
  644. this.value = this.getValue(e);
  645. RG.Clear(ca);
  646. RG.RedrawCanvas(ca);
  647. RG.FireCustomEvent(this, 'onadjust');
  648. }
  649. }
  650. /**
  651. * This method returns the appropriate angle for a value
  652. *
  653. * @param number value The value to get the angle for
  654. */
  655. this.getAngle = function (value)
  656. {
  657. if (value < this.min || value > this.max) {
  658. return null;
  659. }
  660. var angle = ((value - this.min) / (this.max - this.min)) * HALFPI
  661. angle += (PI + HALFPI);
  662. return angle;
  663. }
  664. /**
  665. * This allows for easy specification of gradients
  666. */
  667. this.parseColors = function ()
  668. {
  669. if (!RG.is_null(prop['chart.colors.ranges'])) {
  670. for (var i=0; i<prop['chart.colors.ranges'].length; ++i) {
  671. prop['chart.colors.ranges'][i][2] = this.parseSingleColorForGradient(prop['chart.colors.ranges'][i][2]);
  672. }
  673. } else {
  674. prop['chart.green.color'] = this.parseSingleColorForGradient(prop['chart.green.color']);
  675. prop['chart.yellow.color'] = this.parseSingleColorForGradient(prop['chart.yellow.color']);
  676. prop['chart.red.color'] = this.parseSingleColorForGradient(prop['chart.red.color']);
  677. }
  678. }
  679. /**
  680. * This parses a single color value
  681. */
  682. this.parseSingleColorForGradient = function (color)
  683. {
  684. if (!color || typeof(color) != 'string') {
  685. return color;
  686. }
  687. if (color.match(/^gradient\((.*)\)$/i)) {
  688. var parts = RegExp.$1.split(':');
  689. var radius_start = this.radius - 54 - prop['chart.text.size'];
  690. var radius_end = radius_start - 15;
  691. // Create the gradient
  692. var grad = co.createRadialGradient(this.centerx, this.centery, radius_start, this.centerx, this.centery, radius_end);
  693. var diff = 1 / (parts.length - 1);
  694. grad.addColorStop(0, RG.trim(parts[0]));
  695. for (var j=1,len=parts.length; j<len; ++j) {
  696. grad.addColorStop(j * diff, RG.trim(parts[j]));
  697. }
  698. }
  699. return grad ? grad : color;
  700. }
  701. /**
  702. * Register the object
  703. */
  704. RG.Register(this);
  705. }