UNPKG

@amcharts/amcharts4

Version:
519 lines 18.2 kB
/** * Defines Pie Chart Series. */ import { __extends } from "tslib"; /** * ============================================================================ * IMPORTS * ============================================================================ * @hidden */ import { PercentSeries, PercentSeriesDataItem } from "./PercentSeries"; import { Slice } from "../../core/elements/Slice"; //import { Slice3D } from "../../core/elements/3D/Slice3D"; import { AxisLabelCircular } from "../axes/AxisLabelCircular"; import { PieTick } from "../elements/PieTick"; import { registry } from "../../core/Registry"; import * as $math from "../../core/utils/Math"; import * as $type from "../../core/utils/Type"; import { Percent, percent } from "../../core/utils/Percent"; /** * ============================================================================ * DATA ITEM * ============================================================================ * @hidden */ //@todo: sequenced? /** * Defines a [[DataItem]] for [[PieSeries]]. * * @see {@link DataItem} */ var PieSeriesDataItem = /** @class */ (function (_super) { __extends(PieSeriesDataItem, _super); /** * Constructor */ function PieSeriesDataItem() { var _this = _super.call(this) || this; _this.className = "PieSeriesDataItem"; _this.values.radiusValue = {}; _this.applyTheme(); return _this; } Object.defineProperty(PieSeriesDataItem.prototype, "radiusValue", { /** * @return Radius */ get: function () { return this.values.radiusValue.value; }, /** * Slice's radius, if other than default. * * @param value Radius */ set: function (value) { this.setValue("radiusValue", value); }, enumerable: true, configurable: true }); /** * Hide the data item (and corresponding visual elements). * * @param duration Duration (ms) * @param delay Delay hiding (ms) * @param toValue Target value for animation * @param fields Fields to animate while hiding */ PieSeriesDataItem.prototype.hide = function (duration, delay, toValue, fields) { return _super.prototype.hide.call(this, duration, delay, 0, ["value", "radiusValue"]); }; /** * Show hidden data item (and corresponding visual elements). * * @param duration Duration (ms) * @param delay Delay hiding (ms) * @param fields Fields to animate while hiding */ PieSeriesDataItem.prototype.show = function (duration, delay, fields) { return _super.prototype.show.call(this, duration, delay, ["value", "radiusValue"]); }; return PieSeriesDataItem; }(PercentSeriesDataItem)); export { PieSeriesDataItem }; /** * ============================================================================ * MAIN CLASS * ============================================================================ * @hidden */ /** * Defines [[Series]] for a slice series on a Pie chart. * * @see {@link IPieSeriesEvents} for a list of available Events * @see {@link IPieSeriesAdapters} for a list of available Adapters * @todo Example * @important */ var PieSeries = /** @class */ (function (_super) { __extends(PieSeries, _super); /** * Constructor */ function PieSeries() { var _this = _super.call(this) || this; _this.className = "PieSeries"; _this.alignLabels = true; //this.startAngle = -90; //this.endAngle = 270; _this.layout = "none"; _this.labels.template.radius = percent(5); _this.addDisposer(_this.labels.template.events.on("enabled", _this.invalidate, _this, false)); _this.applyTheme(); return _this; } /** * creates slice */ PieSeries.prototype.createSlice = function () { return new Slice(); }; /** * creates tick */ PieSeries.prototype.createTick = function () { return new PieTick(); }; /** * creates label */ PieSeries.prototype.createLabel = function () { return new AxisLabelCircular(); }; /** * Sets defaults that instantiate some objects that rely on parent, so they * cannot be set in constructor. */ PieSeries.prototype.applyInternalDefaults = function () { _super.prototype.applyInternalDefaults.call(this); if (!$type.hasValue(this.readerTitle)) { this.readerTitle = this.language.translate("Pie Slice Series"); } }; /** * Returns a new/empty DataItem of the type appropriate for this object. * * @see {@link DataItem} * @return Data Item */ PieSeries.prototype.createDataItem = function () { return new PieSeriesDataItem(); }; /** * Inits slice. * * @param slice to init */ PieSeries.prototype.initSlice = function (slice) { slice.isMeasured = false; slice.defaultState.properties.scale = 1; slice.observe("scale", this.handleSliceScale, this); slice.observe(["dx", "dy", "x", "y", "shiftRadius"], this.handleSliceMove, this); slice.tooltipText = "{category}: {value.percent.formatNumber('#.#p')} ({value.value})"; var hoverState = slice.states.create("hover"); hoverState.properties.scale = 1.05; var defaultState = slice.defaultState; defaultState.properties.shiftRadius = 0; slice.togglable = true; slice.events.on("toggled", function (event) { event.target.hideTooltip(); // The following takes care of removing hover on subsequent click of // a slice if (event.target.interactions.lastHitPointer && event.target.interactions.lastHitPointer.touch && !event.target.isActive) { event.target.isHover = false; } }); var activeState = slice.states.create("active"); activeState.properties.shiftRadius = 0.10; }; /** * (Re)validates the whole series, effectively causing it to redraw. * * @ignore Exclude from docs */ PieSeries.prototype.validate = function () { this._leftItems = []; this._rightItems = []; this._currentStartAngle = this.startAngle; this._arcRect = $math.getArcRect(this.startAngle, this.endAngle); this._maxRadiusPercent = 0; for (var i = this.startIndex; i < this.endIndex; i++) { var dataItem = this.dataItems.getIndex(i); var radiusValuePercent = dataItem.values.radiusValue.percent; if (radiusValuePercent > this._maxRadiusPercent) { this._maxRadiusPercent = radiusValuePercent; } } _super.prototype.validate.call(this); if (this.alignLabels) { if (this.startAngle > this.endAngle) { this._rightItems.reverse(); } else { this._leftItems.reverse(); } this._rightItems.sort(function (a, b) { var aAngle = (a.slice.middleAngle + 360) % 360; var bAngle = (b.slice.middleAngle + 360) % 360; if (aAngle > 270) { aAngle -= 360; } if (bAngle > 270) { bAngle -= 360; } if (aAngle < bAngle) { return -1; } else if (aAngle > bAngle) { return 1; } else { return 0; } }); this._leftItems.sort(function (a, b) { var aAngle = (a.slice.middleAngle + 360) % 360; var bAngle = (b.slice.middleAngle + 360) % 360; if (aAngle < bAngle) { return 1; } else if (aAngle > bAngle) { return -1; } else { return 0; } }); this.arrangeLabels(this._rightItems); this.arrangeLabels2(this._rightItems); this.arrangeLabels(this._leftItems); this.arrangeLabels2(this._leftItems); } }; /** * Validates data item's element, effectively redrawing it. * * @ignore Exclude from docs * @param dataItem Data item */ PieSeries.prototype.validateDataElement = function (dataItem) { if (this.pixelRadius > 0) { if (this.ignoreZeroValues && (dataItem.value == 0 || dataItem.value == null)) { dataItem.__disabled = true; } else { dataItem.__disabled = false; } // SLICE var slice = dataItem.slice; slice.radius = this.pixelRadius; if ($type.isNumber(dataItem.radiusValue)) { slice.radius = this.pixelInnerRadius + (this.pixelRadius - this.pixelInnerRadius) * dataItem.values.radiusValue.percent / this._maxRadiusPercent; } if (!(slice.innerRadius instanceof Percent)) { slice.innerRadius = this.pixelInnerRadius; } slice.startAngle = this._currentStartAngle; slice.arc = Math.abs(dataItem.values.value.percent) * (this.endAngle - this.startAngle) / 100; // LABEL if (!this.labels.template.disabled) { var label = dataItem.label; var tick = dataItem.tick; tick.slice = slice; tick.label = label; var normalizedMiddleAngle = (slice.middleAngle + 360) % 360; // force angle to be 0 - 360; var point = void 0; if (this.alignLabels) { var labelRadius = label.pixelRadius(slice.radius); var x = tick.length + labelRadius; label.dx = 0; label.dy = 0; label.verticalCenter = "middle"; var arcRect = this._arcRect; // right half if (normalizedMiddleAngle > 270 || normalizedMiddleAngle <= 90) { x += (arcRect.width + arcRect.x) * this.pixelRadius; label.horizontalCenter = "left"; this._rightItems.push(dataItem); } // left half else { x -= arcRect.x * this.pixelRadius; label.horizontalCenter = "right"; this._leftItems.push(dataItem); x *= -1; } var distance = slice.radius + tick.length + labelRadius; point = { x: x, y: slice.iy * distance }; label.moveTo(point); } else { var depth = slice["depth"]; if (!$type.isNumber(depth)) { depth = 0; } label.fixPosition(slice.middleAngle, slice.radius, slice.radiusY, 0, -depth); } } this._currentStartAngle += slice.arc; // do this at the end, otherwise bullets won't be positioned properly _super.prototype.validateDataElement.call(this, dataItem); } }; Object.defineProperty(PieSeries.prototype, "radius", { /** * @return Radius */ get: function () { return this.getPropertyValue("radius"); }, /** * Outer radius for the series' slices in pixels or [[Percent]]. * * @param value Radius */ set: function (value) { if (this.setPercentProperty("radius", value, true, false, 10, false)) { this.invalidateDataItems(); } }, enumerable: true, configurable: true }); Object.defineProperty(PieSeries.prototype, "pixelRadius", { /** * @return Radius * @ignore */ get: function () { return this._pixelRadius; }, /** * @ignore */ set: function (value) { if (this._pixelRadius != value) { this._pixelRadius = value; this.invalidateDataItems(); } }, enumerable: true, configurable: true }); Object.defineProperty(PieSeries.prototype, "pixelInnerRadius", { /** * @return Pixel inner radius * @ignore */ get: function () { return this._pixelInnerRadius; }, /** * @ignore */ set: function (value) { if (this._pixelInnerRadius != value) { this._pixelInnerRadius = value; this.invalidateDataItems(); } }, enumerable: true, configurable: true }); Object.defineProperty(PieSeries.prototype, "innerRadius", { /** * @ignore Exclude from docs * @return Radius */ get: function () { return this.getPropertyValue("innerRadius"); }, /** * Inner radius for the series' slices in pixels. * * @ignore Exclude from docs * @todo Redo so that users can set it * @param value Radius */ set: function (value) { this.setPercentProperty("innerRadius", value, true, false, 10, false); }, enumerable: true, configurable: true }); Object.defineProperty(PieSeries.prototype, "startAngle", { /** * @return Angle */ get: function () { var startAngle = this.getPropertyValue("startAngle"); if ($type.isNumber(startAngle)) { return startAngle; } else { return this._startAngleInternal; } }, /** * Start angle for the series' slices in degrees. (0-360) * * @param value Angle */ set: function (value) { this.setPropertyValue("startAngle", $math.normalizeAngle(value), true); }, enumerable: true, configurable: true }); Object.defineProperty(PieSeries.prototype, "endAngle", { /** * @return Angle */ get: function () { var endAngle = this.getPropertyValue("endAngle"); if ($type.isNumber(endAngle)) { return endAngle; } else { return this._endAngleInternal; } }, /** * End angle for the series' slices in degrees. (0-360) * * @param value Angle */ set: function (value) { this.setPropertyValue("endAngle", value, true); }, enumerable: true, configurable: true }); /** * Positions series bullet. * * @ignore Exclude from docs * @param bullet Bullet */ PieSeries.prototype.positionBullet = function (bullet) { _super.prototype.positionBullet.call(this, bullet); var dataItem = bullet.dataItem; var slice = dataItem.slice; var locationX = bullet.locationX; if (!$type.isNumber(locationX)) { locationX = 0.5; } var locationY = bullet.locationY; if (!$type.isNumber(locationY)) { locationY = 1; } var angle = slice.startAngle + slice.arc * locationX; bullet.x = locationY * slice.radius * $math.cos(angle); bullet.y = locationY * slice.radiusY * $math.sin(angle); }; /** * Repositions bullet and labels when slice moves. * * @ignore Exclude from docs * @param event Event */ PieSeries.prototype.handleSliceMove = function (event) { if (!this.alignLabels) { var slice = event.target; var dataItem = slice.dataItem; // moving textelement, as label dx and dy are already employed for aligning //@labeltodo if (dataItem) { var label = dataItem.label; if (label) { label.dx = label.fdx + slice.dx + slice.pixelX; label.dy = label.fdy + slice.dy + slice.pixelY; } } } }; Object.defineProperty(PieSeries.prototype, "bbox", { /** * Returns bounding box (square) for this element. * * @ignore Exclude from docs */ get: function () { if (this.definedBBox) { return this.definedBBox; } var chart = this.chart; if (chart) { return $math.getArcRect(chart.startAngle, chart.endAngle, this.pixelRadius); } return $math.getArcRect(this.startAngle, this.endAngle, this.pixelRadius); }, enumerable: true, configurable: true }); return PieSeries; }(PercentSeries)); export { PieSeries }; /** * bboxter class in system, so that it can be instantiated using its name from * anywhere. * * @ignore */ registry.registeredClasses["PieSeries"] = PieSeries; registry.registeredClasses["PieSeriesDataItem"] = PieSeriesDataItem; //# sourceMappingURL=PieSeries.js.map