123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943 |
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>The source code</title>
- <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
- <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
- <style type="text/css">
- .highlight { display: block; background-color: #ddd; }
- </style>
- <script type="text/javascript">
- function highlight() {
- document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
- }
- </script>
- </head>
- <body onload="prettyPrint(); highlight();">
- <pre class="prettyprint lang-js"><span id='Ext-chart-axis-Axis'>/**
- </span> * @class Ext.chart.axis.Axis
- *
- * Defines axis for charts. The axis position, type, style can be configured.
- * The axes are defined in an axes array of configuration objects where the type,
- * field, grid and other configuration options can be set. To know more about how
- * to create a Chart please check the Chart class documentation. Here's an example for the axes part:
- * An example of axis for a series (in this case for an area chart that has multiple layers of yFields) could be:
- *
- * axes: [{
- * type: 'Numeric',
- * position: 'left',
- * fields: ['data1', 'data2', 'data3'],
- * title: 'Number of Hits',
- * grid: {
- * odd: {
- * opacity: 1,
- * fill: '#ddd',
- * stroke: '#bbb',
- * 'stroke-width': 1
- * }
- * },
- * minimum: 0
- * }, {
- * type: 'Category',
- * position: 'bottom',
- * fields: ['name'],
- * title: 'Month of the Year',
- * grid: true,
- * label: {
- * rotate: {
- * degrees: 315
- * }
- * }
- * }]
- *
- * In this case we use a `Numeric` axis for displaying the values of the Area series and a `Category` axis for displaying the names of
- * the store elements. The numeric axis is placed on the left of the screen, while the category axis is placed at the bottom of the chart.
- * Both the category and numeric axes have `grid` set, which means that horizontal and vertical lines will cover the chart background. In the
- * category axis the labels will be rotated so they can fit the space better.
- */
- Ext.define('Ext.chart.axis.Axis', {
- /* Begin Definitions */
- extend: 'Ext.chart.axis.Abstract',
- alternateClassName: 'Ext.chart.Axis',
- requires: ['Ext.draw.Draw'],
- /* End Definitions */
- <span id='Ext-chart-axis-Axis-cfg-grid'> /**
- </span> * @cfg {Boolean/Object} grid
- * The grid configuration enables you to set a background grid for an axis.
- * If set to *true* on a vertical axis, vertical lines will be drawn.
- * If set to *true* on a horizontal axis, horizontal lines will be drawn.
- * If both are set, a proper grid with horizontal and vertical lines will be drawn.
- *
- * You can set specific options for the grid configuration for odd and/or even lines/rows.
- * Since the rows being drawn are rectangle sprites, you can set to an odd or even property
- * all styles that apply to {@link Ext.draw.Sprite}. For more information on all the style
- * properties you can set please take a look at {@link Ext.draw.Sprite}. Some useful style properties are `opacity`, `fill`, `stroke`, `stroke-width`, etc.
- *
- * The possible values for a grid option are then *true*, *false*, or an object with `{ odd, even }` properties
- * where each property contains a sprite style descriptor object that is defined in {@link Ext.draw.Sprite}.
- *
- * For example:
- *
- * axes: [{
- * type: 'Numeric',
- * position: 'left',
- * fields: ['data1', 'data2', 'data3'],
- * title: 'Number of Hits',
- * grid: {
- * odd: {
- * opacity: 1,
- * fill: '#ddd',
- * stroke: '#bbb',
- * 'stroke-width': 1
- * }
- * }
- * }, {
- * type: 'Category',
- * position: 'bottom',
- * fields: ['name'],
- * title: 'Month of the Year',
- * grid: true
- * }]
- *
- */
- <span id='Ext-chart-axis-Axis-cfg-majorTickSteps'> /**
- </span> * @cfg {Number} majorTickSteps
- * If `minimum` and `maximum` are specified it forces the number of major ticks to the specified value.
- * If a number of major ticks is forced, it wont search for pretty numbers at the ticks.
- */
- <span id='Ext-chart-axis-Axis-cfg-minorTickSteps'> /**
- </span> * @cfg {Number} minorTickSteps
- * The number of small ticks between two major ticks. Default is zero.
- */
- <span id='Ext-chart-axis-Axis-cfg-title'> /**
- </span> * @cfg {String} title
- * The title for the Axis
- */
- // @private force min/max values from store
- forceMinMax: false,
- <span id='Ext-chart-axis-Axis-cfg-dashSize'> /**
- </span> * @cfg {Number} dashSize
- * The size of the dash marker. Default's 3.
- */
- dashSize: 3,
- <span id='Ext-chart-axis-Axis-cfg-position'> /**
- </span> * @cfg {String} position
- * Where to set the axis. Available options are `left`, `bottom`, `right`, `top`. Default's `bottom`.
- */
- position: 'bottom',
- // @private
- skipFirst: false,
- <span id='Ext-chart-axis-Axis-cfg-length'> /**
- </span> * @cfg {Number} length
- * Offset axis position. Default's 0.
- */
- length: 0,
- <span id='Ext-chart-axis-Axis-cfg-width'> /**
- </span> * @cfg {Number} width
- * Offset axis width. Default's 0.
- */
- width: 0,
- <span id='Ext-chart-axis-Axis-cfg-adjustEnd'> /**
- </span> * @cfg {Boolean} adjustEnd
- * Whether to adjust the label at the end of the axis.
- */
- adjustEnd: true,
- majorTickSteps: false,
- // @private
- applyData: Ext.emptyFn,
- getRange: function () {
- var me = this,
- chart = me.chart,
- store = chart.getChartStore(),
- data = store.data.items,
- series = chart.series.items,
- position = me.position,
- boundedAxes,
- seriesClasses = Ext.chart.series,
- aggregations = [],
- min = Infinity, max = -Infinity,
- vertical = me.position === 'left' || me.position === 'right',
- i, ln, ln2, j, k, dataLength = data.length, aggregates,
- countedFields = {},
- allFields = {},
- excludable = true,
- fields, fieldMap, record, field, value;
- fields = me.fields;
- for (j = 0, ln = fields.length; j < ln; j++) {
- allFields[fields[j]] = true;
- }
- for (i = 0, ln = series.length; i < ln; i++) {
- if (series[i].seriesIsHidden) {
- continue;
- }
- if (!series[i].getAxesForXAndYFields) {
- continue;
- }
- boundedAxes = series[i].getAxesForXAndYFields();
- if (boundedAxes.xAxis && boundedAxes.xAxis !== position && boundedAxes.yAxis && boundedAxes.yAxis !== position) {
- // If the series explicitly exclude current Axis, then exit.
- continue;
- }
- if (seriesClasses.Bar && series[i] instanceof seriesClasses.Bar && !series[i].column) {
- // If this is a horizontal bar series, then flip xField and yField.
- fields = vertical ? Ext.Array.from(series[i].xField) : Ext.Array.from(series[i].yField);
- } else {
- fields = vertical ? Ext.Array.from(series[i].yField) : Ext.Array.from(series[i].xField);
- }
- if (me.fields.length) {
- for (j = 0, ln2 = fields.length; j < ln2; j++) {
- if (allFields[fields[j]]) {
- break;
- }
- }
- if (j == ln2) {
- // Not matching fields, skipping this series.
- continue;
- }
- }
- if (aggregates = series[i].stacked) {
- // If this is a bar/column series, then it will be aggregated if it is of the same direction of the axis.
- if (seriesClasses.Bar && series[i] instanceof seriesClasses.Bar) {
- if (series[i].column != vertical) {
- aggregates = false;
- excludable = false;
- }
- }
- // Otherwise it is stacked vertically
- else if (!vertical) {
- aggregates = false;
- excludable = false;
- }
- }
- if (aggregates) {
- fieldMap = {};
- for (j = 0; j < fields.length; j++) {
- if (excludable && series[i].__excludes && series[i].__excludes[j]) {
- continue;
- }
- if (!allFields[fields[j]]) {
- Ext.Logger.warn('Field `' + fields[j] + '` is not included in the ' + position + ' axis config.');
- }
- allFields[fields[j]] = fieldMap[fields[j]] = true;
- }
- aggregations.push({
- fields: fieldMap,
- value: 0
- });
- } else {
- if (!fields || fields.length == 0) {
- fields = me.fields;
- }
- for (j = 0; j < fields.length; j++) {
- if (excludable && series[i].__excludes && series[i].__excludes[j]) {
- continue;
- }
- allFields[fields[j]] = countedFields[fields[j]] = true;
- }
- }
- }
- for (i = 0; i < dataLength; i++) {
- record = data[i];
- for (k = 0; k < aggregations.length; k++) {
- aggregations[k].value = 0;
- }
- for (field in allFields) {
- value = record.get(field);
- if (isNaN(value)) {
- continue;
- }
- if (value === undefined) {
- value = 0;
- }
- if (countedFields[field]) {
- if (min > value) {
- min = value;
- }
- if (max < value) {
- max = value;
- }
- }
- for (k = 0; k < aggregations.length; k++) {
- if (aggregations[k].fields[field]) {
- aggregations[k].value += value;
- // If any aggregation is actually hit, then the min value should be at most 0.
- if (min > 0) {
- min = 0;
- }
- if (max < aggregations[k].value) {
- max = aggregations[k].value;
- }
- }
- }
- }
- }
- if (!isFinite(max)) {
- max = me.prevMax || 0;
- }
- if (!isFinite(min)) {
- min = me.prevMin || 0;
- }
- //normalize min max for snapEnds.
- if (min != max && (max != Math.floor(max))) {
- max = Math.floor(max) + 1;
- }
- if (!isNaN(me.minimum)) {
- min = me.minimum;
- }
- if (!isNaN(me.maximum)) {
- max = me.maximum;
- }
- if (min >= max) {
- // snapEnds will return NaN if max >= min;
- max = min + 1;
- }
- return {min: min, max: max};
- },
- // @private creates a structure with start, end and step points.
- calcEnds: function () {
- var me = this,
- range = me.getRange(),
- min = range.min,
- max = range.max,
- steps, prettyNumbers, out, changedRange;
- steps = (Ext.isNumber(me.majorTickSteps) ? me.majorTickSteps + 1 : me.steps);
- prettyNumbers = !(Ext.isNumber(me.maximum) && Ext.isNumber(me.minimum) && Ext.isNumber(me.majorTickSteps) && me.majorTickSteps > 0);
- out = Ext.draw.Draw.snapEnds(min, max, steps, prettyNumbers);
- if (Ext.isNumber(me.maximum)) {
- out.to = me.maximum;
- changedRange = true;
- }
- if (Ext.isNumber(me.minimum)) {
- out.from = me.minimum;
- changedRange = true;
- }
- if (me.adjustMaximumByMajorUnit) {
- out.to = Math.ceil(out.to / out.step) * out.step;
- changedRange = true;
- }
- if (me.adjustMinimumByMajorUnit) {
- out.from = Math.floor(out.from / out.step) * out.step;
- changedRange = true;
- }
- if (changedRange) {
- out.steps = Math.ceil((out.to - out.from) / out.step);
- }
- me.prevMin = (min == max ? 0 : min);
- me.prevMax = max;
- return out;
- },
- <span id='Ext-chart-axis-Axis-method-drawAxis'> /**
- </span> * Renders the axis into the screen and updates its position.
- */
- drawAxis: function (init) {
- var me = this,
- i,
- x = me.x,
- y = me.y,
- gutterX = me.chart.maxGutter[0],
- gutterY = me.chart.maxGutter[1],
- dashSize = me.dashSize,
- subDashesX = me.minorTickSteps || 0,
- subDashesY = me.minorTickSteps || 0,
- length = me.length,
- position = me.position,
- inflections = [],
- calcLabels = false,
- stepCalcs = me.applyData(),
- step = stepCalcs.step,
- steps = stepCalcs.steps,
- from = stepCalcs.from,
- to = stepCalcs.to,
- trueLength,
- currentX,
- currentY,
- path,
- dashesX,
- dashesY,
- delta;
- //If no steps are specified
- //then don't draw the axis. This generally happens
- //when an empty store.
- if (me.hidden || isNaN(step) || (from > to)) {
- return;
- }
- me.from = stepCalcs.from;
- me.to = stepCalcs.to;
- if (position == 'left' || position == 'right') {
- currentX = Math.floor(x) + 0.5;
- path = ["M", currentX, y, "l", 0, -length];
- trueLength = length - (gutterY * 2);
- }
- else {
- currentY = Math.floor(y) + 0.5;
- path = ["M", x, currentY, "l", length, 0];
- trueLength = length - (gutterX * 2);
- }
- // Supports the case that we have only 1 record.
- delta = steps && trueLength / steps;
- dashesX = Math.max(subDashesX + 1, 0);
- dashesY = Math.max(subDashesY + 1, 0);
- if (me.type == 'Numeric' || me.type == 'Time') {
- calcLabels = true;
- me.labels = [stepCalcs.from];
- }
- if (position == 'right' || position == 'left') {
- currentY = y - gutterY;
- currentX = x - ((position == 'left') * dashSize * 2);
- while (currentY >= y - gutterY - trueLength) {
- path.push("M", currentX, Math.floor(currentY) + 0.5, "l", dashSize * 2 + 1, 0);
- if (currentY != y - gutterY) {
- for (i = 1; i < dashesY; i++) {
- path.push("M", currentX + dashSize, Math.floor(currentY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
- }
- }
- inflections.push([ Math.floor(x), Math.floor(currentY) ]);
- currentY -= delta;
- if (calcLabels) {
- me.labels.push(me.labels[me.labels.length - 1] + step);
- }
- if (delta === 0) {
- break;
- }
- }
- if (Math.round(currentY + delta - (y - gutterY - trueLength))) {
- path.push("M", currentX, Math.floor(y - length + gutterY) + 0.5, "l", dashSize * 2 + 1, 0);
- for (i = 1; i < dashesY; i++) {
- path.push("M", currentX + dashSize, Math.floor(y - length + gutterY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
- }
- inflections.push([ Math.floor(x), Math.floor(currentY) ]);
- if (calcLabels) {
- me.labels.push(me.labels[me.labels.length - 1] + step);
- }
- }
- } else {
- currentX = x + gutterX;
- currentY = y - ((position == 'top') * dashSize * 2);
- while (currentX <= x + gutterX + trueLength) {
- path.push("M", Math.floor(currentX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
- if (currentX != x + gutterX) {
- for (i = 1; i < dashesX; i++) {
- path.push("M", Math.floor(currentX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
- }
- }
- inflections.push([ Math.floor(currentX), Math.floor(y) ]);
- currentX += delta;
- if (calcLabels) {
- me.labels.push(me.labels[me.labels.length - 1] + step);
- }
- if (delta === 0) {
- break;
- }
- }
- if (Math.round(currentX - delta - (x + gutterX + trueLength))) {
- path.push("M", Math.floor(x + length - gutterX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
- for (i = 1; i < dashesX; i++) {
- path.push("M", Math.floor(x + length - gutterX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
- }
- inflections.push([ Math.floor(currentX), Math.floor(y) ]);
- if (calcLabels) {
- me.labels.push(me.labels[me.labels.length - 1] + step);
- }
- }
- }
- // the label on index "inflections.length-1" is the last label that gets rendered
- if (calcLabels) {
- me.labels[inflections.length - 1] = +(me.labels[inflections.length - 1]).toFixed(10);
- }
- if (!me.axis) {
- me.axis = me.chart.surface.add(Ext.apply({
- type: 'path',
- path: path
- }, me.axisStyle));
- }
- me.axis.setAttributes({
- path: path
- }, true);
- me.inflections = inflections;
- if (!init && me.grid) {
- me.drawGrid();
- }
- me.axisBBox = me.axis.getBBox();
- me.drawLabel();
- },
- <span id='Ext-chart-axis-Axis-method-drawGrid'> /**
- </span> * Renders an horizontal and/or vertical grid into the Surface.
- */
- drawGrid: function () {
- var me = this,
- surface = me.chart.surface,
- grid = me.grid,
- odd = grid.odd,
- even = grid.even,
- inflections = me.inflections,
- ln = inflections.length - ((odd || even) ? 0 : 1),
- position = me.position,
- gutter = me.chart.maxGutter,
- width = me.width - 2,
- point, prevPoint,
- i = 1,
- path = [], styles, lineWidth, dlineWidth,
- oddPath = [], evenPath = [];
- if ((gutter[1] !== 0 && (position == 'left' || position == 'right')) ||
- (gutter[0] !== 0 && (position == 'top' || position == 'bottom'))) {
- i = 0;
- ln++;
- }
- for (; i < ln; i++) {
- point = inflections[i];
- prevPoint = inflections[i - 1];
- if (odd || even) {
- path = (i % 2) ? oddPath : evenPath;
- styles = ((i % 2) ? odd : even) || {};
- lineWidth = (styles.lineWidth || styles['stroke-width'] || 0) / 2;
- dlineWidth = 2 * lineWidth;
- if (position == 'left') {
- path.push("M", prevPoint[0] + 1 + lineWidth, prevPoint[1] + 0.5 - lineWidth,
- "L", prevPoint[0] + 1 + width - lineWidth, prevPoint[1] + 0.5 - lineWidth,
- "L", point[0] + 1 + width - lineWidth, point[1] + 0.5 + lineWidth,
- "L", point[0] + 1 + lineWidth, point[1] + 0.5 + lineWidth, "Z");
- }
- else if (position == 'right') {
- path.push("M", prevPoint[0] - lineWidth, prevPoint[1] + 0.5 - lineWidth,
- "L", prevPoint[0] - width + lineWidth, prevPoint[1] + 0.5 - lineWidth,
- "L", point[0] - width + lineWidth, point[1] + 0.5 + lineWidth,
- "L", point[0] - lineWidth, point[1] + 0.5 + lineWidth, "Z");
- }
- else if (position == 'top') {
- path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + lineWidth,
- "L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + width - lineWidth,
- "L", point[0] + 0.5 - lineWidth, point[1] + 1 + width - lineWidth,
- "L", point[0] + 0.5 - lineWidth, point[1] + 1 + lineWidth, "Z");
- }
- else {
- path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - lineWidth,
- "L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - width + lineWidth,
- "L", point[0] + 0.5 - lineWidth, point[1] - width + lineWidth,
- "L", point[0] + 0.5 - lineWidth, point[1] - lineWidth, "Z");
- }
- } else {
- if (position == 'left') {
- path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", width, 0]);
- }
- else if (position == 'right') {
- path = path.concat(["M", point[0] - 0.5, point[1] + 0.5, "l", -width, 0]);
- }
- else if (position == 'top') {
- path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", 0, width]);
- }
- else {
- path = path.concat(["M", point[0] + 0.5, point[1] - 0.5, "l", 0, -width]);
- }
- }
- }
- if (odd || even) {
- if (oddPath.length) {
- if (!me.gridOdd && oddPath.length) {
- me.gridOdd = surface.add({
- type: 'path',
- path: oddPath
- });
- }
- me.gridOdd.setAttributes(Ext.apply({
- path: oddPath,
- hidden: false
- }, odd || {}), true);
- }
- if (evenPath.length) {
- if (!me.gridEven) {
- me.gridEven = surface.add({
- type: 'path',
- path: evenPath
- });
- }
- me.gridEven.setAttributes(Ext.apply({
- path: evenPath,
- hidden: false
- }, even || {}), true);
- }
- }
- else {
- if (path.length) {
- if (!me.gridLines) {
- me.gridLines = me.chart.surface.add({
- type: 'path',
- path: path,
- "stroke-width": me.lineWidth || 1,
- stroke: me.gridColor || '#ccc'
- });
- }
- me.gridLines.setAttributes({
- hidden: false,
- path: path
- }, true);
- }
- else if (me.gridLines) {
- me.gridLines.hide(true);
- }
- }
- },
- // @private
- getOrCreateLabel: function (i, text) {
- var me = this,
- labelGroup = me.labelGroup,
- textLabel = labelGroup.getAt(i),
- surface = me.chart.surface;
- if (textLabel) {
- if (text != textLabel.attr.text) {
- textLabel.setAttributes(Ext.apply({
- text: text
- }, me.label), true);
- textLabel._bbox = textLabel.getBBox();
- }
- }
- else {
- textLabel = surface.add(Ext.apply({
- group: labelGroup,
- type: 'text',
- x: 0,
- y: 0,
- text: text
- }, me.label));
- surface.renderItem(textLabel);
- textLabel._bbox = textLabel.getBBox();
- }
- //get untransformed bounding box
- if (me.label.rotation) {
- textLabel.setAttributes({
- rotation: {
- degrees: 0
- }
- }, true);
- textLabel._ubbox = textLabel.getBBox();
- textLabel.setAttributes(me.label, true);
- } else {
- textLabel._ubbox = textLabel._bbox;
- }
- return textLabel;
- },
- rect2pointArray: function (sprite) {
- var surface = this.chart.surface,
- rect = surface.getBBox(sprite, true),
- p1 = [rect.x, rect.y],
- p1p = p1.slice(),
- p2 = [rect.x + rect.width, rect.y],
- p2p = p2.slice(),
- p3 = [rect.x + rect.width, rect.y + rect.height],
- p3p = p3.slice(),
- p4 = [rect.x, rect.y + rect.height],
- p4p = p4.slice(),
- matrix = sprite.matrix;
- //transform the points
- p1[0] = matrix.x.apply(matrix, p1p);
- p1[1] = matrix.y.apply(matrix, p1p);
- p2[0] = matrix.x.apply(matrix, p2p);
- p2[1] = matrix.y.apply(matrix, p2p);
- p3[0] = matrix.x.apply(matrix, p3p);
- p3[1] = matrix.y.apply(matrix, p3p);
- p4[0] = matrix.x.apply(matrix, p4p);
- p4[1] = matrix.y.apply(matrix, p4p);
- return [p1, p2, p3, p4];
- },
- intersect: function (l1, l2) {
- var r1 = this.rect2pointArray(l1),
- r2 = this.rect2pointArray(l2);
- return !!Ext.draw.Draw.intersect(r1, r2).length;
- },
- drawHorizontalLabels: function () {
- var me = this,
- labelConf = me.label,
- floor = Math.floor,
- max = Math.max,
- axes = me.chart.axes,
- insetPadding = me.chart.insetPadding,
- position = me.position,
- inflections = me.inflections,
- ln = inflections.length,
- labels = me.labels,
- maxHeight = 0,
- ratio,
- bbox, point, prevLabel, prevLabelId,
- adjustEnd = me.adjustEnd,
- hasLeft = axes.findIndex('position', 'left') != -1,
- hasRight = axes.findIndex('position', 'right') != -1,
- textLabel, text,
- last, x, y, i, firstLabel;
- last = ln - 1;
- //get a reference to the first text label dimensions
- point = inflections[0];
- firstLabel = me.getOrCreateLabel(0, me.label.renderer(labels[0]));
- ratio = Math.floor(Math.abs(Math.sin(labelConf.rotate && (labelConf.rotate.degrees * Math.PI / 180) || 0)));
- for (i = 0; i < ln; i++) {
- point = inflections[i];
- text = me.label.renderer(labels[i]);
- textLabel = me.getOrCreateLabel(i, text);
- bbox = textLabel._bbox;
- maxHeight = max(maxHeight, bbox.height + me.dashSize + me.label.padding);
- x = floor(point[0] - (ratio ? bbox.height : bbox.width) / 2);
- if (adjustEnd && me.chart.maxGutter[0] == 0) {
- if (i == 0 && !hasLeft) {
- x = point[0];
- }
- else if (i == last && !hasRight) {
- x = Math.min(x, point[0] - bbox.width + insetPadding);
- }
- }
- if (position == 'top') {
- y = point[1] - (me.dashSize * 2) - me.label.padding - (bbox.height / 2);
- }
- else {
- y = point[1] + (me.dashSize * 2) + me.label.padding + (bbox.height / 2);
- }
- textLabel.setAttributes({
- hidden: false,
- x: x,
- y: y
- }, true);
- // Skip label if there isn't available minimum space
- if (i != 0 && (me.intersect(textLabel, prevLabel)
- || me.intersect(textLabel, firstLabel))) {
- if (i === last && prevLabelId !== 0) {
- prevLabel.hide(true);
- } else {
- textLabel.hide(true);
- continue;
- }
- }
- prevLabel = textLabel;
- prevLabelId = i;
- }
- return maxHeight;
- },
- drawVerticalLabels: function () {
- var me = this,
- inflections = me.inflections,
- position = me.position,
- ln = inflections.length,
- chart = me.chart,
- insetPadding = chart.insetPadding,
- labels = me.labels,
- maxWidth = 0,
- max = Math.max,
- floor = Math.floor,
- ceil = Math.ceil,
- axes = me.chart.axes,
- gutterY = me.chart.maxGutter[1],
- bbox, point, prevLabel, prevLabelId,
- hasTop = axes.findIndex('position', 'top') != -1,
- hasBottom = axes.findIndex('position', 'bottom') != -1,
- adjustEnd = me.adjustEnd,
- textLabel, text,
- last = ln - 1, x, y, i;
- for (i = 0; i < ln; i++) {
- point = inflections[i];
- text = me.label.renderer(labels[i]);
- textLabel = me.getOrCreateLabel(i, text);
- bbox = textLabel._bbox;
- maxWidth = max(maxWidth, bbox.width + me.dashSize + me.label.padding);
- y = point[1];
- if (adjustEnd && gutterY < bbox.height / 2) {
- if (i == last && !hasTop) {
- y = Math.max(y, me.y - me.length + ceil(bbox.height / 2) - insetPadding);
- }
- else if (i == 0 && !hasBottom) {
- y = me.y + gutterY - floor(bbox.height / 2);
- }
- }
- if (position == 'left') {
- x = point[0] - bbox.width - me.dashSize - me.label.padding - 2;
- }
- else {
- x = point[0] + me.dashSize + me.label.padding + 2;
- }
- textLabel.setAttributes(Ext.apply({
- hidden: false,
- x: x,
- y: y
- }, me.label), true);
- // Skip label if there isn't available minimum space
- if (i != 0 && me.intersect(textLabel, prevLabel)) {
- if (i === last && prevLabelId !== 0) {
- prevLabel.hide(true);
- } else {
- textLabel.hide(true);
- continue;
- }
- }
- prevLabel = textLabel;
- prevLabelId = i;
- }
- return maxWidth;
- },
- <span id='Ext-chart-axis-Axis-method-drawLabel'> /**
- </span> * Renders the labels in the axes.
- */
- drawLabel: function () {
- var me = this,
- position = me.position,
- labelGroup = me.labelGroup,
- inflections = me.inflections,
- maxWidth = 0,
- maxHeight = 0,
- ln, i;
- if (position == 'left' || position == 'right') {
- maxWidth = me.drawVerticalLabels();
- } else {
- maxHeight = me.drawHorizontalLabels();
- }
- // Hide unused bars
- ln = labelGroup.getCount();
- i = inflections.length;
- for (; i < ln; i++) {
- labelGroup.getAt(i).hide(true);
- }
- me.bbox = {};
- Ext.apply(me.bbox, me.axisBBox);
- me.bbox.height = maxHeight;
- me.bbox.width = maxWidth;
- if (Ext.isString(me.title)) {
- me.drawTitle(maxWidth, maxHeight);
- }
- },
- <span id='Ext-chart-axis-Axis-method-setTitle'> /**
- </span> * Updates the {@link #title} of this axis.
- * @param {String} title
- */
- setTitle: function (title) {
- this.title = title;
- this.drawLabel();
- },
- // @private draws the title for the axis.
- drawTitle: function (maxWidth, maxHeight) {
- var me = this,
- position = me.position,
- surface = me.chart.surface,
- displaySprite = me.displaySprite,
- title = me.title,
- rotate = (position == 'left' || position == 'right'),
- x = me.x,
- y = me.y,
- base, bbox, pad;
- if (displaySprite) {
- displaySprite.setAttributes({text: title}, true);
- } else {
- base = {
- type: 'text',
- x: 0,
- y: 0,
- text: title
- };
- displaySprite = me.displaySprite = surface.add(Ext.apply(base, me.axisTitleStyle, me.labelTitle));
- surface.renderItem(displaySprite);
- }
- bbox = displaySprite.getBBox();
- pad = me.dashSize + me.label.padding;
- if (rotate) {
- y -= ((me.length / 2) - (bbox.height / 2));
- if (position == 'left') {
- x -= (maxWidth + pad + (bbox.width / 2));
- }
- else {
- x += (maxWidth + pad + bbox.width - (bbox.width / 2));
- }
- me.bbox.width += bbox.width + 10;
- }
- else {
- x += (me.length / 2) - (bbox.width * 0.5);
- if (position == 'top') {
- y -= (maxHeight + pad + (bbox.height * 0.3));
- }
- else {
- y += (maxHeight + pad + (bbox.height * 0.8));
- }
- me.bbox.height += bbox.height + 10;
- }
- displaySprite.setAttributes({
- translate: {
- x: x,
- y: y
- }
- }, true);
- }
- });
- </pre>
- </body>
- </html>
|