UNPKG

scichart

Version:

Fast WebGL JavaScript Charting Library and Framework

970 lines (969 loc) 49.7 kB
"use strict"; 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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.addEventListenerToPieSegment = exports.SciChartPieSurface = exports.EPieValueMode = exports.EPieType = exports.ESizingMode = void 0; var chartBuilder_1 = require("../../../Builder/chartBuilder"); var classFactory_1 = require("../../../Builder/classFactory"); var app_1 = require("../../../constants/app"); var EasingFunctions_1 = require("../../../Core/Animations/EasingFunctions"); var DeletableEntity_1 = require("../../../Core/DeletableEntity"); var Deleter_1 = require("../../../Core/Deleter"); var EventHandler_1 = require("../../../Core/EventHandler"); var Globals_1 = require("../../../Core/Globals"); var ObservableArray_1 = require("../../../Core/ObservableArray"); var Rect_1 = require("../../../Core/Rect"); var BaseType_1 = require("../../../types/BaseType"); var SciChartSurfaceType_1 = require("../../../types/SciChartSurfaceType"); var guid_1 = require("../../../utils/guid"); var SciChartJSDarkTheme_1 = require("../../Themes/SciChartJSDarkTheme"); var annotationHelpers_1 = require("../Annotations/annotationHelpers"); var PieLabelProvider_1 = require("../Axis/LabelProvider/PieLabelProvider"); var SciChartPieLegend_1 = require("../Legend/SciChartPieLegend"); var sciChartInitCommon_1 = require("../sciChartInitCommon"); var SciChartSurfaceBase_1 = require("../SciChartSurfaceBase"); var DpiHelper_1 = require("../TextureManager/DpiHelper"); var constants_1 = require("./constants"); var constants_2 = require("./PieSegment/constants"); /** @ignore */ var DEG_TO_RAD = Math.PI / 180; /** @ignore */ var START_ANGLE = 90; var ESizingMode; (function (ESizingMode) { /** * The size value is specified as absolute value ( e.g. 1px, 10dp etc) */ ESizingMode["Absolute"] = "Absolute"; /** * The size value is specified as relative value ( e.g. 10% from available size ) */ ESizingMode["Relative"] = "Relative"; })(ESizingMode = exports.ESizingMode || (exports.ESizingMode = {})); var EPieType; (function (EPieType) { EPieType["Pie"] = "Pie"; EPieType["Donut"] = "Donut"; })(EPieType = exports.EPieType || (exports.EPieType = {})); var EPieValueMode; (function (EPieValueMode) { EPieValueMode[EPieValueMode["Percentage"] = 0] = "Percentage"; EPieValueMode[EPieValueMode["Raw"] = 1] = "Raw"; })(EPieValueMode = exports.EPieValueMode || (exports.EPieValueMode = {})); /** * @summary The {@link SciChartPieSurface} is the root Pie and Donut Chart control in SciChart's High Performance Real-time * {@link https://www.scichart.com/javascript-chart-features | JavaScript Chart Library} * @description * To create a Pie chart using SciChart, declare a {@link SciChartPieSurface} using {@link SciChartPieSurface.create}, * * Next, add a pie segments by adding a {@link PieSegment} to the {@link SciChartPieSurface.pieSegments} collection. * * You can create a donut chart by setting the {@link SciChartPieSurface.holeRadius} property. * * You can add and configure a legend by setting the {@link SciChartPieSurface.legend} property. * @remarks * It is possible to have more than one {@link SciChartPieSurface} on screen at the same time. * {@link SciChartPieSurface | SciChartPieSurfaces} scale to fit the parent DIV where they are hosted. Use CSS to position the DIV. */ var SciChartPieSurface = /** @class */ (function (_super) { __extends(SciChartPieSurface, _super); function SciChartPieSurface(canvases, options) { if (canvases === void 0) { canvases = {}; } var _this = this; var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r; _this = _super.call(this) || this; _this.animate = true; /* The number of frames for the animation. Default 30. A frame will be trigged every 20ms. */ _this.animationFrames = 30; /** * An event handler which notifies its subscribers when a render operation has finished. Use this * to time render performance, or to update elements of the chart or your UI on redraw. */ _this.rendered = new EventHandler_1.EventHandler(); _this.pieTypeProperty = EPieType.Pie; _this.holeRadiusProperty = 0.5; _this.holeRadiusSizingModeProperty = ESizingMode.Relative; _this.seriesSpacingProperty = 0; _this.labelRadiusProperty = 1; _this.titleDivs = []; _this.sweepAnimationDone = false; _this.suspendUpdate = false; _this.themeProviderProperty = new SciChartJSDarkTheme_1.SciChartJSDarkTheme(); _this.previousThemeProviderProperty = new SciChartJSDarkTheme_1.SciChartJSDarkTheme(); _this.deletables = []; _this.valueModeProperty = EPieValueMode.Percentage; _this.labelStyleProperty = { fontSize: 14, fontFamily: "Arial", color: "#1e323d", fontWeight: "bold" }; _this.id = (_a = options === null || options === void 0 ? void 0 : options.id) !== null && _a !== void 0 ? _a : (0, guid_1.generateGuid)(); _this.domChartRoot = canvases.domChartRoot; _this.domCanvas2D = canvases.domCanvas2D; _this.domSvgContainer = canvases.domSvgContainer; _this.domSvgAdornerLayer = canvases.domSvgAdornerLayer; _this.domDivContainer = canvases.domDivContainer; var width = _this.domCanvas2D.width / DpiHelper_1.DpiHelper.PIXEL_RATIO; var height = _this.domCanvas2D.height / DpiHelper_1.DpiHelper.PIXEL_RATIO; _this.viewRect = new Rect_1.Rect(0, 0, width, height); _this.resizeSubscriptionToken = sciChartInitCommon_1.default.subscribeToResize( // @ts-ignore canvases.domCanvas2D, canvases.aspect, _this); _this.drawChart = _this.drawChart.bind(_this); _this.deleteInternals = _this.deleteInternals.bind(_this); _this.invalidateElement = _this.invalidateElement.bind(_this); _this.detachPieSegment = _this.detachPieSegment.bind(_this); _this.attachPieSegment = _this.attachPieSegment.bind(_this); _this.pieSegments = new ObservableArray_1.ObservableArray(); _this.pieSegments.collectionChanged.subscribe(function (args) { var _a, _b; (_a = args.getOldItems()) === null || _a === void 0 ? void 0 : _a.forEach(_this.detachPieSegment); (_b = args.getNewItems()) === null || _b === void 0 ? void 0 : _b.forEach(_this.attachPieSegment); // Do this only after all changes have been processed _this.invalidateElement(); }); _this.applySciChartBackground(SciChartSurfaceBase_1.SciChartSurfaceBase.DEFAULT_THEME.sciChartBackground); _this.legend = new SciChartPieLegend_1.SciChartPieLegend(); _this.legend.setRootDiv(_this.domDivContainer); _this.legend.setPieSegmentArray(_this.pieSegments.asArray()); _this.legend.setInvalidateParentSurface(_this.invalidateElement); _this.legend.setParentSurface(_this); _this.heightAspect = (_b = options === null || options === void 0 ? void 0 : options.heightAspect) !== null && _b !== void 0 ? _b : 0; _this.widthAspect = (_c = options === null || options === void 0 ? void 0 : options.widthAspect) !== null && _c !== void 0 ? _c : 0; _this.pieTypeProperty = (_d = options === null || options === void 0 ? void 0 : options.pieType) !== null && _d !== void 0 ? _d : _this.pieType; _this.holeRadiusProperty = (_e = options === null || options === void 0 ? void 0 : options.holeRadius) !== null && _e !== void 0 ? _e : _this.holeRadius; _this.animate = (_f = options === null || options === void 0 ? void 0 : options.animate) !== null && _f !== void 0 ? _f : _this.animate; _this.holeRadiusSizingModeProperty = (_g = options === null || options === void 0 ? void 0 : options.holeRadiusSizingMode) !== null && _g !== void 0 ? _g : _this.holeRadiusSizingModeProperty; _this.seriesSpacingProperty = (_h = options === null || options === void 0 ? void 0 : options.seriesSpacing) !== null && _h !== void 0 ? _h : _this.seriesSpacingProperty; _this.labelRadiusProperty = (_j = options === null || options === void 0 ? void 0 : options.labelRadiusAdjustment) !== null && _j !== void 0 ? _j : _this.labelRadiusProperty; _this.legend.showLegend = (_k = options === null || options === void 0 ? void 0 : options.showLegend) !== null && _k !== void 0 ? _k : _this.legend.showLegend; _this.legend.animate = (_l = options === null || options === void 0 ? void 0 : options.animateLegend) !== null && _l !== void 0 ? _l : _this.legend.animate; _this.legend.showCheckboxes = (_m = options === null || options === void 0 ? void 0 : options.showLegendCheckBoxes) !== null && _m !== void 0 ? _m : _this.legend.showCheckboxes; _this.legend.showSeriesMarkers = (_o = options === null || options === void 0 ? void 0 : options.showLegendSeriesMarkers) !== null && _o !== void 0 ? _o : _this.legend.showSeriesMarkers; _this.paddingProperty = (_p = options === null || options === void 0 ? void 0 : options.padding) !== null && _p !== void 0 ? _p : _this.paddingProperty; if (options === null || options === void 0 ? void 0 : options.labelProvider) { if (!("getSegmentText" in (options === null || options === void 0 ? void 0 : options.labelProvider))) { options.labelProvider = (0, classFactory_1.createType)(BaseType_1.EBaseType.LabelProvider, options.labelProvider.type, undefined, options.labelProvider.options); } } _this.labelProvider = (_q = options === null || options === void 0 ? void 0 : options.labelProvider) !== null && _q !== void 0 ? _q : new PieLabelProvider_1.PieLabelProvider(); _this.valueModeProperty = (_r = options === null || options === void 0 ? void 0 : options.valueMode) !== null && _r !== void 0 ? _r : _this.valueModeProperty; return _this; } /** * Creates a {@link SciChartPieSurface} to occupy the div by element ID in your DOM. * @remarks This method is async and must be awaited * @param divElementId The Div Element ID where the {@link SciChartPieSurface} will reside * @param width Optional - the width of the {@link SciChartPieSurface} in pixels. By default SciChart will scale to fit the parent Div * @param height Optional - the height of the {@link SciChartPieSurface} in pixels. By default SciChart will scale to fit the parent Div */ SciChartPieSurface.create = function (divElement, options) { var _a, _b; (0, chartBuilder_1.ensureRegistrations)(); var canvases = sciChartInitCommon_1.default.initCanvas(divElement, (_a = options === null || options === void 0 ? void 0 : options.widthAspect) !== null && _a !== void 0 ? _a : 0, (_b = options === null || options === void 0 ? void 0 : options.heightAspect) !== null && _b !== void 0 ? _b : 0, sciChartInitCommon_1.default.ECanvasType.svg, undefined, options === null || options === void 0 ? void 0 : options.touchAction); return new Promise(function (resolve) { var _a, _b, _c; var conflictingRenderContextDestinations = __spreadArray(__spreadArray(__spreadArray(__spreadArray([], Globals_1.sciChartDestinations, true), Globals_1.sciChart3DDestinations, true), Globals_1.sciChartSingleDestinations, true), Globals_1.sciChartPieDestinations, true).filter(function (destination) { return destination.sciChartSurface.domChartRoot.id === canvases.domChartRoot.id; }); conflictingRenderContextDestinations.forEach(function (destination) { return destination.sciChartSurface.delete(); }); options = SciChartSurfaceBase_1.SciChartSurfaceBase.resolveOptions(options); var scps = new SciChartPieSurface(canvases, options); scps.applyTheme(options === null || options === void 0 ? void 0 : options.theme); Globals_1.sciChartPieDestinations.push({ canvasElementId: (_a = canvases.domCanvas2D) === null || _a === void 0 ? void 0 : _a.id, sciChartSurface: scps, width: (_b = canvases.domCanvas2D) === null || _b === void 0 ? void 0 : _b.width, height: (_c = canvases.domCanvas2D) === null || _c === void 0 ? void 0 : _c.height }); scps.setDestinations(Globals_1.sciChartPieDestinations); // setTimeout is used to make function async like createSciChartSurface, to have a consistent API setTimeout(function () { return resolve(scps); }, 0); }); }; Object.defineProperty(SciChartPieSurface.prototype, "isDeleted", { get: function () { return this.isDeletedProperty; }, enumerable: false, configurable: true }); Object.defineProperty(SciChartPieSurface.prototype, "labelProvider", { /** * Gets or sets a {@link LabelProvider} - a class which is responsible for formatting axis labels and cursor labels from numeric values */ get: function () { return this.labelProviderProperty; }, /** * Gets or sets a {@link LabelProvider} - a class which is responsible for formatting axis labels and cursor labels from numeric values */ set: function (labelProvider) { if (labelProvider && this.labelProviderProperty !== labelProvider) { this.labelProviderProperty = labelProvider; this.notifyPropertyChanged(constants_1.PROPERTY.LABEL_PROVIDER); } }, enumerable: false, configurable: true }); Object.defineProperty(SciChartPieSurface.prototype, "labelStyle", { /** * Gets or sets a {@link TTextStyle} object for styling labels */ get: function () { return this.labelStyleProperty; }, /** * Gets or sets a {@link TTextStyle} object for styling labels */ set: function (textStyle) { this.labelStyleProperty = __assign(__assign({}, this.labelStyle), textStyle); this.notifyPropertyChanged(constants_1.PROPERTY.TEXT_STYLE); }, enumerable: false, configurable: true }); /** * @inheritDoc */ SciChartPieSurface.prototype.applyTheme = function (themeProvider) { this.previousThemeProviderProperty = this.themeProviderProperty; this.themeProviderProperty = themeProvider; this.applySciChartBackground(themeProvider.sciChartBackground); if (this.labelStyle.color === this.previousThemeProvider.tickTextBrush) { this.labelStyle = { color: themeProvider.tickTextBrush }; } this.invalidateElement(); }; Object.defineProperty(SciChartPieSurface.prototype, "themeProvider", { /** * Used internally - gets the previous {@link IThemeProvider} */ get: function () { return this.themeProviderProperty; }, enumerable: false, configurable: true }); Object.defineProperty(SciChartPieSurface.prototype, "previousThemeProvider", { /** * Used internally - gets the previous {@link IThemeProvider} */ get: function () { return this.previousThemeProviderProperty; }, enumerable: false, configurable: true }); SciChartPieSurface.prototype.setDestinations = function (destinations) { this.destinations = destinations; }; Object.defineProperty(SciChartPieSurface.prototype, "otherSurfaces", { get: function () { var _this = this; if (!this.destinations) { return []; } return this.destinations.map(function (el) { return el.sciChartSurface; }).filter(function (el2) { return el2 !== _this; }); }, enumerable: false, configurable: true }); /** * Call invalidateElement() to trigger a redraw of the {@link SciChartPieSurface}. SciChart's rendering * engine will schedule a redraw a the next time the renderer is free. */ SciChartPieSurface.prototype.invalidateElement = function (options) { // TODO make params type consistent with 2D and 3D if (this.isValidToDraw()) { if (typeof options === "string" && options === constants_2.PROPERTY.VALUE) { this.sweepAnimationDone = false; } this.update(); } }; /** * Called internally - Updates and draws the Pie Chart */ SciChartPieSurface.prototype.update = function () { var _a; if (!this.suspendUpdate) { this.draw(); (_a = this.legend) === null || _a === void 0 ? void 0 : _a.update(); } }; /** * @inheritDoc */ SciChartPieSurface.prototype.delete = function () { var _this = this; var _a; this.deleteInternals(); this.legend = (0, Deleter_1.deleteSafe)(this.legend); this.labelProvider = (0, Deleter_1.deleteSafe)(this.labelProvider); this.resizeSubscriptionToken = (0, Deleter_1.deleteSafe)(this.resizeSubscriptionToken); // TODO probably this should be moved outside for Proxy === this comparison issue exists var currentSurfaceIndex = (_a = this.destinations) === null || _a === void 0 ? void 0 : _a.findIndex(function (dest) { return dest.sciChartSurface.id === _this.id; }); if (currentSurfaceIndex >= 0) { this.destinations.splice(currentSurfaceIndex, 1); } this.isDeletedProperty = true; }; /** * Used Internally. Cleans up the chart internal parts, subscriptions, etc. */ SciChartPieSurface.prototype.deleteInternals = function (isAnimationProgress) { var _this = this; if (this.svg) { this.domSvgContainer.removeChild(this.svg); this.svg = undefined; } if (!isAnimationProgress) { this.titleDivs.forEach(function (divEl) { _this.domDivContainer.removeChild(divEl); }); this.titleDivs = []; } for (var _i = 0, _a = this.deletables; _i < _a.length; _i++) { var deletable = _a[_i]; (0, Deleter_1.deleteSafe)(deletable); } this.deletables = []; }; /** * @inheritDoc */ SciChartPieSurface.prototype.addDeletable = function (deletable) { this.deletables.push(deletable); }; /** * @inheritDoc */ SciChartPieSurface.prototype.changeViewportSize = function (width, height) { var domWidth = width; var domHeight = height; this.viewRect = new Rect_1.Rect(0, 0, width, height); this.changeDomViewportSize(domWidth, domHeight); this.invalidateElement(); }; Object.defineProperty(SciChartPieSurface.prototype, "pieType", { // GETTERS AND SETTERS FOR PROPERTIES /** * Gets or sets the type of the pie chart. See {@link EPieType} for a list of values * @remarks See also {@link holeRadius} which is required for Donut charts and {@link holeRadiusSizingMode} * which defines whether the Donut hole is relative or absolute. */ get: function () { return this.pieTypeProperty; }, /** * Gets or sets the type of the pie chart. See {@link EPieType} for a list of values * @remarks See also {@link holeRadius} which is required for Donut charts and {@link holeRadiusSizingMode} * which defines whether the Donut hole is relative or absolute. */ set: function (value) { this.pieTypeProperty = value; this.notifyPropertyChanged(constants_1.PROPERTY.PIE_TYPE); }, enumerable: false, configurable: true }); Object.defineProperty(SciChartPieSurface.prototype, "holeRadius", { /** * Gets or sets the hole radius, which allows you to create Donut charts instead of Pie. * @remarks See also {@link EPieType} which is required to change from Pie to Donut and {@link holeRadiusSizingMode} * which defines whether the Donut hole is relative or absolute. */ get: function () { return this.holeRadiusProperty; }, /** * Gets or sets the hole radius, which allows you to create Donut charts instead of Pie. * @remarks See also {@link EPieType} which is required to change from Pie to Donut and {@link holeRadiusSizingMode} * which defines whether the Donut hole is relative or absolute. */ set: function (holeRadius) { this.holeRadiusProperty = holeRadius; this.notifyPropertyChanged(constants_1.PROPERTY.HOLE_RADIUS); }, enumerable: false, configurable: true }); Object.defineProperty(SciChartPieSurface.prototype, "holeRadiusSizingMode", { /** * Gets or sets the hole radius size mode for Donut charts. See {@link ESizingMode} for a list of values * @remarks See also {@link EPieType} which is required to change from Pie to Donut, and {@link holeRadius} * which sets the size of a Donut Chart hole */ get: function () { return this.holeRadiusSizingModeProperty; }, /** * Gets or sets the hole radius size mode for Donut charts. See {@link ESizingMode} for a list of values * @remarks See also {@link EPieType} which is required to change from Pie to Donut, and {@link holeRadius} * which sets the size of a Donut Chart hole */ set: function (holeRadiusSizingMode) { this.holeRadiusSizingModeProperty = holeRadiusSizingMode; this.notifyPropertyChanged(constants_1.PROPERTY.HOLE_RADIUS_SIZING_MODE); }, enumerable: false, configurable: true }); Object.defineProperty(SciChartPieSurface.prototype, "padding", { /** * Gets or sets padding */ get: function () { return this.paddingProperty; }, /** * Gets or sets padding */ set: function (value) { if (this.paddingProperty !== value) { this.paddingProperty = value; this.updateLegendMargin(); this.notifyPropertyChanged(constants_1.PROPERTY.PADDING); } }, enumerable: false, configurable: true }); Object.defineProperty(SciChartPieSurface.prototype, "canvasBorder", { /** * Gets or sets canvas border */ get: function () { return this.canvasBorderProperty; }, /** * Gets or sets canvas border */ set: function (value) { if (this.canvasBorderProperty !== value) { this.canvasBorderProperty = value; this.updateLegendMargin(); this.notifyPropertyChanged(constants_1.PROPERTY.PADDING); } }, enumerable: false, configurable: true }); Object.defineProperty(SciChartPieSurface.prototype, "seriesSpacing", { get: function () { return this.seriesSpacingProperty; }, set: function (value) { if (this.seriesSpacingProperty !== value) { this.seriesSpacingProperty = value; this.notifyPropertyChanged(constants_1.PROPERTY.SERIES_SPACING); } }, enumerable: false, configurable: true }); Object.defineProperty(SciChartPieSurface.prototype, "valueMode", { /** Whether to show labels as percentages, or raw values. Default to percentages */ get: function () { return this.valueModeProperty; }, /** Whether to show labels as percentages, or raw values. Default to percentages */ set: function (value) { this.valueModeProperty = value; this.notifyPropertyChanged(constants_1.PROPERTY.VALUE_MODE); }, enumerable: false, configurable: true }); Object.defineProperty(SciChartPieSurface.prototype, "labelRadiusAdjustment", { /** * Use this to adjust the position of the labels. 1 is the default. Larger values will shift the labels outwards. * For Pie charts, 1.7 will place the labels outside the pie * If you want more detailed control you can override calcTitlePosition. */ get: function () { return this.labelRadiusProperty; }, /** * Use this to adjust the position of the labels. 1 is the default. Larger values will shift the labels outwards. * If you want more detailed control you can override calcTitlePosition. */ set: function (value) { this.labelRadiusProperty = value; this.notifyPropertyChanged(constants_1.PROPERTY.VALUE_MODE); }, enumerable: false, configurable: true }); /** * Convert the surface to a {@link TSurfaceDefinition} * @param excludedata If false, segments will be included in the json */ SciChartPieSurface.prototype.toJSON = function (excludedata) { if (excludedata === void 0) { excludedata = false; } var theme; if ("toJSON" in this.themeProvider) { // @ts-ignore theme = this.themeProvider.toJSON(); } else { theme = this.themeProvider; } var surface = { animate: this.animate, animateLegend: this.legend.animate, heightAspect: this.heightAspect, widthAspect: this.widthAspect, holeRadius: this.holeRadius, holeRadiusSizingMode: this.holeRadiusSizingMode, pieType: this.pieType, showLegend: this.legend.showLegend, showLegendCheckBoxes: this.legend.showCheckboxes, showLegendSeriesMarkers: this.legend.showSeriesMarkers, padding: this.padding, canvasBorder: this.canvasBorder, seriesSpacing: this.seriesSpacing, // @ts-ignore labelProvider: this.labelProvider.toJSON(), valueMode: this.valueMode, labelRadiusAdjustment: this.labelRadiusAdjustment, animationFrames: this.animationFrames, theme: theme }; var options = { surface: surface, onCreated: this.onCreatedName }; if (!excludedata) { options.segments = this.pieSegments.asArray().map(function (s) { return s.toJSON(); }); } return { type: SciChartSurfaceType_1.ESciChartSurfaceType.Pie2D, options: options }; }; /** The method used to calculate the label position for each segment */ SciChartPieSurface.prototype.calcTitlePosition = function (x, y, outerRadius, innerRadius, a1, a2, delta, divWidth, divHeight) { var centerRadius = innerRadius < outerRadius / 2 ? (outerRadius * 2) / 3 + innerRadius / 6 : (outerRadius + innerRadius) / 2; var centerAngle = (a1 + a2) / 2; var left = x + Math.cos(DEG_TO_RAD * centerAngle) * (centerRadius * this.labelRadiusProperty + delta) - divWidth / 2; var top = y + Math.sin(DEG_TO_RAD * centerAngle) * (centerRadius * this.labelRadiusProperty + delta) - divHeight / 2; return { left: left, top: top }; }; /** * Changes the size of the DOM element where the {@link SciChartSurfaceBase} resides. * @param width * @param height */ SciChartPieSurface.prototype.changeDomViewportSize = function (width, height) { if (this.domSvgContainer) { this.domSvgContainer.setAttribute("width", width.toString()); this.domSvgContainer.setAttribute("height", height.toString()); } if (this.domSvgAdornerLayer) { this.domSvgAdornerLayer.setAttribute("width", width.toString()); this.domSvgAdornerLayer.setAttribute("height", height.toString()); } }; // PRIVATE SciChartPieSurface.prototype.notifyPropertyChanged = function (propertyName) { this.invalidateElement(); if (propertyName === constants_1.PROPERTY.LABEL_PROVIDER && this.labelProviderProperty) { this.labelProviderProperty.attachedToSurface(this); } }; SciChartPieSurface.prototype.isValidToDraw = function () { // TODO return true; }; SciChartPieSurface.prototype.detachPieSegment = function (pieSegment) { pieSegment.onDetach(); }; SciChartPieSurface.prototype.attachPieSegment = function (pieSegment) { pieSegment.onAttach(this); }; SciChartPieSurface.prototype.updateLegendMargin = function () { var _a, _b, _c; var paddingTop = ((_a = this.padding) === null || _a === void 0 ? void 0 : _a.top) || 0; var canvasBorderTop = ((_b = this.canvasBorder) === null || _b === void 0 ? void 0 : _b.border) || ((_c = this.canvasBorder) === null || _c === void 0 ? void 0 : _c.borderTop) || 0; // 10 - because of default spacing // only top included because of margin implementation for the legend this.legend.margin = paddingTop + canvasBorderTop + 10; }; SciChartPieSurface.prototype.calculateViewRectWidth = function (width) { var _a, _b, _c, _d, _e; if ((_a = this.padding) === null || _a === void 0 ? void 0 : _a.left) { width -= this.padding.left; } if ((_b = this.padding) === null || _b === void 0 ? void 0 : _b.right) { width -= this.padding.right; } if ((_c = this.canvasBorder) === null || _c === void 0 ? void 0 : _c.border) { width -= this.canvasBorder.border * 2; } else { if ((_d = this.canvasBorder) === null || _d === void 0 ? void 0 : _d.borderLeft) { width -= this.canvasBorder.borderLeft; } if ((_e = this.canvasBorder) === null || _e === void 0 ? void 0 : _e.borderRight) { width -= this.canvasBorder.borderRight; } } return width; }; SciChartPieSurface.prototype.calculateViewRectHeight = function (height) { var _a, _b, _c, _d, _e; if ((_a = this.padding) === null || _a === void 0 ? void 0 : _a.top) { height -= this.padding.top; } if ((_b = this.padding) === null || _b === void 0 ? void 0 : _b.bottom) { height -= this.padding.bottom; } if ((_c = this.canvasBorder) === null || _c === void 0 ? void 0 : _c.border) { height -= this.canvasBorder.border * 2; } else { if ((_d = this.canvasBorder) === null || _d === void 0 ? void 0 : _d.borderTop) { height -= this.canvasBorder.borderTop; } if ((_e = this.canvasBorder) === null || _e === void 0 ? void 0 : _e.borderBottom) { height -= this.canvasBorder.borderBottom; } } return height; }; SciChartPieSurface.prototype.draw = function () { var _this = this; if (this.pieSegments.size() === 0) return; if (this.sweepAnimationDone || !this.animate) { this.deleteInternals(); this.drawChart(); } else { var frames_1 = this.animationFrames; this.suspendUpdate = true; var setSuspendUpdateFalse_1 = function () { return (_this.suspendUpdate = false); }; var setSweepAnimationDone_1 = function () { return (_this.sweepAnimationDone = true); }; var callInvalidateElement_1 = this.invalidateElement; var callDrawChart_1 = this.drawChart; var callDelete_1 = this.deleteInternals; (function myLoop(k) { setTimeout(function () { var animationProgress = k / frames_1; callDelete_1(true); callDrawChart_1(animationProgress); if (k === frames_1) { setSuspendUpdateFalse_1(); setSweepAnimationDone_1(); callInvalidateElement_1(); } if (++k <= frames_1) myLoop(k); }, 20); })(1); } // ADD EVENT LISTENERS if (!app_1.IS_TEST_ENV) { this.pieSegments.asArray().forEach(function (ps) { var el = _this.domChartRoot.querySelector("[id='".concat(ps.id, "']")); if (el) { var subscriptionToken = (0, exports.addEventListenerToPieSegment)(ps, el, _this.animate); _this.addDeletable(subscriptionToken); } }); } this.rendered.raiseEvent(); }; /** * @description Draws pie chart itself * @param animationProgress - Current progress from 0 to 1, is being used for sweep animation on start. */ SciChartPieSurface.prototype.drawChart = function (animationProgress) { var _this = this; if (animationProgress === void 0) { animationProgress = 1; } var totalValue = this.pieSegmentsTotalValue(); if (!totalValue) { return; } var strokeWidth = 2; var strokeColor = this.themeProviderProperty.sciChartBackground; var segments = this.pieSegments.asArray(); var totalOldValue = this.pieSegmentsTotalOldValue(); var outerRadius = (Math.min(this.calculateViewRectWidth(this.viewRect.width), this.calculateViewRectHeight(this.viewRect.height)) * 0.8) / 2; var innerRadius = 0; if (this.pieType === EPieType.Donut) { innerRadius = this.holeRadiusSizingMode === ESizingMode.Absolute ? this.holeRadius : outerRadius * this.holeRadius; } var xCoord = this.calculateViewRectWidth(this.viewRect.width) / 2; var yCoord = this.calculateViewRectHeight(this.viewRect.height) / 2; // CREATING SVG STRING var gradientsBlock = "<defs>"; var pathsBlock = ""; var currentValue = 0; var currentOldValue = 0; segments.forEach(function (el, index) { var _a; if (el.value === 0) { return; } var oldValue = (_a = el.oldValue) !== null && _a !== void 0 ? _a : 0; var newFrom = (360 * currentValue) / totalValue - START_ANGLE; var newTo = (360 * (currentValue + el.value)) / totalValue - START_ANGLE - 0.0001; // newTo != newFrom - for only 1 segment var oldFrom = (360 * currentOldValue) / totalOldValue - START_ANGLE; var oldTo = (360 * (currentOldValue + oldValue)) / totalOldValue - START_ANGLE; currentValue += el.value; currentOldValue += oldValue; var angleFrom = oldFrom + (newFrom - oldFrom) * EasingFunctions_1.easing.inOutCubic(animationProgress); var angleTo = oldTo + (newTo - oldTo) * EasingFunctions_1.easing.inOutCubic(animationProgress); var hasGradient = !!el.colorLinearGradient; var gradientId = "grad".concat(el.id); if (hasGradient) { var x1 = el.colorLinearGradient.startPoint.x * 100; var y1 = el.colorLinearGradient.startPoint.y * 100; var x2 = el.colorLinearGradient.endPoint.x * 100; var y2 = el.colorLinearGradient.endPoint.y * 100; var gradientBlock_1 = "<linearGradient id=\"".concat(gradientId, "\" x1=\"").concat(x1, "%\" y1=\"").concat(y1, "%\" x2=\"").concat(x2, "%\" y2=\"").concat(y2, "%\">"); el.colorLinearGradient.gradientStops.forEach(function (gStop) { var offset = gStop.offset * 100; gradientBlock_1 += "<stop offset=\"".concat(offset, "%\" style=\"stop-color:").concat(gStop.color, ";stop-opacity:1\" />"); }); gradientBlock_1 += "</linearGradient>"; gradientsBlock += gradientBlock_1; } var dAttribute = _this.pieType === EPieType.Donut ? getDonutSectorPath(xCoord, yCoord, outerRadius * el.radiusAdjustment, innerRadius, angleFrom, angleTo, el.shift + _this.seriesSpacing) : getSectorPath(xCoord, yCoord, outerRadius * el.radiusAdjustment, angleFrom, angleTo, el.shift + _this.seriesSpacing); var pathBlock = hasGradient ? "<g fill=\"url(#".concat(gradientId, ")\"><path id=\"").concat(el.id, "\" stroke=\"").concat(strokeColor, "\" stroke-width=\"").concat(strokeWidth, "\" d=\"").concat(dAttribute, "\" /></g>") : "<path id=\"".concat(el.id, "\" stroke=\"").concat(strokeColor, "\" stroke-width=\"").concat(strokeWidth, "\" d=\"").concat(dAttribute, "\" fill=\"").concat(el.color, "\" />"); pathsBlock += pathBlock; if (animationProgress === 1 || el.oldValue) { _this.drawSegmentLabel(el, index, totalValue, angleFrom, angleTo, xCoord, yCoord, outerRadius * el.radiusAdjustment, innerRadius); } }); gradientsBlock += "</defs>"; this.adjustDomContainer(); var svgString = "<svg width=\"".concat(this.calculateViewRectWidth(this.viewRect.width), "\" height=\"").concat(this.calculateViewRectHeight(this.viewRect.height), "\">").concat(gradientsBlock).concat(pathsBlock, "</svg>"); // CREATING AND ATTACHING SVG TO DOM var svgNode = annotationHelpers_1.annotationHelpers.createSvg(svgString, this.domSvgContainer); this.svg = svgNode; }; SciChartPieSurface.prototype.adjustDomContainer = function () { var _a, _b, _c, _d, _e, _f; if (this.padding && this.padding.left) { this.domSvgContainer.style.paddingLeft = this.padding.left + "px"; } if (this.padding && this.padding.right) { this.domSvgContainer.style.paddingRight = this.padding.right + "px"; } if (this.padding && this.padding.top) { this.domSvgContainer.style.paddingTop = this.padding.top + "px"; } if (this.padding && this.padding.bottom) { this.domSvgContainer.style.paddingBottom = this.padding.bottom + "px"; } if (this.canvasBorder) { this.domSvgContainer.style.borderStyle = "solid"; } if ((_a = this.canvasBorder) === null || _a === void 0 ? void 0 : _a.border) { this.domSvgContainer.style.borderWidth = this.canvasBorder.border + "px"; } if ((_b = this.canvasBorder) === null || _b === void 0 ? void 0 : _b.color) { this.domSvgContainer.style.borderColor = this.canvasBorder.color; } if ((_c = this.canvasBorder) === null || _c === void 0 ? void 0 : _c.borderBottom) { this.domSvgContainer.style.borderBottomWidth = this.canvasBorder.borderBottom + "px"; } if ((_d = this.canvasBorder) === null || _d === void 0 ? void 0 : _d.borderTop) { this.domSvgContainer.style.borderTopWidth = this.canvasBorder.borderTop + "px"; } if ((_e = this.canvasBorder) === null || _e === void 0 ? void 0 : _e.borderLeft) { this.domSvgContainer.style.borderLeftWidth = this.canvasBorder.borderLeft + "px"; } if ((_f = this.canvasBorder) === null || _f === void 0 ? void 0 : _f.borderRight) { this.domSvgContainer.style.borderRightWidth = this.canvasBorder.borderRight + "px"; } }; SciChartPieSurface.prototype.drawSegmentLabel = function (el, index, totalValue, angleFrom, angleTo, xCoord, yCoord, outerRadius, innerRadius) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; if (el.showLabel === false) return; var labelDivId = "segment" + index; var div = this.titleDivs.find(function (d) { return d.id === labelDivId; }); if (!div) { div = document.createElement("div"); var labelStyle = el.labelStyle; div.className = "scichart-pie-text-container"; div.id = labelDivId; div.style.position = "absolute"; div.style.pointerEvents = "none"; div.style.padding = "5px"; div.style.borderRadius = "3px"; this.titleDivs.push(div); this.domDivContainer.appendChild(div); div.style.display = "block"; } div.style.color = el.labelStyle.color; div.style.fontWeight = el.labelStyle.fontWeight; div.style.fontFamily = el.labelStyle.fontFamily; div.style.fontSize = el.labelStyle.fontSize.toString() + "px"; div.innerHTML = el.getLabelText(totalValue); var divWidth = div.offsetWidth; var divHeight = div.offsetHeight; var leftShift = 0; var topShift = 0; if ((_a = this.padding) === null || _a === void 0 ? void 0 : _a.left) { leftShift += (_b = this.padding) === null || _b === void 0 ? void 0 : _b.left; } if ((_c = this.padding) === null || _c === void 0 ? void 0 : _c.top) { topShift += (_d = this.padding) === null || _d === void 0 ? void 0 : _d.top; } if ((_e = this.canvasBorder) === null || _e === void 0 ? void 0 : _e.border) { leftShift += (_f = this.canvasBorder) === null || _f === void 0 ? void 0 : _f.border; topShift += (_g = this.canvasBorder) === null || _g === void 0 ? void 0 : _g.border; } else { if ((_h = this.canvasBorder) === null || _h === void 0 ? void 0 : _h.borderLeft) { leftShift += (_j = this.canvasBorder) === null || _j === void 0 ? void 0 : _j.borderLeft; } if ((_k = this.canvasBorder) === null || _k === void 0 ? void 0 : _k.borderTop) { leftShift += (_l = this.canvasBorder) === null || _l === void 0 ? void 0 : _l.borderTop; } } var position = this.calcTitlePosition(xCoord + leftShift, yCoord + topShift, outerRadius, innerRadius, angleFrom, angleTo, el.shift + this.seriesSpacing, divWidth, divHeight); div.style.left = "".concat(position.left + el.labelOffset.x, "px"); div.style.top = "".concat(position.top + el.labelOffset.y, "px"); }; SciChartPieSurface.prototype.pieSegmentsTotalValue = function () { return this.pieSegments.asArray().reduce(function (prev, cur) { return prev + cur.value; }, 0); }; SciChartPieSurface.prototype.pieSegmentsTotalOldValue = function () { var total = this.pieSegments.asArray().reduce(function (prev, cur) { var _a; return prev + ((_a = cur.oldValue) !== null && _a !== void 0 ? _a : 0); }, 0); return total > 0 ? total : 1; }; SciChartPieSurface.prototype.applySciChartBackground = function (htmlColor) { this.domCanvas2D.style.background = htmlColor; }; return SciChartPieSurface; }(DeletableEntity_1.DeletableEntity)); exports.SciChartPieSurface = SciChartPieSurface; /** * @ignore * @description Create sector path string * @param x - circle x coordinate * @param y - circle y coordinate * @param outerRadius - circle radius * @param a1 - angleFrom in degrees * @param a2 - angleTo in degrees * @param delta - sector shift, is used for selected sectors */ var getSectorPath = function (x, y, outerRadius, a1, a2, delta) { var bigArc = Math.abs(a2 - a1) > 180 ? 1 : 0; var deltaAngle = (a1 + a2) / 2; var deltaX = Math.cos(DEG_TO_RAD * deltaAngle) * delta; var deltaY = Math.sin(DEG_TO_RAD * deltaAngle) * delta; var cx1 = Math.cos(DEG_TO_RAD * a2) * outerRadius + x + deltaX; var cy1 = Math.sin(DEG_TO_RAD * a2) * outerRadius + y + deltaY; var cx2 = Math.cos(DEG_TO_RAD * a1) * outerRadius + x + deltaX; var cy2 = Math.sin(DEG_TO_RAD * a1) * outerRadius + y + deltaY; if (Math.abs(cx1 - cx2) < 0.0001) { cx2 += 0.001; } return "M".concat(x + deltaX, " ").concat(y + deltaY, " ").concat(cx1, " ").concat(cy1, " A").concat(outerRadius, " ").concat(outerRadius, " 0 ").concat(bigArc, " 0 ").concat(cx2, " ").concat(cy2, "Z"); }; /** * @ignore * @description Create donut sector path string * @param x - circle x coordinate * @param y - circle y coordinate * @param outerR - circle outer radius * @param innerR - circle inner radius * @param a1 - angleFrom in degrees * @param a2 - angleTo in degrees * @param delta - sector shift, is used for selected sectors */ var getDonutSectorPath = function (x, y, outerR, innerR, a1, a2, delta) { var bigArc = Math.abs(a2 - a1) > 180 ? 1 : 0; var deltaAngle = (a1 + a2) / 2; var deltaX = Math.cos(DEG_TO_RAD * deltaAngle) * delta; var deltaY = Math.sin(DEG_TO_RAD * deltaAngle) * delta; var outerX1 = Math.cos(DEG_TO_RAD * a2) * outerR + x + deltaX; var outerY1 = Math.sin(DEG_TO_RAD * a2) * outerR + y + deltaY; var outerX2 = Math.cos(DEG_TO_RAD * a1) * outerR + x + deltaX; var outerY2 = Math.sin(DEG_TO_RAD * a1) * outerR + y + deltaY; var innerX1 = Math.cos(DEG_TO_RAD * a2) * innerR + x + deltaX; var innerY1 = Math.sin(DEG_TO_RAD * a2) * innerR + y + deltaY; var innerX2 = Math.cos(DEG_TO_RAD * a1) * innerR + x + deltaX; var innerY2 = Math.sin(DEG_TO_RAD * a1) * innerR + y + deltaY; return "M".concat(outerX1, " ").concat(outerY1, " A").concat(outerR, " ").concat(outerR, " 0 ").concat(bigArc, " 0 ").concat(outerX2, " ").concat(outerY2, " L").concat(innerX2, " ").concat(innerY2, " A").concat(innerR, " ").concat(innerR, " 0 ").concat(bigArc, " 1 ").concat(innerX1, " ").concat(innerY1, "Z"); }; /** @ignore */ var isListenerBlocked = false; /** @ignore */ var addEventListenerToPieSegment = function (ps, el, animate) { var eventListener = function (e) { if (!animate) { ps.isSelected = !ps.isSelected; return; } // ANIMATE if (!isListenerBlocked) { var ROUNDS_1 = 10; var directionDown = ps.isSelected; var start_1 = directionDown ? ps.delta : 0; var d_1 = directionDown ? -ps.delta / ROUNDS_1 : ps.delta / ROUNDS_1; isListenerBlocked = true; ps.isSelected = !ps.isSelected; (function myLoop(k) { setTimeout(function () { ps.shift = start_1 + d_1 * k; if (k === ROUNDS_1) { isListenerBlocked = false; } if (++k <= ROUNDS_1) myLoop(k); }, 20); })(1); } }; el.addEventListener("click", eventListener); return { eventListener: eventListener, eventType: "click", element: el, delete: function () { return el.removeEventListener("click", eventListener); } }; }; exports.addEventListenerToPieSegment = addEventListenerToPieSegment;