UNPKG

@syncfusion/ej2-charts

Version:

Feature-rich chart control with built-in support for over 25 chart types, technical indictors, trendline, zooming, tooltip, selection, crosshair and trackball.

929 lines 74.7 kB
var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { Property, Complex, ChildProperty, extend, getValue } from '@syncfusion/ej2-base'; import { measureText, Rect, TextOption, Size, PathOption } from '@syncfusion/ej2-svg-base'; import { Font, Border, Margin, Location, ContainerPadding, Accessibility } from '../model/base'; import { subtractThickness, Thickness, drawSymbol, ChartLocation, titlePositionX, getTitle, textTrim, getTextAnchor } from '../utils/helper'; import { RectOption, textElement, stringToNumber } from '../utils/helper'; import { removeElement, showTooltip, getElement, appendChildElement } from '../utils/helper'; /** * Configures the appearance and behavior of legends in charts. */ var LegendSettings = /** @class */ (function (_super) { __extends(LegendSettings, _super); function LegendSettings() { return _super !== null && _super.apply(this, arguments) || this; } __decorate([ Property(true) ], LegendSettings.prototype, "visible", void 0); __decorate([ Property(null) ], LegendSettings.prototype, "height", void 0); __decorate([ Property(null) ], LegendSettings.prototype, "width", void 0); __decorate([ Complex({ x: 0, y: 0 }, Location) ], LegendSettings.prototype, "location", void 0); __decorate([ Property('Auto') ], LegendSettings.prototype, "position", void 0); __decorate([ Property('Series') ], LegendSettings.prototype, "mode", void 0); __decorate([ Property(8) ], LegendSettings.prototype, "padding", void 0); __decorate([ Property(null) ], LegendSettings.prototype, "itemPadding", void 0); __decorate([ Property('Center') ], LegendSettings.prototype, "alignment", void 0); __decorate([ Complex({ fontFamily: null, size: null, fontStyle: null, fontWeight: null, color: null }, Font) ], LegendSettings.prototype, "textStyle", void 0); __decorate([ Property(10) ], LegendSettings.prototype, "shapeHeight", void 0); __decorate([ Property(10) ], LegendSettings.prototype, "shapeWidth", void 0); __decorate([ Complex({}, Border) ], LegendSettings.prototype, "border", void 0); __decorate([ Complex({ left: 0, right: 0, top: 0, bottom: 0 }, Margin) ], LegendSettings.prototype, "margin", void 0); __decorate([ Complex({ left: 0, right: 0, top: 0, bottom: 0 }, ContainerPadding) ], LegendSettings.prototype, "containerPadding", void 0); __decorate([ Property(8) ], LegendSettings.prototype, "shapePadding", void 0); __decorate([ Property('transparent') ], LegendSettings.prototype, "background", void 0); __decorate([ Property(1) ], LegendSettings.prototype, "opacity", void 0); __decorate([ Property(true) ], LegendSettings.prototype, "toggleVisibility", void 0); __decorate([ Property(false) ], LegendSettings.prototype, "enableHighlight", void 0); __decorate([ Property(null) ], LegendSettings.prototype, "description", void 0); __decorate([ Property(3) ], LegendSettings.prototype, "tabIndex", void 0); __decorate([ Property(null) ], LegendSettings.prototype, "title", void 0); __decorate([ Complex({ fontFamily: null, size: null, fontStyle: null, fontWeight: null, color: null }, Font) ], LegendSettings.prototype, "titleStyle", void 0); __decorate([ Property('Top') ], LegendSettings.prototype, "titlePosition", void 0); __decorate([ Property('Normal') ], LegendSettings.prototype, "textWrap", void 0); __decorate([ Property('Ellipsis') ], LegendSettings.prototype, "textOverflow", void 0); __decorate([ Property(100) ], LegendSettings.prototype, "maximumTitleWidth", void 0); __decorate([ Property(null) ], LegendSettings.prototype, "maximumLabelWidth", void 0); __decorate([ Property(true) ], LegendSettings.prototype, "enablePages", void 0); __decorate([ Property(false) ], LegendSettings.prototype, "isInversed", void 0); __decorate([ Property(false) ], LegendSettings.prototype, "reverse", void 0); __decorate([ Property('Auto') ], LegendSettings.prototype, "layout", void 0); __decorate([ Property(null) ], LegendSettings.prototype, "maximumColumns", void 0); __decorate([ Property(false) ], LegendSettings.prototype, "fixedWidth", void 0); __decorate([ Complex({}, Accessibility) ], LegendSettings.prototype, "accessibility", void 0); return LegendSettings; }(ChildProperty)); export { LegendSettings }; /** * Legend base class for Chart and Accumulation chart. * * @private */ var BaseLegend = /** @class */ (function () { /** * Constructor for the dateTime module. * * @private */ function BaseLegend(chart) { this.maxItemHeight = 0; this.rowHeights = []; this.pageHeights = []; this.columnHeights = []; this.pageXCollections = []; // pages of x locations this.chartRowCount = 1; this.legendTitleCollections = []; this.legendRegions = []; this.pagingRegions = []; this.chart = chart; this.legend = chart.legendSettings; this.legendID = chart.element.id + '_chart_legend'; this.isChartControl = (chart.getModuleName() === 'chart' || chart.getModuleName() === 'chart3d'); this.isAccChartControl = (chart.getModuleName() === 'accumulationchart' || chart.getModuleName() === 'circularchart3d'); this.isBulletChartControl = (chart.getModuleName() === 'bulletChart'); this.isStockChartControl = (chart.getModuleName() === 'stockChart'); this.bulletChart = this.chart; this.fivePixel = 5; this.rowCount = 0; this.pageButtonSize = 8; this.maxColumns = 0; this.maxWidth = 0; this.currentPage = 1; this.backwardArrowOpacity = 0; this.forwardArrowOpacity = 1; this.arrowWidth = (2 * (this.fivePixel + this.pageButtonSize + this.fivePixel)); this.arrowHeight = this.arrowWidth; this.isTop = false; this.isTitle = false; this.currentPageNumber = 1; } /** * Calculate the bounds for the legends. * * @returns {void} * @private */ BaseLegend.prototype.calculateLegendBounds = function (rect, availableSize, maxLabelSize, previousLegendBounds, pointAnimation) { var legend = this.legend; var defaultValue = (this.isBulletChartControl || ((this.chart.getModuleName() === 'accumulationchart' || this.chart.getModuleName() === 'chart') && (this.legend.layout !== 'Auto' || this.legend.maximumColumns > 0))) ? '40%' : '20%'; this.getPosition(legend.position, availableSize); this.legendBounds = new Rect(rect.x, rect.y, 0, 0); this.isVertical = (this.position === 'Left' || this.position === 'Right'); this.itemPadding = this.legend.itemPadding ? this.legend.itemPadding : this.isVertical ? 8 : 20; if (this.isVertical) { this.legendBounds.height = stringToNumber(legend.height, availableSize.height - (rect.y - this.chart.margin.top)) || rect.height; this.legendBounds.width = stringToNumber(legend.width || defaultValue, availableSize.width); } else { this.legendBounds.width = stringToNumber(legend.width, availableSize.width) || rect.width; this.legendBounds.height = stringToNumber(legend.height || defaultValue, availableSize.height); } if (this.chart.getModuleName() === 'chart3d') { this.library.get3DLegendBounds(availableSize, this.legendBounds, legend); } else { this.library.getLegendBounds(availableSize, this.legendBounds, legend); } if (!this.isBulletChartControl) { this.legendBounds.width += (this.legend.containerPadding.left + this.legend.containerPadding.right); this.legendBounds.height += (this.legend.containerPadding.top + this.legend.containerPadding.bottom); } this.getLocation(this.position, legend.alignment, this.legendBounds, rect, availableSize, maxLabelSize, previousLegendBounds, pointAnimation); }; /** * To find legend position based on available size for chart and accumulation chart * * @param position * @param availableSize * @param position * @param availableSize * @returns {void} */ BaseLegend.prototype.getPosition = function (position, availableSize) { var chart = this.chart; var accumulation = this.chart; if (this.isChartControl || this.isBulletChartControl || this.isStockChartControl) { this.position = (position !== 'Auto') ? position : 'Bottom'; } else { if (position === 'Auto' && ((chart || accumulation).visibleSeries && (chart || accumulation).visibleSeries[0].type === 'Funnel' || (chart || accumulation).visibleSeries[0].type === 'Pyramid')) { position = 'Top'; } this.position = (position !== 'Auto') ? position : (availableSize.width > availableSize.height ? 'Right' : 'Bottom'); } }; /** * To set bounds for chart and accumulation chart * * @param computedWidth * @param computedHeight * @param legend * @param legendBounds * @param computedWidth * @param computedHeight * @param legend * @param legendBounds * @param computedWidth * @param computedHeight * @param legend * @param legendBounds * @param computedWidth * @param computedHeight * @param legend * @param legendBounds * @returns {void} */ BaseLegend.prototype.setBounds = function (computedWidth, computedHeight, legend, legendBounds) { var titleHeight = legend.title && legend.titlePosition === 'Top' ? this.legendTitleSize.height + this.fivePixel : 0; if (this.isVertical && this.isPaging && !legend.enablePages && !this.isBulletChartControl) { titleHeight = legend.title && legend.titlePosition === 'Top' ? this.legendTitleSize.height + this.fivePixel : 0; titleHeight += (this.pageButtonSize + this.fivePixel); } computedWidth = Math.min(computedWidth, legendBounds.width); computedHeight = Math.min(computedHeight, legendBounds.height); if (legend.mode === 'Gradient') { legendBounds.width = legend.width ? legendBounds.width : this.isVertical ? computedWidth : 0.75 * legendBounds.width; legendBounds.height = legend.height ? legendBounds.height : this.isVertical ? 0.75 * legendBounds.height : computedHeight; } else { legendBounds.width = !legend.width ? computedWidth : legendBounds.width; legendBounds.height = !legend.height ? computedHeight : legendBounds.height; } if (!this.isBulletChartControl) { if (this.isTop && legend.titleStyle.textOverflow !== 'None') { this.calculateLegendTitle(legend, legendBounds); legendBounds.height += legend.titleStyle.textOverflow === 'Wrap' && this.legendTitleCollections.length > 1 ? (this.legendTitleSize.height - (this.legendTitleSize.height / this.legendTitleCollections.length)) : 0; } } this.rowCount = Math.max(1, Math.ceil((legendBounds.height - legend.padding - titleHeight) / (this.maxItemHeight + legend.padding))); }; /** * To find legend location based on position, alignment for chart and accumulation chart * * @param position * @param alignment * @param legendBounds * @param rect * @param availableSize * @param maxLabelSize * @param position * @param alignment * @param legendBounds * @param rect * @param availableSize * @param maxLabelSize * @param position * @param alignment * @param legendBounds * @param rect * @param availableSize * @param maxLabelSize * @param position * @param alignment * @param legendBounds * @param rect * @param availableSize * @param maxLabelSize * @param position * @param alignment * @param legendBounds * @param rect * @param availableSize * @param maxLabelSize * @param position * @param alignment * @param legendBounds * @param rect * @param availableSize * @param maxLabelSize */ BaseLegend.prototype.getLocation = function (position, alignment, legendBounds, rect, availableSize, maxLabelSize, previousLegendBounds, pointAnimation) { var padding = this.legend.border.width; var isBulletChart = this.isBulletChartControl; var bulletChart = this.bulletChart; var labelIns = bulletChart.labelPosition === 'Inside'; var ticklIns = bulletChart.tickPosition === 'Inside'; var isVertical = bulletChart.orientation === 'Vertical'; var categoryFieldValue = (isBulletChart && bulletChart.categoryField !== '') ? maxLabelSize.width + this.chart.border.width + padding * 3 : 0; var marginBottom = this.chart.margin.bottom; var legendHeight = legendBounds.height + padding + this.legend.margin.top + this.legend.margin.bottom; var legendWidth = legendBounds.width + padding + this.legend.margin.left + this.legend.margin.right; if (position === 'Bottom') { legendBounds.x = this.alignLegend(legendBounds.x, availableSize.width, legendBounds.width, alignment); legendBounds.y = (previousLegendBounds && (legendBounds.height === previousLegendBounds.height || this.chart.series[0].type !== 'Pie')) ? previousLegendBounds.y : rect.y + (rect.height - legendHeight) + padding + this.legend.margin.top; legendBounds.y += (isBulletChart && !bulletChart.opposedPosition && !labelIns && !ticklIns && !isVertical) ? bulletChart.majorTickLines.height + marginBottom + this.legend.border.width + padding * 2 : (isVertical && bulletChart.categoryField !== '') ? maxLabelSize.height + padding * 2 : 0; if ((!pointAnimation || (legendBounds.height !== previousLegendBounds.height))) { { subtractThickness(rect, new Thickness(0, 0, 0, legendHeight)); } } } else if (position === 'Top') { var axisTextSize = void 0; if (this.isChartControl) { axisTextSize = measureText('100', this.chart.verticalAxes[0].labelStyle, this.chart.themeStyle.legendLabelFont); } legendBounds.x = this.alignLegend(legendBounds.x, availableSize.width, legendBounds.width, alignment); legendBounds.y = (previousLegendBounds && (legendBounds.height === previousLegendBounds.height || this.chart.series[0].type !== 'Pie')) ? previousLegendBounds.y : rect.y + padding + this.legend.margin.top; legendBounds.y -= (isBulletChart && bulletChart.opposedPosition && !labelIns && !ticklIns && !isVertical) ? bulletChart.majorTickLines.height + this.chart.margin.top : 0; legendHeight -= (isBulletChart) ? -padding * 2 : (this.isChartControl ? -padding * 2 - axisTextSize.height / 2 : 0); if (!pointAnimation || (legendBounds.height !== previousLegendBounds.height)) { subtractThickness(rect, new Thickness(0, 0, legendHeight, 0)); } } else if (position === 'Right') { legendBounds.x = (previousLegendBounds && (legendBounds.width === previousLegendBounds.width || this.chart.series[0].type !== 'Pie')) ? previousLegendBounds.x : rect.x + (rect.width - legendBounds.width) - this.legend.margin.right; legendBounds.y = rect.y + this.alignLegend(0, availableSize.height - (rect.y + marginBottom), legendBounds.height, alignment); legendWidth += (isBulletChart && bulletChart.opposedPosition && !labelIns && !ticklIns && isVertical) ? (this.chart.margin.left + this.chart.margin.right + bulletChart.majorTickLines.height) : 0; if (!pointAnimation || (legendBounds.width !== previousLegendBounds.width)) { subtractThickness(rect, new Thickness(0, legendWidth, 0, 0)); } } else if (position === 'Left') { legendBounds.x = (previousLegendBounds && (legendBounds.width === previousLegendBounds.width || this.chart.series[0].type !== 'Pie')) ? previousLegendBounds.x : legendBounds.x + this.legend.margin.left; legendBounds.y = rect.y + this.alignLegend(0, availableSize.height - (rect.y + marginBottom), legendBounds.height, alignment); legendWidth += (isBulletChart && !bulletChart.opposedPosition && !labelIns && !ticklIns && isVertical) ? (legendBounds.x - this.chart.margin.left + padding + bulletChart.majorTickLines.height) : (bulletChart.orientation !== 'Vertical' && bulletChart.categoryField !== '') ? categoryFieldValue : 0; if (!pointAnimation || (legendBounds.width !== previousLegendBounds.width)) { subtractThickness(rect, new Thickness(legendWidth, 0, 0, 0)); } } else { legendBounds.x = this.legend.location.x; legendBounds.y = this.legend.location.y; subtractThickness(rect, new Thickness(0, 0, 0, 0)); } }; /** * To find legend alignment for chart and accumulation chart * * @param start * @param size * @param legendSize * @param alignment * @param start * @param size * @param legendSize * @param alignment * @param start * @param size * @param legendSize * @param alignment * @param start * @param size * @param legendSize * @param alignment */ BaseLegend.prototype.alignLegend = function (start, size, legendSize, alignment) { switch (alignment) { case 'Far': start = (size - legendSize) - start; break; case 'Center': start = ((size - legendSize) / 2); break; } return start; }; /** * Renders the legend. * * @param chart * @param legend * @param legendBounds * @param redraw * @param chart * @param legend * @param legendBounds * @param redraw * @param chart * @param legend * @param legendBounds * @param redraw * @param chart * @param legend * @param legendBounds * @param redraw * @returns {void} * @private */ BaseLegend.prototype.renderLegend = function (chart, legend, legendBounds, redraw, pointAnimation) { var titleHeight = 0; var titlePlusArrowWidth = 0; var pagingLegendBounds = new Rect(0, 0, 0, 0); var requireLegendBounds = new Rect(0, 0, 0, 0); var xValue; var yValue; if (pointAnimation) { xValue = getElement(this.legendID + '_element').getAttribute('x'); yValue = getElement(this.legendID + '_element').getAttribute('y'); } var firstLegend = this.findFirstLegendPosition(this.legendCollections); var padding = legend.padding; this.itemPadding = this.isBulletChartControl ? legend.padding : this.itemPadding; var isPaging = legend.enablePages; var titlePosition = legend.titlePosition; var upArrowHeight = this.isPaging && !legend.enablePages && this.isVertical && ((chart.getModuleName() !== 'accumulationchart' && chart.getModuleName() !== 'chart') || this.legend.layout === 'Auto') ? this.pageButtonSize : 0; var legendGroup = chart.renderer.createGroup({ id: this.legendID + '_g' }); var legendTranslateGroup = this.createLegendElements(chart, legendBounds, legendGroup, legend, this.legendID, redraw); this.legendRegions = []; this.chartRowCount = 1; var maxHeight = 0; titleHeight = !this.isTitle ? 0 : (this.isTop || this.isVertical ? this.legendTitleSize.height : 0); if (this.isChartControl || (this.isAccChartControl && (!this.isVertical || (legend.layout && legend.layout !== 'Auto')))) { var pageCount = 1; var rowHeights = this.rowHeights[0] + ((this.isVertical || (this.rowHeights.length > 1 && this.legend.itemPadding && this.chart.getModuleName() === 'chart')) ? this.itemPadding : padding); for (var i = 1; i < this.rowHeights.length; i++) { if ((rowHeights + this.rowHeights[i] + (((this.isVertical || (this.rowHeights.length > 1 && this.chart.getModuleName() === 'chart')) && this.legend.itemPadding) ? this.itemPadding : padding)) > (this.legendBounds.height - this.pageButtonSize - this.maxItemHeight / 2) - this.legend.containerPadding.top - this.legend.containerPadding.bottom) { this.pageHeights[pageCount - 1] = rowHeights + titleHeight; pageCount++; rowHeights = 0; } rowHeights += (this.rowHeights[i] + ((this.isVertical || (this.rowHeights.length > 1 && this.legend.itemPadding && this.chart.getModuleName() === 'chart')) ? this.itemPadding : padding)); } this.pageHeights[pageCount - 1] = rowHeights + titleHeight; this.totalPages = pageCount; } for (var i = 0; i < this.legendCollections.length; i++) { if (this.legendCollections[i].text !== '') { maxHeight = Math.max(this.legendCollections[i].textSize.height, maxHeight); break; } else { continue; } } if (!this.isChartControl && !this.isAccChartControl) { this.maxItemHeight = Math.max(maxHeight, legend.shapeHeight); } // For new legend navigation if (!isPaging && this.isPaging && !this.isVertical) { titlePlusArrowWidth = !this.isTitle ? 0 : titlePosition === 'Left' ? this.legendTitleSize.width : 0; titlePlusArrowWidth += (this.pageButtonSize + (2 * this.fivePixel)); } else if (this.isTitle && !this.isVertical) { titlePlusArrowWidth = titlePosition === ((!this.isRtlEnable) ? 'Left' : 'Right') ? (this.fivePixel + this.legendTitleSize.width) : 0; } if (chart.legendSettings.mode === 'Gradient' && this.legendCollections.length > 1) { this.getLinearLegend(legendBounds, chart, legend, legendTranslateGroup); this.totalPages = 1; } else if (firstLegend !== this.legendCollections.length) { var legendSeriesGroup = void 0; // legendItem group for each series group element var count = 0; var previousLegend = this.legendCollections[firstLegend]; // starting shape center x,y position && to resolve lint error used new line for declaration var startPadding = this.isBulletChartControl ? padding : titlePlusArrowWidth + padding + (legend.shapeWidth / 2) + legend.containerPadding.left; var xLocation = (this.isBulletChartControl && !this.isRtlEnable) ? legendBounds.x + titlePlusArrowWidth + padding + (legend.shapeWidth / 2) : (!this.isRtlEnable) ? legendBounds.x + startPadding : legendBounds.x + ((this.chart.getModuleName() === 'accumulationchart' && this.isVertical && legend.layout === 'Auto' && !(legend.maximumColumns > 0)) ? this.maxWidth : legendBounds.width) - startPadding; var start = new ChartLocation(xLocation, this.isBulletChartControl ? legendBounds.y + titleHeight + upArrowHeight + padding + (this.maxItemHeight / 2) : legendBounds.y + titleHeight + upArrowHeight + padding + (this.maxItemHeight / 2) + legend.containerPadding.top); var anchor = chart.isRtlEnabled || chart.enableRtl ? 'end' : 'start'; var textOptions = new TextOption('', start.x, start.y, anchor); var textPadding = legend.shapePadding + this.itemPadding + legend.shapeWidth; // initialization for totalPages legend click totalpage again calculate this.totalPages = this.totalPages = (this.isAccChartControl || this.isChartControl || this.isBulletChartControl || this.isStockChartControl) ? this.totalPages : 0; this.pageXCollections = []; this.legendCollections[firstLegend].location = start; var legendIndex = void 0; if (!legend.enablePages && this.isPaging) { var x = start.x - this.fivePixel; var y = start.y - this.fivePixel; var leftSpace = this.isTitle && !this.isVertical && titlePosition === 'Left' ? this.legendTitleSize.width + this.fivePixel : 0; var bottomSapce = this.isVertical ? (this.pageButtonSize) + Math.abs(y - legendBounds.y) : 0; var rightSpace = this.isTitle && !this.isVertical && titlePosition === 'Right' ? this.legendTitleSize.width + this.fivePixel : 0; rightSpace += this.isVertical ? 0 : (this.fivePixel + this.pageButtonSize + this.fivePixel); pagingLegendBounds = new Rect(x, y, legendBounds.width - rightSpace - leftSpace, legendBounds.height - bottomSapce); requireLegendBounds = pagingLegendBounds; } else { requireLegendBounds = legendBounds; } var legendOption = void 0; for (var i = 0; i < this.legendCollections.length; i++) { legendOption = this.legendCollections[i]; legendIndex = !this.isReverse ? count : (this.legendCollections.length - 1) - count; if (this.chart.getModuleName() === 'accumulationchart' && this.chart.accumulationLegendModule.legendRenderArgFill.indexOf(i) === -1) { legendOption.fill = (this.chart || this.chart || this.chart || this.chart).visibleSeries[0].points[legendOption.pointIndex].color; } if (this.chart.getModuleName() === 'stockChart') { legendOption.type = this.chart.visibleSeries[count].type; } this.accessbilityText = (this.isBulletChartControl) ? 'Legend of bullet chart' + '' + legendOption.text : 'Click to show or hide the ' + legendOption.text + ' series'; if (legendOption.render && legendOption.text && legendOption.text !== '') { legendSeriesGroup = chart.renderer.createGroup({ id: this.legendID + this.generateId(legendOption, '_g_', legendIndex) }); if (legendSeriesGroup && (this.chart.getModuleName() === 'chart' || this.chart.getModuleName() === 'accumulationchart')) { legendSeriesGroup.setAttribute('tabindex', (i === 0 && legend.accessibility.focusable) ? String(legend.accessibility.tabIndex) : ''); legendSeriesGroup.style.outline = 'none'; legendSeriesGroup.setAttribute('aria-label', legend.accessibility.accessibilityDescription ? legend.accessibility.accessibilityDescription : (legendOption.text + ' series is ' + (legendOption.visible ? 'showing, press enter to hide the ' : 'hidden, press enter to show the ') + legendOption.text + ' series')); legendSeriesGroup.setAttribute('role', legend.accessibility.accessibilityRole ? legend.accessibility.accessibilityRole : 'button'); legendSeriesGroup.setAttribute('aria-pressed', legendOption.visible ? 'true' : 'false'); } else if (legendSeriesGroup) { legendSeriesGroup.setAttribute('tabindex', i === 0 ? '0' : ''); legendSeriesGroup.style.outline = 'none'; legendSeriesGroup.setAttribute('aria-label', legend.description || (legendOption.text + ' series is ' + (legendOption.visible ? 'showing, press enter to hide the ' : 'hidden, press enter to show the ') + legendOption.text + ' series')); legendSeriesGroup.setAttribute('role', 'button'); legendSeriesGroup.setAttribute('aria-pressed', legendOption.visible ? 'true' : 'false'); } this.library.getRenderPoint(legendOption, start, textPadding, previousLegend, requireLegendBounds, count, firstLegend); this.renderSymbol(legendOption, legendSeriesGroup, legendIndex); this.renderText(chart, legendOption, legendSeriesGroup, textOptions, count, legendIndex); if (legendSeriesGroup) { legendSeriesGroup.style.cssText = 'pointer-events: bounding-box; cursor: ' + ((!legend.toggleVisibility && (chart.selectionMode === 'None' || chart.highlightMode === 'None' || chart.selectionMode === 'None') || this.isBulletChartControl) ? 'auto' : 'pointer'); } if (legendTranslateGroup) { legendTranslateGroup.appendChild(legendSeriesGroup); } previousLegend = legendOption; } count++; } this.totalPages = (this.isPaging && !this.isBulletChartControl && !this.legend.enablePages && !this.isVertical && this.totalPages > this.chartRowCount) ? this.chartRowCount : this.totalPages; this.currentPage = this.currentPage > 1 && this.currentPage > this.totalPages ? this.totalPages : this.currentPage; if (this.isPaging && this.totalPages > 1) { this.renderPagingElements(chart, legendBounds, textOptions, legendGroup); } else { this.totalPages = 1; } } if (pointAnimation) { var translateX = "translate(" + (this.rowCount > 1 ? 0 : Math.round(Number(xValue)) - Math.round(this.legendBounds.x)) + " \n + ',' + " + (Math.round(Number(yValue)) - Math.round(this.legendBounds.y)) + ")"; var translateY = "translate(" + (Math.round(Number(xValue)) - Math.round(this.legendBounds.x)) + ", " + (Math.round(Number(yValue)) - Math.round(this.legendBounds.y)) + ")"; appendChildElement(chart.enableCanvas, chart.svgObject, legendGroup, redraw, true, 'x', 'y', undefined, undefined, undefined, undefined, undefined, chart.duration, undefined, undefined, new ChartLocation(0, 0), this.position === 'Top' || this.position === 'Bottom' ? translateX : translateY); } else { appendChildElement(chart.enableCanvas, chart.svgObject, legendGroup, redraw); } }; /** * To get linear legend. * * @param {Rect} legendBounds - The bounds of the legend. * @param {Chart | AccumulationChart | BulletChart | StockChart | Chart3D | CircularChart3D} chart - The chart instance. * @param {LegendSettingsModel} legend - The legend settings. * @param {Element} legendTranslateGroup - The group element to translate the legend. * @returns {void} * @private */ BaseLegend.prototype.getLinearLegend = function (legendBounds, chart, legend, legendTranslateGroup) { var xmlns = 'http://www.w3.org/2000/svg'; var previousLegend = this.legendCollections[0]; var nextLegend = this.legendCollections[1]; var defElement = this.chart.renderer.createDefs(); var gradientLegendCount = 0; var linerGradientEle = document.createElementNS(xmlns, 'linearGradient'); var opacity = 1; var fillColors = []; var numberItems = []; if (legend.title) { if (!this.isVertical) { if (legend.titlePosition === 'Left') { legendBounds.x += this.legendTitleSize.width; legendBounds.width -= this.legendTitleSize.width; } else if (legend.titlePosition === 'Right') { legendBounds.width -= this.legendTitleSize.width; } else if (legend.titlePosition === 'Top') { legendBounds.y += this.legendTitleSize.height; legendBounds.height -= this.legendTitleSize.height; } } else { legendBounds.y += this.legendTitleSize.height; legendBounds.height -= this.legendTitleSize.height; } } for (var _i = 0, _a = this.chart.rangeColorSettings; _i < _a.length; _i++) { var colorMap = _a[_i]; if (numberItems.indexOf(colorMap.start) < 0) { numberItems.push(colorMap.start); } if (colorMap.colors.length > 2) { var diffValue = (colorMap.end - colorMap.start); var colorsLength = colorMap.colors.length - 1; if (diffValue > 0) { diffValue = diffValue / colorsLength; for (var index = 1; index < colorsLength; index++) { var calculatedValue = colorMap.start + (diffValue * index); numberItems.push(calculatedValue); } } else { for (var index = 1; index < colorsLength; index++) { numberItems.push(colorMap.start); } } } if (numberItems.indexOf(colorMap.end) < 0) { numberItems.push(colorMap.end); } for (var _b = 0, _c = colorMap.colors; _b < _c.length; _b++) { var fillColor = _c[_b]; if (fillColors.indexOf(fillColor) < 0) { fillColors.push(fillColor); } } if (colorMap.colors.length > 0 && colorMap.colors.length < 2) { fillColors.push(colorMap.colors[0]); } } var x1 = this.isRtlEnable && !this.isVertical ? '100%' : '0%'; var x2 = this.isVertical || this.isRtlEnable ? '0%' : '100%'; var y2 = this.isVertical ? '100%' : '0%'; linerGradientEle.setAttribute('id', this.generateId(previousLegend, 'linearGradient', gradientLegendCount)); linerGradientEle.setAttribute('x1', x1); linerGradientEle.setAttribute('y1', '0%'); linerGradientEle.setAttribute('x2', x2); linerGradientEle.setAttribute('y2', y2); var full = numberItems[numberItems.length - 1] - numberItems[0]; for (var b = 0; b < fillColors.length; b++) { var offsetValue = numberItems[b] - numberItems[0]; offsetValue = offsetValue / full; var stopEle = document.createElementNS(xmlns, 'stop'); stopEle.setAttribute('offset', offsetValue.toString()); stopEle.setAttribute('stop-color', fillColors[b]); stopEle.setAttribute('stop-opacity', opacity.toString()); linerGradientEle.appendChild(stopEle); } var startLabel = previousLegend.text.toString(); var endLabel = nextLegend.text.toString(); var startTextSize = measureText(startLabel, legend.textStyle, this.chart.themeStyle.legendLabelFont); var endTextSize = measureText(endLabel, legend.textStyle, this.chart.themeStyle.legendLabelFont); var textWidth = startTextSize.width > endTextSize.width ? startTextSize.width : endTextSize.width; var textHeight = startTextSize.height > endTextSize.height ? startTextSize.height : endTextSize.height; var otherSpaces = (2 * textWidth) + (4 * legend.padding); var linearBarWidth = legendBounds.width; var linearBarHeight = legendBounds.height; var xValue = legendBounds.x + textWidth + (2 * legend.padding); var yValue = legendBounds.y + legend.padding; var startLabelY; var endLabelY; var startLabelX; var endLabelX; if (this.isVertical) { otherSpaces = (2 * textHeight) + (4 * legend.padding); linearBarWidth = legendBounds.width - (2 * legend.padding); linearBarHeight = legendBounds.height - otherSpaces; xValue = legendBounds.x + legend.padding; yValue = legendBounds.y + textHeight + (2 * legend.padding); startLabelY = legendBounds.y + legend.padding + textHeight; endLabelY = yValue + linearBarHeight + textHeight; startLabelX = (legendBounds.x + (legendBounds.width * 0.5)) - (textWidth * 0.5); endLabelX = startLabelX; if (linearBarWidth > 30) { var diffWidth = linearBarWidth - 30; linearBarWidth = 30; xValue = xValue + (diffWidth / 2); } } else { linearBarWidth = legendBounds.width - otherSpaces; linearBarHeight = legendBounds.height - (2 * legend.padding); startLabelX = legendBounds.x + ((!this.isRtlEnable) ? legend.padding + (textWidth - startTextSize.width) : linearBarWidth + (3 * legend.padding) + textWidth); endLabelX = legendBounds.x + ((!this.isRtlEnable) ? linearBarWidth + (3 * legend.padding) + textWidth : legend.padding + (textWidth - endTextSize.width)); startLabelY = legendBounds.y + (legendBounds.height * 0.5) + (textHeight * 0.25); endLabelY = startLabelY; if (linearBarHeight > 30) { var diffHeight = linearBarHeight - 30; linearBarHeight = 30; yValue = yValue + (diffHeight / 2); } } var anchor = chart.enableRtl ? 'end' : ''; var textOptions = new TextOption('', startLabelX, startLabelY, anchor, startLabel); var hiddenColor = '#D3D3D3'; textOptions.id = this.legendID + this.generateId(previousLegend, '_text_', 1); var fontcolor = previousLegend.visible ? legend.textStyle.color || chart.themeStyle.legendLabelFont.color : hiddenColor; var isCanvas = this.isStockChartControl ? false : this.chart.enableCanvas; textElement(chart.renderer, textOptions, legend.textStyle, fontcolor, legendTranslateGroup, false, false, false, false, null, this.currentPageNumber && isCanvas ? new Rect(0, -this.translatePage(isCanvas, null, this.currentPageNumber - 1, this.currentPageNumber), 0, 0) : null, null, null, null, null, this.chart.themeStyle.legendLabelFont); textOptions = new TextOption('', endLabelX, endLabelY, anchor, endLabel); textOptions.id = this.legendID + this.generateId(previousLegend, '_text_', 2); textElement(chart.renderer, textOptions, legend.textStyle, fontcolor, legendTranslateGroup, false, false, false, false, null, this.currentPageNumber && isCanvas ? new Rect(0, -this.translatePage(isCanvas, null, this.currentPageNumber - 1, this.currentPageNumber), 0, 0) : null, null, null, null, null, this.chart.themeStyle.legendLabelFont); var gradientLegend = chart.renderer.drawRectangle({ width: linearBarWidth, height: linearBarHeight, x: xValue, y: yValue, fill: 'url(#' + this.generateId(previousLegend, 'linearGradient', gradientLegendCount) + ')' }); defElement.appendChild(linerGradientEle); legendTranslateGroup.appendChild(defElement); legendTranslateGroup.appendChild(gradientLegend); }; /** * To find first valid legend text index for chart and accumulation chart * * @param legendCollection * @returns {number} * @private */ BaseLegend.prototype.findFirstLegendPosition = function (legendCollection) { var count = 0; for (var _i = 0, legendCollection_1 = legendCollection; _i < legendCollection_1.length; _i++) { var legend = legendCollection_1[_i]; if (legend.render && legend.text && legend.text !== '') { break; } count++; } return count; }; /** * To get the legend title text width and height. * * @param legend * @param legendBounds */ BaseLegend.prototype.calculateLegendTitle = function (legend, legendBounds) { if (legend.title) { this.isTop = legend.titlePosition === 'Top'; var padding = legend.titleStyle.textOverflow === 'Trim' ? 2 * legend.padding : 0; if (this.isTop || this.isVertical) { this.legendTitleCollections = getTitle(legend.title, legend.titleStyle, (legendBounds.width - padding), this.chart.enableRtl, this.chart.themeStyle.legendTitleFont); } else { this.legendTitleCollections[0] = textTrim(legend.maximumTitleWidth, legend.title, legend.titleStyle, this.chart.enableRtl, this.chart.themeStyle.legendTitleFont); } var text = this.isTop ? legend.title : this.legendTitleCollections[0]; this.legendTitleSize = measureText(text, legend.titleStyle, this.chart.themeStyle.legendTitleFont); this.legendTitleSize.height *= this.legendTitleCollections.length; } else { this.legendTitleSize = new Size(0, 0); } }; /** * Render the legend title * * @param chart * @param legend * @param legendBounds * @param legendGroup */ BaseLegend.prototype.renderLegendTitle = function (chart, legend, legendBounds, legendGroup) { var padding = legend.padding; var alignment = legend.titleStyle.textAlignment; this.isTop = legend.titlePosition === 'Top'; var anchor = getTextAnchor(legend.titleStyle.textAlignment, chart.enableRtl); var x = titlePositionX(legendBounds, legend.titleStyle); anchor = this.isTop || this.isVertical ? anchor : (chart.enableRtl) ? 'end' : ''; x = alignment === 'Near' ? (x + padding) : alignment === 'Far' ? (x - padding) : x; x = (this.isTop || this.isVertical) ? x : ((legendBounds.x) + (legend.titlePosition === 'Left' ? 5 : (legendBounds.width - this.legendTitleSize.width - 5))); var topPadding = (legendBounds.height / 2) + (this.legendTitleSize.height / 4); var y = legendBounds.y + (!this.isTop && !this.isVertical ? topPadding : (this.legendTitleSize.height / this.legendTitleCollections.length)); var legendTitleTextOptions = new TextOption(this.legendID + '_title', x, y, anchor, this.legendTitleCollections); textElement(chart.renderer, legendTitleTextOptions, legend.titleStyle, legend.titleStyle.color || this.chart.themeStyle.legendTitleFont.color, legendGroup, null, null, null, null, null, null, null, null, null, null, this.chart.themeStyle.legendTitleFont); }; /** * To create legend rendering elements for chart and accumulation chart * * @param chart * @param legendBounds * @param legendGroup * @param legend * @param id * @param redraw */ BaseLegend.prototype.createLegendElements = function (chart, legendBounds, legendGroup, legend, id, redraw) { var padding = legend.padding; var options = new RectOption(id + '_element', legend.background, legend.border, legend.opacity, legendBounds, 0, 0, '', this.legend.border.dashArray); var legendItemsGroup = chart.renderer.createGroup({ id: id + '_collections' }); var isCanvas = this.isStockChartControl ? false : chart.enableCanvas; var clippath = chart.renderer.createClipPath({ id: id + '_clipPath' }); options.width = (this.isRtlEnable && this.chart.getModuleName() === 'accumulationchart' && this.isVertical && legend.layout === 'Auto' && !(legend.maximumColumns > 0)) ? this.maxWidth : legendBounds.width; if (legendGroup) { legendGroup.appendChild(chart.renderer.drawRectangle(options)); } else { chart.renderer.drawRectangle(options); } if (legend.title) { this.renderLegendTitle(chart, legend, legendBounds, legendGroup); } if (!isCanvas) { legendGroup.appendChild(legendItemsGroup); } this.legendTranslateGroup = chart.renderer.createGroup({ id: id + '_translate_g' }); if (!isCanvas) { legendItemsGroup.appendChild(this.legendTranslateGroup); } options.y += (this.isTop ? this.legendTitleSize.height : 0) + (!this.isBulletChartControl ? legend.containerPadding.top : 0); options.height -= (this.isTop && (this.isChartControl || !this.isVertical || legend.layout !== 'Auto') ? this.legendTitleSize.height : 0) + (this.isBulletChartControl ? 0 : legend.containerPadding.top); options.id += '_clipPath_rect'; options.width = ((!this.isChartControl && chart.getModuleName() !== 'bulletChart' && !this.isStockChartControl && !(chart.getModuleName() === 'accumulationchart' && (legend.layout !== 'Auto' || legend.maximumColumns > 0))) && this.isVertical) ? this.maxWidth - padding + legend.containerPadding.left + legend.containerPadding.right : legendBounds.width; options.width = chart.legendSettings.titlePosition === 'Right' ? (options.width - this.legendTitleSize.width - padding) : options.width; if (!isCanvas) { this.clipRect = chart.renderer.drawRectangle(options); clippath.appendChild(this.clipRect); } else { this.pagingClipRect = options; } appendChildElement(isCanvas, chart.svgObject, clippath, redraw); if (!isCanvas) { legendItemsGroup.style.cssText = 'clip-path:url(#' + clippath.id + ')'; } return this.legendTranslateGroup; }; /** * To render legend symbols for chart and accumulation chart * * @param legendOption * @param group * @param i * @param legendOption * @param group * @param i * @param legendOption * @param group * @param i */ BaseLegend.prototype.renderSymbol = function (legendOption, group, legendIndex) { var control = this.isBulletChartControl ? this.chart : null; var symbolColor = legendOption.visible ? legendOption.fill : '#D3D3D3'; var isStrokeWidth = (this.chart.getModuleName() === 'chart' || this.chart.getModuleName() === 'stockChart') && (((legendOption.shape === 'SeriesType') && (legendOption.type.toLowerCase().indexOf('line') > -1) && (legendOption.type.toLowerCase().indexOf('area') === -1)) || ((legendOption.shape === 'HorizontalLine') || (legendOption.shape === 'VerticalLine') || (legendOption.shape === 'Cross'))); var isCustomBorder = (this.chart.getModuleName() === 'chart' || this.chart.getModuleName() === 'stockChart') && (legendOption.type === 'Scatter' || legendOption.type === 'Bubble'); var isCanvas = this.isStockChartControl ? false : this.chart.enableCanvas; var borderColor; var shape = (legendOption.shape === 'SeriesType') ? legendOption.type : legendOption.shape; var strokewidth = isStrokeWidth ? (this.legend.mode === 'Series' ? this.chart.visibleSeries[legendIndex].width : this.chart.visibleSeries[0].width) : (this.isBulletChartControl && legendOption.shape === 'Multiply') ? 4 : 1; var regionPadding; shape = shape === 'Scatter' ? legendOption.markerShape : shape; if (isCustomBorder && legendIndex < this.chart.visibleSeries.length) { var series = this.chart.visibleSeries[legendIndex]; var seriesBorder = series.border; var isLineShapemarker = shape === 'HorizontalLine' || shape === 'VerticalLine'; borderColor = isLineShapemarker ? symbolColor : seriesBorder.color ? seriesBorder.color : symbolColor; strokewidth = isLineShapemarker ? series.width : seriesBorder.width ? seriesBorder.width : 1; } var symbolOption = new PathOption(this.legendID + this.generateId(legendOption, '_shape_', legendIndex), symbolColor, strokewidth, (isCustomBorder ? borderColo