@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.
506 lines (505 loc) • 27.9 kB
JavaScript
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;
};
/**
* Circular 3D chart data label.
*/
import { isNullOrUndefined, ChildProperty, Property, Complex, extend, getValue, createElement } from '@syncfusion/ej2-base';
import { Border } from '../../common/model/base';
import { measureText, Rect } from '@syncfusion/ej2-svg-base';
import { textRender } from '../../common/model/constants';
import { appendChildElement, colorNameToHex, convertHexToColor, getFontStyle, getTemplateFunction, measureElementRect, isOverlap, textTrim } from '../../common/utils/helper';
/**
* Configures the fonts in the circular 3D data label.
*/
var CircularChart3DDataLabelFont = /** @class */ (function (_super) {
__extends(CircularChart3DDataLabelFont, _super);
function CircularChart3DDataLabelFont() {
return _super !== null && _super.apply(this, arguments) || this;
}
__decorate([
Property('Normal')
], CircularChart3DDataLabelFont.prototype, "fontStyle", void 0);
__decorate([
Property('16px')
], CircularChart3DDataLabelFont.prototype, "size", void 0);
__decorate([
Property('Normal')
], CircularChart3DDataLabelFont.prototype, "fontWeight", void 0);
__decorate([
Property('')
], CircularChart3DDataLabelFont.prototype, "color", void 0);
__decorate([
Property('Segoe UI')
], CircularChart3DDataLabelFont.prototype, "fontFamily", void 0);
__decorate([
Property(1)
], CircularChart3DDataLabelFont.prototype, "opacity", void 0);
return CircularChart3DDataLabelFont;
}(ChildProperty));
export { CircularChart3DDataLabelFont };
/**
* Defines the appearance of the connector line for the circular 3D chart.
*/
var CircularChart3DConnector = /** @class */ (function (_super) {
__extends(CircularChart3DConnector, _super);
function CircularChart3DConnector() {
return _super !== null && _super.apply(this, arguments) || this;
}
__decorate([
Property(null)
], CircularChart3DConnector.prototype, "color", void 0);
__decorate([
Property(1)
], CircularChart3DConnector.prototype, "width", void 0);
__decorate([
Property(null)
], CircularChart3DConnector.prototype, "length", void 0);
__decorate([
Property('')
], CircularChart3DConnector.prototype, "dashArray", void 0);
return CircularChart3DConnector;
}(ChildProperty));
export { CircularChart3DConnector };
/**
* Configures the data label settings for circular 3D chart.
*/
var CircularChart3DDataLabelSettings = /** @class */ (function (_super) {
__extends(CircularChart3DDataLabelSettings, _super);
function CircularChart3DDataLabelSettings() {
return _super !== null && _super.apply(this, arguments) || this;
}
__decorate([
Property(false)
], CircularChart3DDataLabelSettings.prototype, "visible", void 0);
__decorate([
Property(null)
], CircularChart3DDataLabelSettings.prototype, "name", void 0);
__decorate([
Property('transparent')
], CircularChart3DDataLabelSettings.prototype, "fill", void 0);
__decorate([
Property('Inside')
], CircularChart3DDataLabelSettings.prototype, "position", void 0);
__decorate([
Property(0)
], CircularChart3DDataLabelSettings.prototype, "angle", void 0);
__decorate([
Property(false)
], CircularChart3DDataLabelSettings.prototype, "enableRotation", void 0);
__decorate([
Complex({ width: null, color: null }, Border)
], CircularChart3DDataLabelSettings.prototype, "border", void 0);
__decorate([
Complex({ fontFamily: null, size: '12px', fontStyle: 'Normal', fontWeight: '400', color: null }, CircularChart3DDataLabelFont)
], CircularChart3DDataLabelSettings.prototype, "font", void 0);
__decorate([
Complex({}, CircularChart3DConnector)
], CircularChart3DDataLabelSettings.prototype, "connectorStyle", void 0);
__decorate([
Property(null)
], CircularChart3DDataLabelSettings.prototype, "template", void 0);
__decorate([
Property('')
], CircularChart3DDataLabelSettings.prototype, "format", void 0);
return CircularChart3DDataLabelSettings;
}(ChildProperty));
export { CircularChart3DDataLabelSettings };
/**
* The 'CircularChartDataLabel3D' module used to render dataLabel in circular 3D charts.
*/
var CircularChartDataLabel3D = /** @class */ (function (_super) {
__extends(CircularChartDataLabel3D, _super);
function CircularChartDataLabel3D() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Renders data labels for a circular 3D series on the given chart.
*
* @param {CircularChart3DSeries} series - The circular 3D series for which data labels are to be rendered.
* @param {CircularChart3D} chart - The circular 3D chart instance.
* @returns {void}
* @private
*/
CircularChartDataLabel3D.prototype.renderDataLabel = function (series, chart) {
var templateId = chart.element.id + '-series-' + series.index + '-data-label-collections';
series.labelBound = isNullOrUndefined(series.labelBound) ? new Rect(Infinity, Infinity, -Infinity, -Infinity) : series.labelBound;
series.dataLabelElement = createElement('div', { id: templateId });
for (var i = 0; i < series.points.length; i++) {
var point = series.points[i];
var pointText = this.getDatalabelText(series.dataLabel.format, chart, point.text ? point.text : isNullOrUndefined(point.y) ? '' : point.y.toString());
var border = { width: series.dataLabel.border.width, color: series.dataLabel.border.color,
dashArray: series.dataLabel.border.dashArray };
var argsFont = (extend({}, getValue('properties', series.dataLabel.font), null, true));
var argsData = {
cancel: false, name: textRender, series: series, point: point,
text: pointText, border: border, color: series.dataLabel.fill, template: series.dataLabel.template, font: argsFont
};
chart.trigger(textRender, argsData);
point.argsData = argsData;
if (point.visible && !argsData.cancel && !isNullOrUndefined(point.y)) {
this.draw3DDataLabel(series, point.index, point, chart);
}
}
if (series.dataLabel.template) {
appendChildElement(false, document.getElementById(chart.element.id + '_Secondary_Element'), series.dataLabelElement, chart.redraw, false, 'x', 'y', null, '', false, false, null);
}
};
/**
* Creates a data label template for a specific data point in a 3D series.
*
* @param {HTMLElement} parentElement - The parent HTML element to which the data label template is attached.
* @param {CircularChart3DSeries} series - The 3D series to which the data point belongs.
* @param {CircularChart3DDataLabelSettingsModel} dataLabel - The style settings for data labels.
* @param {CircularChart3DPoints} point - The data point for which the data label template is created.
* @param {CircularChart3DTextRenderEventArgs} data - The text render event arguments.
* @param {number} labelIndex - The index of the data label.
* @param {boolean} redraw - Indicates whether the template should be redrawn.
* @param {CircularChart3DLocation} location - The location values for the data label.
* @param {CircularChart3D} chart - The circular 3D chart instance.
* @returns {void}
* @private
*/
CircularChartDataLabel3D.prototype.createDataLabelTemplate = function (parentElement, series, dataLabel, point, data, labelIndex, redraw, location, chart) {
var childElement = this.createTemplate(createElement('div', {
id: chart.element.id + '-series-' + series.index + '-data-label-' + labelIndex,
styles: 'position: absolute;background-color:' + data.color + ';' +
getFontStyle(dataLabel.font, chart.themeStyle.datalabelFont) + ';border:' + data.border.width + 'px solid ' + data.border.color + ';'
}), data.template, chart, point, series, chart.element.id + '-data-label-');
this.calculateTemplateLabelSize(parentElement, childElement, point, series, dataLabel, redraw, location);
};
/**
* Calculates the size of a data label template for a specific data point in a 3D series.
*
* @param {HTMLElement} parentElement - The parent HTML element containing the data label template.
* @param {HTMLElement} childElement - The child HTML element representing the data label template.
* @param {CircularChart3DPoints} point - The data point for which the data label template size is calculated.
* @param {CircularChart3DSeries} series - The circular 3D series to which the data point belongs.
* @param {CircularChart3DDataLabelSettingsModel} dataLabel - The style for data labels.
* @param {boolean} redraw - Indicates whether the template should be redrawn.
* @param {CircularChart3DLocation} location - The location values for the data label.
* @param {boolean} isReactCallback - Indicates whether the callback is associated with React.
* @returns {void}
*/
CircularChartDataLabel3D.prototype.calculateTemplateLabelSize = function (parentElement, childElement, point, series, dataLabel, redraw, location, isReactCallback) {
var elementRect = measureElementRect(childElement, redraw, isReactCallback);
childElement.style.left = (location.x - (elementRect.width / 2)) + 'px';
childElement.style.top = (location.y - elementRect.height) + 'px';
appendChildElement(false, parentElement, childElement, redraw, true, 'left', 'top');
};
/**
* Creates a template element for rendering data labels associated with a specific data point in a 3D series.
*
* @param {HTMLElement} childElement - The child HTML element to contain the template content.
* @param {string | Function} content - The content or function for the data label template.
* @param {CircularChart3D} chart - The circular 3D chart instance.
* @param {CircularChart3DPoints} point - The data point for which the template is created (optional).
* @param {CircularChart3DSeries} series - The 3D series to which the data point belongs (optional).
* @param {string} dataLabelId - The ID for the data label element (optional).
* @returns {HTMLElement} - The created template element.
*/
CircularChartDataLabel3D.prototype.createTemplate = function (childElement, content, chart, point, series, dataLabelId) {
var templateFn = getTemplateFunction(content);
var templateElement;
try {
var tempObject = { chart: chart, series: series, point: point };
var templateId = dataLabelId + '-template';
var elementData = templateFn ? templateFn(tempObject, chart, templateId, dataLabelId) : [];
if (elementData.length) {
templateElement = Array.prototype.slice.call(elementData);
var len = templateElement.length;
for (var i = 0; i < len; i++) {
childElement.appendChild(templateElement[i]);
}
}
var reactCallback = void 0;
if (chart.isReact) {
chart.renderReactTemplates(reactCallback);
}
}
catch (e) {
return childElement;
}
return childElement;
};
/**
* Draws a 3D data label for a circular 3D series.
* This method is responsible for drawing a 3D data label for a circular 3D series.
*
* @param {CircularChart3DSeries} series - The CircularChart3DSeries to which the data label belongs.
* @param {number} pointIndex - The index of the data label point in the series.
* @param {CircularChart3DPoints} point - The CircularChart3DPoints representing the 3D point of the data label.
* @param {CircularChart3D} chart - The circular 3D chart instance.
* @returns {void}
*/
CircularChartDataLabel3D.prototype.draw3DDataLabel = function (series, pointIndex, point, chart) {
var connectorHeight = series.dataLabel.connectorStyle.length ?
parseFloat(series.dataLabel.connectorStyle.length) : series.dataLabel.connectorStyle.length;
var radius;
var pointX;
var pointY;
var degree;
var commonEventArgs = { data: null };
var location = { x: 0, y: 0 };
var seriesIndex = series.index;
var center = point.symbolLocation.center;
var dradius = point.symbolLocation.radius * series.coefficient;
if (isNullOrUndefined(connectorHeight)) {
connectorHeight = measureText(point.argsData.text, series.dataLabel.font, chart.themeStyle.datalabelFont).height;
}
if (series != null && series.dataLabel.position !== 'Inside') {
radius = point.symbolLocation.radius + connectorHeight;
}
else if (series != null) {
radius = dradius + (point.symbolLocation.radius - dradius) / 2;
}
pointX = location.x = center.x + (parseFloat(point.argsData.font.size) / 3) + radius * Math.cos(point.symbolLocation.angle);
pointY = location.y = center.y + (parseFloat(point.argsData.font.size) / 3) + radius * Math.sin(point.symbolLocation.angle);
commonEventArgs.data = {
text: point.argsData.text, location: { x: pointX, y: pointY },
series: series, pointIndex: pointIndex, seriesIndex: seriesIndex
};
commonEventArgs.data.Text = commonEventArgs.data.text;
var size = measureText(point.argsData.text, series.dataLabel.font, chart.themeStyle.datalabelFont);
pointX = location.x = commonEventArgs.data.location.x;
pointY = location.y = commonEventArgs.data.location.y;
var tag = (!series.dataLabel.template) ? 'text' : 'template';
var saturationColor = this.getSaturatedColor(point, point.argsData.color, chart);
var element = { width: size.width, height: size.height, fill: saturationColor, label: commonEventArgs.data, textAnchor: 'middle', tag: tag, font: point.argsData.font, angle: 0, id: chart.element.id + '-svg-data-label-text-' + pointIndex, child: chart.groupElement };
if (chart.circularChartLegend3DModule && chart.legendSettings.visible && point.visible && series.dataLabel.position === 'Outside') {
var rect = chart.circularChartLegend3DModule.legendBounds;
var legendpadding = chart.legendSettings.border.width / 2;
rect = new Rect(rect.x - legendpadding, rect.y - legendpadding, rect.width +
(2 * legendpadding), rect.height + (2 * legendpadding));
var labelRegion = new Rect(element.label.location.x + (size.width / 2) + 20, element.label.location.y + 2.5, element.width, element.height);
if (isOverlap(labelRegion, rect)) {
if (chart.circularChartLegend3DModule.position === 'Right') {
element.width = rect.x - labelRegion.x;
}
else if (chart.circularChartLegend3DModule.position === 'Left') {
element.width = labelRegion.x - (rect.x + rect.width);
if (element.width < 0) {
element.width += labelRegion.width;
element.label.location.x = rect.x + rect.width - (size.width / 2) + 20;
}
}
if (labelRegion && element.width < labelRegion.width) {
element.label.text = textTrim(element.width, element.label.text, series.dataLabel.font, chart.enableRtl, chart.themeStyle.datalabelFont);
}
if (element.label.text.length === 3 && element.label.text.indexOf('...') > -1) {
return;
}
}
}
var connectorPoints;
if (series.dataLabel.position !== 'Inside') {
connectorPoints = this.updateConnectorLine(point, pointIndex, series, connectorHeight, chart);
}
if (series.dataLabel.template && series.dataLabel.position !== 'Inside') {
var childElement = this.createTemplate(createElement('div', {
id: chart.element.id + '-series-data-label-' + 0,
styles: 'position: absolute;background-color:' + point.argsData.color + ';' +
getFontStyle(point.argsData.font, chart.themeStyle.datalabelFont) + ';border:' + point.argsData.border.width + 'px solid ' + point.argsData.border.color + ';'
}), point.argsData.template, chart, point, series, chart.element.id + '-data-label-');
size = measureText(childElement.textContent, series.dataLabel.font, chart.themeStyle.datalabelFont);
}
if (chart.circularChartLegend3DModule && chart.legendSettings.visible && (series.dataLabel.position === 'Outside')) {
chart.visibleSeries[0].findMaxBounds(chart.visibleSeries[0].labelBound, { x: pointX, y: pointY, width: size.width, height: size.height });
}
var padding = 0;
var heightPadding = 0;
var textAngle = point.symbolLocation.angle;
if (series.dataLabel.position !== 'Inside') {
if ((textAngle > 1.5 && textAngle < 1.8) || (textAngle > 1.3 && textAngle < 1.5) ||
(textAngle > 4.5 && textAngle < 4.8) || (textAngle > 4.3 && textAngle < 4.5)) {
location.x = connectorPoints.x;
location.y = connectorPoints.y;
textAngle = connectorPoints.angle;
}
if (textAngle < (Math.PI / 2) || textAngle >= (Math.PI / 2) + Math.PI) {
padding = (size.width / 2) + 20;
heightPadding = 5 / 2;
}
else {
padding = -((size.width / 2) + (point.argsData.color !== 'transparent' || point.argsData.border.color ? 25 : 20));
heightPadding = 5 / 2;
}
}
if (!point.argsData.template && commonEventArgs.data.text !== '') {
var element_1 = { tag: 'dataLabel', series: series, point: point, pointIndex: pointIndex, id: chart.element.id + '-svg-' + seriesIndex + '-data-label-' + pointIndex, child: chart.groupElement };
var angle = void 0;
var transform = '';
if (series.dataLabel.enableRotation) {
angle = degree = series.dataLabel.angle;
if (angle === 0) {
var toDegrees = function (angle) { return angle * (180 / Math.PI); };
var midAngle = toDegrees(point.symbolLocation.angle);
if (series.dataLabel.position === 'Outside') {
degree = 0;
}
else if (midAngle >= 90 && midAngle <= 260) {
degree = midAngle + 180;
location.x = location.x - (parseFloat(point.argsData.font.size) / 2);
}
else {
degree = midAngle;
}
}
else {
degree = (angle > 360) ? angle - 360 : (angle < -360) ? angle + 360 : angle;
}
transform = 'rotate(' + degree + ',' + (location.x) + ',' + (location.y) + ')';
}
element_1.transform = transform;
var borderElement = chart.polygon.createTextElement(chart.vector.vector3D(pointX + padding, pointY + heightPadding, (point.symbolLocation.z) ?
point.symbolLocation.z : 0), element_1, 0, -size.height);
chart.circular3DPolygon.push(borderElement);
}
element.angle = series.dataLabel.enableRotation ? series.dataLabel.angle !== 0 ? series.dataLabel.angle : degree : 0;
var polygon = chart.polygon.createTextElement(chart.vector.vector3D(location.x + padding, location.y + heightPadding, -1), element, 0, -size.height);
chart.circular3DPolygon.push(polygon);
};
/**
* To find saturated color for datalabel.
*
* @param {CircularChart3DPoints} point - The point to get the color saturation.
* @param {string} color - The color to be saturated.
* @param {CircularChart3D} chart - The circular 3D chart instance.
* @returns {string} - The saturated color computed for the data label.
*/
CircularChartDataLabel3D.prototype.getSaturatedColor = function (point, color, chart) {
var saturatedColor;
saturatedColor = color === 'transparent' ? this.getLabelBackground(point, chart) : color;
saturatedColor = (saturatedColor === 'transparent') ? ((chart.theme.indexOf('Dark') > -1 || chart.theme.indexOf('HighContrast') > -1) ? 'black' : 'white') : saturatedColor;
var rgbValue = convertHexToColor(colorNameToHex(saturatedColor));
var contrast = Math.round((rgbValue.r * 299 + rgbValue.g * 587 + rgbValue.b * 114) / 1000);
return chart.theme === 'Bootstrap5' ? '#212529' : chart.theme === 'Bootstrap5Dark' ? '#DEE2E6' : contrast >= 128 ? chart.theme.indexOf('Tailwind3') > -1 ? '#4B5563' : 'black' : chart.theme.indexOf('Tailwind3') > -1 ? '#D1D5DB' : 'white';
};
/**
* To find background color for the datalabel.
*
* @param {CircularChart3DPoints} point - The point to get the color saturation.
* @param {CircularChart3D} chart - The circular 3D chart instance.
* @returns {string} - The background color computed for the data label.
*/
CircularChartDataLabel3D.prototype.getLabelBackground = function (point, chart) {
return point.argsData.series.dataLabel.position === 'Outside' ?
chart.background || chart.themeStyle.background : !point.y ? chart.theme.indexOf('dark') ? 'white' : 'black' : point.color;
};
/**
* Gets the data label text based on a specified format, chart configuration, and input label text.
*
* @param {string} labelFormat - The format string for the data label.
* @param {CircularChart3D} chart - The Circular 3D chart instance.
* @param {string} labelText - The original label text to be formatted.
* @returns {string} - The formatted data label text.
*/
CircularChartDataLabel3D.prototype.getDatalabelText = function (labelFormat, chart, labelText) {
if (Number(labelText)) {
var customLabelFormat = labelFormat.match('{value}') !== null;
var format = chart.intl.getNumberFormat({
format: customLabelFormat ? '' : labelFormat,
useGrouping: chart.useGroupingSeparator
});
labelText = customLabelFormat ? labelFormat.replace('{value}', format(parseFloat(labelText))) : format(parseFloat(labelText));
}
return labelText;
};
/**
* Updates the connector line for a 3D point in a circular 3D series.
*
* @param {CircularChart3DPoints} point - The CircularChart3DPoints representing the 3D point.
* @param {number} pointIndex - The index of the point in the series.
* @param {CircularChart3DSeries} series - The instance of the circular 3D series.
* @param {number} connectorHeight - The height of the connector line.
* @param {CircularChart3D} chart - The circular 3D chart instance.
* @returns {void}
*/
CircularChartDataLabel3D.prototype.updateConnectorLine = function (point, pointIndex, series, connectorHeight, chart) {
var drawPoints = [];
var symbolLocation = point.symbolLocation;
var x = symbolLocation.center.x + Math.cos(symbolLocation.angle) * symbolLocation.radius;
var y = symbolLocation.center.y + Math.sin(symbolLocation.angle) * symbolLocation.radius;
drawPoints.push({ x: x, y: y });
var labelRadiusFromOrigin = symbolLocation.radius + connectorHeight;
var angle = symbolLocation.angle;
x = symbolLocation.center.x + Math.cos(angle) * labelRadiusFromOrigin;
y = symbolLocation.center.y + Math.sin(angle) * labelRadiusFromOrigin;
drawPoints.push({ x: x, y: y });
var padding;
if (angle < (Math.PI / 2) || angle >= (Math.PI / 2) + Math.PI) {
padding = 10;
}
else {
padding = -10;
}
drawPoints.push({ x: x + padding, y: y });
this.drawLineSegment(drawPoints, pointIndex, series, chart);
return ({ x: x, y: y, angle: angle });
};
/**
* Draws a line segment based on the provided points in 3D space for the circular 3D series.
*
* @param {CircularChart3DLocation[]} drawpoints - An array of CircularChart3DLocation representing the points in 3D space.
* @param {number} pointIndex - The index of the point in the series.
* @param {CircularChart3DSeries} series - The instance of the circular 3D series to which the point belongs.
* @param {CircularChart3D} chart - The circular 3D chart instance.
* @returns {void}
*/
CircularChartDataLabel3D.prototype.drawLineSegment = function (drawpoints, pointIndex, series, chart) {
var vectorPoints = [];
for (var i = 0; i < drawpoints.length; i++) {
vectorPoints.push(chart.vector.vector3D(drawpoints[i].x, drawpoints[i].y, 0));
}
var seriesIndex = series.index;
var color = series.points[pointIndex].color;
var stroke = series.dataLabel.connectorStyle.color ? series.dataLabel.connectorStyle.color : color;
var line = {
width: series.dataLabel.connectorStyle.width,
stroke: stroke,
child: chart.groupElement,
tag: 'polyline',
dashArray: series.dataLabel.connectorStyle.dashArray,
id: chart.element.id + '-datalabel-series-' + seriesIndex + '-connector-' + pointIndex
};
var ploygon = chart.polygon.createPolyline(vectorPoints, line);
chart.circular3DPolygon.push(ploygon);
};
/**
* Gets the module name for the circular 3D data label.
*
* @returns {string} - The module name, which is 'CircularChartDataLabel3D'.
*/
CircularChartDataLabel3D.prototype.getModuleName = function () {
return 'CircularChartDataLabel3D';
};
/**
* Destroys the circular 3D chart data label.
*
* @returns {void}
* @private
*/
CircularChartDataLabel3D.prototype.destroy = function () {
/**
* Destroy method performed here.
*/
};
return CircularChartDataLabel3D;
}(ChildProperty));
export { CircularChartDataLabel3D };