Area.html 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-chart-series-Area'>/**
  19. </span> * @class Ext.chart.series.Area
  20. * @extends Ext.chart.series.Cartesian
  21. *
  22. * Creates a Stacked Area Chart. The stacked area chart is useful when displaying multiple aggregated layers of information.
  23. * As with all other series, the Area Series must be appended in the *series* Chart array configuration. See the Chart
  24. * documentation for more information. A typical configuration object for the area series could be:
  25. *
  26. * @example
  27. * var store = Ext.create('Ext.data.JsonStore', {
  28. * fields: ['name', 'data1', 'data2', 'data3', 'data4', 'data5'],
  29. * data: [
  30. * { 'name': 'metric one', 'data1':10, 'data2':12, 'data3':14, 'data4':8, 'data5':13 },
  31. * { 'name': 'metric two', 'data1':7, 'data2':8, 'data3':16, 'data4':10, 'data5':3 },
  32. * { 'name': 'metric three', 'data1':5, 'data2':2, 'data3':14, 'data4':12, 'data5':7 },
  33. * { 'name': 'metric four', 'data1':2, 'data2':14, 'data3':6, 'data4':1, 'data5':23 },
  34. * { 'name': 'metric five', 'data1':27, 'data2':38, 'data3':36, 'data4':13, 'data5':33 }
  35. * ]
  36. * });
  37. *
  38. * Ext.create('Ext.chart.Chart', {
  39. * renderTo: Ext.getBody(),
  40. * width: 500,
  41. * height: 300,
  42. * store: store,
  43. * axes: [
  44. * {
  45. * type: 'Numeric',
  46. * grid: true,
  47. * position: 'left',
  48. * fields: ['data1', 'data2', 'data3', 'data4', 'data5'],
  49. * title: 'Sample Values',
  50. * grid: {
  51. * odd: {
  52. * opacity: 1,
  53. * fill: '#ddd',
  54. * stroke: '#bbb',
  55. * 'stroke-width': 1
  56. * }
  57. * },
  58. * minimum: 0,
  59. * adjustMinimumByMajorUnit: 0
  60. * },
  61. * {
  62. * type: 'Category',
  63. * position: 'bottom',
  64. * fields: ['name'],
  65. * title: 'Sample Metrics',
  66. * grid: true,
  67. * label: {
  68. * rotate: {
  69. * degrees: 315
  70. * }
  71. * }
  72. * }
  73. * ],
  74. * series: [{
  75. * type: 'area',
  76. * highlight: false,
  77. * axis: 'left',
  78. * xField: 'name',
  79. * yField: ['data1', 'data2', 'data3', 'data4', 'data5'],
  80. * style: {
  81. * opacity: 0.93
  82. * }
  83. * }]
  84. * });
  85. *
  86. * In this configuration we set `area` as the type for the series, set highlighting options to true for highlighting elements on hover,
  87. * take the left axis to measure the data in the area series, set as xField (x values) the name field of each element in the store,
  88. * and as yFields (aggregated layers) seven data fields from the same store. Then we override some theming styles by adding some opacity
  89. * to the style object.
  90. *
  91. * @xtype area
  92. */
  93. Ext.define('Ext.chart.series.Area', {
  94. /* Begin Definitions */
  95. extend: 'Ext.chart.series.Cartesian',
  96. alias: 'series.area',
  97. requires: ['Ext.chart.axis.Axis', 'Ext.draw.Color', 'Ext.fx.Anim'],
  98. /* End Definitions */
  99. type: 'area',
  100. // @private Area charts are alyways stacked
  101. stacked: true,
  102. <span id='Ext-chart-series-Area-cfg-style'> /**
  103. </span> * @cfg {Object} style
  104. * Append styling properties to this object for it to override theme properties.
  105. */
  106. style: {},
  107. constructor: function(config) {
  108. this.callParent(arguments);
  109. var me = this,
  110. surface = me.chart.surface,
  111. i, l;
  112. config.highlightCfg = Ext.Object.merge({}, {
  113. lineWidth: 3,
  114. stroke: '#55c',
  115. opacity: 0.8,
  116. color: '#f00'
  117. }, config.highlightCfg);
  118. Ext.apply(me, config, {
  119. __excludes: []
  120. });
  121. if (me.highlight) {
  122. me.highlightSprite = surface.add({
  123. type: 'path',
  124. path: ['M', 0, 0],
  125. zIndex: 1000,
  126. opacity: 0.3,
  127. lineWidth: 5,
  128. hidden: true,
  129. stroke: '#444'
  130. });
  131. }
  132. me.group = surface.getGroup(me.seriesId);
  133. },
  134. // @private Shrinks dataSets down to a smaller size
  135. shrink: function(xValues, yValues, size) {
  136. var len = xValues.length,
  137. ratio = Math.floor(len / size),
  138. i, j,
  139. xSum = 0,
  140. yCompLen = this.areas.length,
  141. ySum = [],
  142. xRes = [],
  143. yRes = [];
  144. //initialize array
  145. for (j = 0; j &lt; yCompLen; ++j) {
  146. ySum[j] = 0;
  147. }
  148. for (i = 0; i &lt; len; ++i) {
  149. xSum += +xValues[i];
  150. for (j = 0; j &lt; yCompLen; ++j) {
  151. ySum[j] += +yValues[i][j];
  152. }
  153. if (i % ratio == 0) {
  154. //push averages
  155. xRes.push(xSum/ratio);
  156. for (j = 0; j &lt; yCompLen; ++j) {
  157. ySum[j] /= ratio;
  158. }
  159. yRes.push(ySum);
  160. //reset sum accumulators
  161. xSum = 0;
  162. for (j = 0, ySum = []; j &lt; yCompLen; ++j) {
  163. ySum[j] = 0;
  164. }
  165. }
  166. }
  167. return {
  168. x: xRes,
  169. y: yRes
  170. };
  171. },
  172. // @private Get chart and data boundaries
  173. getBounds: function() {
  174. var me = this,
  175. chart = me.chart,
  176. store = chart.getChartStore(),
  177. data = store.data.items,
  178. i, l, record,
  179. areas = [].concat(me.yField),
  180. areasLen = areas.length,
  181. xValues = [],
  182. yValues = [],
  183. infinity = Infinity,
  184. minX = infinity,
  185. minY = infinity,
  186. maxX = -infinity,
  187. maxY = -infinity,
  188. math = Math,
  189. mmin = math.min,
  190. mmax = math.max,
  191. boundAxis = me.getAxesForXAndYFields(),
  192. boundXAxis = boundAxis.xAxis,
  193. boundYAxis = boundAxis.yAxis,
  194. ends, allowDate,
  195. bbox, xScale, yScale, xValue, yValue, areaIndex, acumY, ln, sumValues, clipBox, areaElem, axis, out;
  196. me.setBBox();
  197. bbox = me.bbox;
  198. if (axis = chart.axes.get(boundXAxis)) {
  199. if (axis.type === 'Time') {
  200. allowDate = true;
  201. }
  202. ends = axis.applyData();
  203. minX = ends.from;
  204. maxX = ends.to;
  205. }
  206. if (axis = chart.axes.get(boundYAxis)) {
  207. ends = axis.applyData();
  208. minY = ends.from;
  209. maxY = ends.to;
  210. }
  211. // If a field was specified without a corresponding axis, create one to get bounds
  212. if (me.xField &amp;&amp; !Ext.isNumber(minX)) {
  213. axis = me.getMinMaxXValues();
  214. allowDate = true;
  215. minX = axis[0];
  216. maxX = axis[1];
  217. }
  218. if (me.yField &amp;&amp; !Ext.isNumber(minY)) {
  219. axis = me.getMinMaxYValues();
  220. minY = axis[0];
  221. maxY = axis[1];
  222. }
  223. if (!Ext.isNumber(minY)) {
  224. minY = 0;
  225. }
  226. if (!Ext.isNumber(maxY)) {
  227. maxY = 0;
  228. }
  229. for (i = 0, l = data.length; i &lt; l; i++) {
  230. record = data[i];
  231. xValue = record.get(me.xField);
  232. yValue = [];
  233. if (typeof xValue != 'number') {
  234. if (allowDate) {
  235. xValue = +xValue;
  236. } else {
  237. xValue = i;
  238. }
  239. }
  240. xValues.push(xValue);
  241. acumY = 0;
  242. for (areaIndex = 0; areaIndex &lt; areasLen; areaIndex++) {
  243. // Excluded series
  244. if (me.__excludes[areaIndex]) {
  245. continue;
  246. }
  247. areaElem = record.get(areas[areaIndex]);
  248. if (typeof areaElem == 'number') {
  249. yValue.push(areaElem);
  250. }
  251. }
  252. yValues.push(yValue);
  253. }
  254. xScale = bbox.width / ((maxX - minX) || 1);
  255. yScale = bbox.height / ((maxY - minY) || 1);
  256. ln = xValues.length;
  257. if ((ln &gt; bbox.width) &amp;&amp; me.areas) {
  258. sumValues = me.shrink(xValues, yValues, bbox.width);
  259. xValues = sumValues.x;
  260. yValues = sumValues.y;
  261. }
  262. return {
  263. bbox: bbox,
  264. minX: minX,
  265. minY: minY,
  266. xValues: xValues,
  267. yValues: yValues,
  268. xScale: xScale,
  269. yScale: yScale,
  270. areasLen: areasLen
  271. };
  272. },
  273. // @private Build an array of paths for the chart
  274. getPaths: function() {
  275. var me = this,
  276. chart = me.chart,
  277. store = chart.getChartStore(),
  278. first = true,
  279. bounds = me.getBounds(),
  280. bbox = bounds.bbox,
  281. items = me.items = [],
  282. componentPaths = [],
  283. componentPath,
  284. count = 0,
  285. paths = [],
  286. i, ln, x, y, xValue, yValue, acumY, areaIndex, prevAreaIndex, areaElem, path;
  287. ln = bounds.xValues.length;
  288. // Start the path
  289. for (i = 0; i &lt; ln; i++) {
  290. xValue = bounds.xValues[i];
  291. yValue = bounds.yValues[i];
  292. x = bbox.x + (xValue - bounds.minX) * bounds.xScale;
  293. acumY = 0;
  294. count = 0;
  295. for (areaIndex = 0; areaIndex &lt; bounds.areasLen; areaIndex++) {
  296. // Excluded series
  297. if (me.__excludes[areaIndex]) {
  298. continue;
  299. }
  300. if (!componentPaths[areaIndex]) {
  301. componentPaths[areaIndex] = [];
  302. }
  303. areaElem = yValue[count];
  304. acumY += areaElem;
  305. y = bbox.y + bbox.height - (acumY - bounds.minY) * bounds.yScale;
  306. if (!paths[areaIndex]) {
  307. paths[areaIndex] = ['M', x, y];
  308. componentPaths[areaIndex].push(['L', x, y]);
  309. } else {
  310. paths[areaIndex].push('L', x, y);
  311. componentPaths[areaIndex].push(['L', x, y]);
  312. }
  313. if (!items[areaIndex]) {
  314. items[areaIndex] = {
  315. pointsUp: [],
  316. pointsDown: [],
  317. series: me
  318. };
  319. }
  320. items[areaIndex].pointsUp.push([x, y]);
  321. count++;
  322. }
  323. }
  324. // Close the paths
  325. for (areaIndex = 0; areaIndex &lt; bounds.areasLen; areaIndex++) {
  326. // Excluded series
  327. if (me.__excludes[areaIndex]) {
  328. continue;
  329. }
  330. path = paths[areaIndex];
  331. // Close bottom path to the axis
  332. if (areaIndex == 0 || first) {
  333. first = false;
  334. path.push('L', x, bbox.y + bbox.height,
  335. 'L', bbox.x, bbox.y + bbox.height,
  336. 'Z');
  337. }
  338. // Close other paths to the one before them
  339. else {
  340. componentPath = componentPaths[prevAreaIndex];
  341. componentPath.reverse();
  342. path.push('L', x, componentPath[0][2]);
  343. for (i = 0; i &lt; ln; i++) {
  344. path.push(componentPath[i][0],
  345. componentPath[i][1],
  346. componentPath[i][2]);
  347. items[areaIndex].pointsDown[ln -i -1] = [componentPath[i][1], componentPath[i][2]];
  348. }
  349. path.push('L', bbox.x, path[2], 'Z');
  350. }
  351. prevAreaIndex = areaIndex;
  352. }
  353. return {
  354. paths: paths,
  355. areasLen: bounds.areasLen
  356. };
  357. },
  358. <span id='Ext-chart-series-Area-method-drawSeries'> /**
  359. </span> * Draws the series for the current chart.
  360. */
  361. drawSeries: function() {
  362. var me = this,
  363. chart = me.chart,
  364. store = chart.getChartStore(),
  365. surface = chart.surface,
  366. animate = chart.animate,
  367. group = me.group,
  368. endLineStyle = Ext.apply(me.seriesStyle, me.style),
  369. colorArrayStyle = me.colorArrayStyle,
  370. colorArrayLength = colorArrayStyle &amp;&amp; colorArrayStyle.length || 0,
  371. areaIndex, areaElem, paths, path, rendererAttributes;
  372. me.unHighlightItem();
  373. me.cleanHighlights();
  374. if (!store || !store.getCount() || me.seriesIsHidden) {
  375. me.hide();
  376. me.items = [];
  377. return;
  378. }
  379. paths = me.getPaths();
  380. if (!me.areas) {
  381. me.areas = [];
  382. }
  383. for (areaIndex = 0; areaIndex &lt; paths.areasLen; areaIndex++) {
  384. // Excluded series
  385. if (me.__excludes[areaIndex]) {
  386. continue;
  387. }
  388. if (!me.areas[areaIndex]) {
  389. me.items[areaIndex].sprite = me.areas[areaIndex] = surface.add(Ext.apply({}, {
  390. type: 'path',
  391. group: group,
  392. // 'clip-rect': me.clipBox,
  393. path: paths.paths[areaIndex],
  394. stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength],
  395. fill: colorArrayStyle[areaIndex % colorArrayLength]
  396. }, endLineStyle || {}));
  397. }
  398. areaElem = me.areas[areaIndex];
  399. path = paths.paths[areaIndex];
  400. if (animate) {
  401. //Add renderer to line. There is not a unique record associated with this.
  402. rendererAttributes = me.renderer(areaElem, false, {
  403. path: path,
  404. // 'clip-rect': me.clipBox,
  405. fill: colorArrayStyle[areaIndex % colorArrayLength],
  406. stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
  407. }, areaIndex, store);
  408. //fill should not be used here but when drawing the special fill path object
  409. me.animation = me.onAnimate(areaElem, {
  410. to: rendererAttributes
  411. });
  412. } else {
  413. rendererAttributes = me.renderer(areaElem, false, {
  414. path: path,
  415. // 'clip-rect': me.clipBox,
  416. hidden: false,
  417. fill: colorArrayStyle[areaIndex % colorArrayLength],
  418. stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
  419. }, areaIndex, store);
  420. me.areas[areaIndex].setAttributes(rendererAttributes, true);
  421. }
  422. }
  423. me.renderLabels();
  424. me.renderCallouts();
  425. },
  426. // @private
  427. onAnimate: function(sprite, attr) {
  428. sprite.show();
  429. return this.callParent(arguments);
  430. },
  431. // @private
  432. onCreateLabel: function(storeItem, item, i, display) {
  433. var me = this,
  434. group = me.labelsGroup,
  435. config = me.label,
  436. bbox = me.bbox,
  437. endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
  438. return me.chart.surface.add(Ext.apply({
  439. 'type': 'text',
  440. 'text-anchor': 'middle',
  441. 'group': group,
  442. 'x': item.point[0],
  443. 'y': bbox.y + bbox.height / 2
  444. }, endLabelStyle || {}));
  445. },
  446. // @private
  447. onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
  448. var me = this,
  449. chart = me.chart,
  450. resizing = chart.resizing,
  451. config = me.label,
  452. format = config.renderer,
  453. field = config.field,
  454. bbox = me.bbox,
  455. x = item.point[0],
  456. y = item.point[1],
  457. bb, width, height;
  458. label.setAttributes({
  459. text: format(storeItem.get(field[index])),
  460. hidden: true
  461. }, true);
  462. bb = label.getBBox();
  463. width = bb.width / 2;
  464. height = bb.height / 2;
  465. x = x - width &lt; bbox.x? bbox.x + width : x;
  466. x = (x + width &gt; bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
  467. y = y - height &lt; bbox.y? bbox.y + height : y;
  468. y = (y + height &gt; bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
  469. if (me.chart.animate &amp;&amp; !me.chart.resizing) {
  470. label.show(true);
  471. me.onAnimate(label, {
  472. to: {
  473. x: x,
  474. y: y
  475. }
  476. });
  477. } else {
  478. label.setAttributes({
  479. x: x,
  480. y: y
  481. }, true);
  482. if (resizing) {
  483. me.animation.on('afteranimate', function() {
  484. label.show(true);
  485. });
  486. } else {
  487. label.show(true);
  488. }
  489. }
  490. },
  491. // @private
  492. onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) {
  493. var me = this,
  494. chart = me.chart,
  495. surface = chart.surface,
  496. resizing = chart.resizing,
  497. config = me.callouts,
  498. items = me.items,
  499. prev = (i == 0) ? false : items[i -1].point,
  500. next = (i == items.length -1) ? false : items[i +1].point,
  501. cur = item.point,
  502. dir, norm, normal, a, aprev, anext,
  503. bbox = callout.label.getBBox(),
  504. offsetFromViz = 30,
  505. offsetToSide = 10,
  506. offsetBox = 3,
  507. boxx, boxy, boxw, boxh,
  508. p, clipRect = me.clipRect,
  509. x, y;
  510. //get the right two points
  511. if (!prev) {
  512. prev = cur;
  513. }
  514. if (!next) {
  515. next = cur;
  516. }
  517. a = (next[1] - prev[1]) / (next[0] - prev[0]);
  518. aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]);
  519. anext = (next[1] - cur[1]) / (next[0] - cur[0]);
  520. norm = Math.sqrt(1 + a * a);
  521. dir = [1 / norm, a / norm];
  522. normal = [-dir[1], dir[0]];
  523. //keep the label always on the outer part of the &quot;elbow&quot;
  524. if (aprev &gt; 0 &amp;&amp; anext &lt; 0 &amp;&amp; normal[1] &lt; 0 || aprev &lt; 0 &amp;&amp; anext &gt; 0 &amp;&amp; normal[1] &gt; 0) {
  525. normal[0] *= -1;
  526. normal[1] *= -1;
  527. } else if (Math.abs(aprev) &lt; Math.abs(anext) &amp;&amp; normal[0] &lt; 0 || Math.abs(aprev) &gt; Math.abs(anext) &amp;&amp; normal[0] &gt; 0) {
  528. normal[0] *= -1;
  529. normal[1] *= -1;
  530. }
  531. //position
  532. x = cur[0] + normal[0] * offsetFromViz;
  533. y = cur[1] + normal[1] * offsetFromViz;
  534. //box position and dimensions
  535. boxx = x + (normal[0] &gt; 0? 0 : -(bbox.width + 2 * offsetBox));
  536. boxy = y - bbox.height /2 - offsetBox;
  537. boxw = bbox.width + 2 * offsetBox;
  538. boxh = bbox.height + 2 * offsetBox;
  539. //now check if we're out of bounds and invert the normal vector correspondingly
  540. //this may add new overlaps between labels (but labels won't be out of bounds).
  541. if (boxx &lt; clipRect[0] || (boxx + boxw) &gt; (clipRect[0] + clipRect[2])) {
  542. normal[0] *= -1;
  543. }
  544. if (boxy &lt; clipRect[1] || (boxy + boxh) &gt; (clipRect[1] + clipRect[3])) {
  545. normal[1] *= -1;
  546. }
  547. //update positions
  548. x = cur[0] + normal[0] * offsetFromViz;
  549. y = cur[1] + normal[1] * offsetFromViz;
  550. //update box position and dimensions
  551. boxx = x + (normal[0] &gt; 0? 0 : -(bbox.width + 2 * offsetBox));
  552. boxy = y - bbox.height /2 - offsetBox;
  553. boxw = bbox.width + 2 * offsetBox;
  554. boxh = bbox.height + 2 * offsetBox;
  555. //set the line from the middle of the pie to the box.
  556. callout.lines.setAttributes({
  557. path: [&quot;M&quot;, cur[0], cur[1], &quot;L&quot;, x, y, &quot;Z&quot;]
  558. }, true);
  559. //set box position
  560. callout.box.setAttributes({
  561. x: boxx,
  562. y: boxy,
  563. width: boxw,
  564. height: boxh
  565. }, true);
  566. //set text position
  567. callout.label.setAttributes({
  568. x: x + (normal[0] &gt; 0? offsetBox : -(bbox.width + offsetBox)),
  569. y: y
  570. }, true);
  571. for (p in callout) {
  572. callout[p].show(true);
  573. }
  574. },
  575. isItemInPoint: function(x, y, item, i) {
  576. var me = this,
  577. pointsUp = item.pointsUp,
  578. pointsDown = item.pointsDown,
  579. abs = Math.abs,
  580. distChanged = false,
  581. last = false,
  582. dist = Infinity, p, pln, point;
  583. for (p = 0, pln = pointsUp.length; p &lt; pln; p++) {
  584. point = [pointsUp[p][0], pointsUp[p][1]];
  585. distChanged = false;
  586. last = p == pln -1;
  587. if (dist &gt; abs(x - point[0])) {
  588. dist = abs(x - point[0]);
  589. distChanged = true;
  590. if (last) {
  591. ++p;
  592. }
  593. }
  594. if (!distChanged || (distChanged &amp;&amp; last)) {
  595. point = pointsUp[p -1];
  596. if (y &gt;= point[1] &amp;&amp; (!pointsDown.length || y &lt;= (pointsDown[p -1][1]))) {
  597. item.storeIndex = p -1;
  598. item.storeField = me.yField[i];
  599. item.storeItem = me.chart.store.getAt(p -1);
  600. item._points = pointsDown.length? [point, pointsDown[p -1]] : [point];
  601. return true;
  602. } else {
  603. break;
  604. }
  605. }
  606. }
  607. return false;
  608. },
  609. <span id='Ext-chart-series-Area-method-highlightSeries'> /**
  610. </span> * Highlight this entire series.
  611. * @param {Object} item Info about the item; same format as returned by #getItemForPoint.
  612. */
  613. highlightSeries: function() {
  614. var area, to, fillColor;
  615. if (this._index !== undefined) {
  616. area = this.areas[this._index];
  617. if (area.__highlightAnim) {
  618. area.__highlightAnim.paused = true;
  619. }
  620. area.__highlighted = true;
  621. area.__prevOpacity = area.__prevOpacity || area.attr.opacity || 1;
  622. area.__prevFill = area.__prevFill || area.attr.fill;
  623. area.__prevLineWidth = area.__prevLineWidth || area.attr.lineWidth;
  624. fillColor = Ext.draw.Color.fromString(area.__prevFill);
  625. to = {
  626. lineWidth: (area.__prevLineWidth || 0) + 2
  627. };
  628. if (fillColor) {
  629. to.fill = fillColor.getLighter(0.2).toString();
  630. }
  631. else {
  632. to.opacity = Math.max(area.__prevOpacity - 0.3, 0);
  633. }
  634. if (this.chart.animate) {
  635. area.__highlightAnim = new Ext.fx.Anim(Ext.apply({
  636. target: area,
  637. to: to
  638. }, this.chart.animate));
  639. }
  640. else {
  641. area.setAttributes(to, true);
  642. }
  643. }
  644. },
  645. <span id='Ext-chart-series-Area-method-unHighlightSeries'> /**
  646. </span> * UnHighlight this entire series.
  647. * @param {Object} item Info about the item; same format as returned by #getItemForPoint.
  648. */
  649. unHighlightSeries: function() {
  650. var area;
  651. if (this._index !== undefined) {
  652. area = this.areas[this._index];
  653. if (area.__highlightAnim) {
  654. area.__highlightAnim.paused = true;
  655. }
  656. if (area.__highlighted) {
  657. area.__highlighted = false;
  658. area.__highlightAnim = new Ext.fx.Anim({
  659. target: area,
  660. to: {
  661. fill: area.__prevFill,
  662. opacity: area.__prevOpacity,
  663. lineWidth: area.__prevLineWidth
  664. }
  665. });
  666. }
  667. }
  668. },
  669. <span id='Ext-chart-series-Area-method-highlightItem'> /**
  670. </span> * Highlight the specified item. If no item is provided the whole series will be highlighted.
  671. * @param item {Object} Info about the item; same format as returned by #getItemForPoint
  672. */
  673. highlightItem: function(item) {
  674. var me = this,
  675. points, path;
  676. if (!item) {
  677. this.highlightSeries();
  678. return;
  679. }
  680. points = item._points;
  681. path = points.length == 2? ['M', points[0][0], points[0][1], 'L', points[1][0], points[1][1]]
  682. : ['M', points[0][0], points[0][1], 'L', points[0][0], me.bbox.y + me.bbox.height];
  683. me.highlightSprite.setAttributes({
  684. path: path,
  685. hidden: false
  686. }, true);
  687. },
  688. <span id='Ext-chart-series-Area-method-unHighlightItem'> /**
  689. </span> * Un-highlights the specified item. If no item is provided it will un-highlight the entire series.
  690. * @param {Object} item Info about the item; same format as returned by #getItemForPoint
  691. */
  692. unHighlightItem: function(item) {
  693. if (!item) {
  694. this.unHighlightSeries();
  695. }
  696. if (this.highlightSprite) {
  697. this.highlightSprite.hide(true);
  698. }
  699. },
  700. // @private
  701. hideAll: function(index) {
  702. var me = this;
  703. index = (isNaN(me._index) ? index : me._index) || 0;
  704. me.__excludes[index] = true;
  705. me.areas[index].hide(true);
  706. me.redraw();
  707. },
  708. // @private
  709. showAll: function(index) {
  710. var me = this;
  711. index = (isNaN(me._index) ? index : me._index) || 0;
  712. me.__excludes[index] = false;
  713. me.areas[index].show(true);
  714. me.redraw();
  715. },
  716. redraw: function() {
  717. //store previous configuration for the legend
  718. //and set it to false so we don't
  719. //re-build label elements if not necessary.
  720. var me = this,
  721. prevLegendConfig;
  722. prevLegendConfig = me.chart.legend.rebuild;
  723. me.chart.legend.rebuild = false;
  724. me.chart.redraw();
  725. me.chart.legend.rebuild = prevLegendConfig;
  726. },
  727. hide: function() {
  728. if (this.areas) {
  729. var me = this,
  730. areas = me.areas,
  731. i, j, l, ln, shadows;
  732. if (areas &amp;&amp; areas.length) {
  733. for (i = 0, ln = areas.length; i &lt; ln; ++i) {
  734. if (areas[i]) {
  735. areas[i].hide(true);
  736. }
  737. }
  738. me.hideLabels();
  739. }
  740. }
  741. },
  742. <span id='Ext-chart-series-Area-method-getLegendColor'> /**
  743. </span> * Returns the color of the series (to be displayed as color for the series legend item).
  744. * @param {Object} item Info about the item; same format as returned by #getItemForPoint
  745. */
  746. getLegendColor: function(index) {
  747. var me = this;
  748. return me.colorArrayStyle[index % me.colorArrayStyle.length];
  749. }
  750. });
  751. </pre>
  752. </body>
  753. </html>