UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

479 lines (469 loc) • 18.3 kB
/** * DevExtreme (viz/pie_chart.js) * Version: 20.1.7 * Build date: Tue Aug 25 2020 * * Copyright (c) 2012 - 2020 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; var _consts = require("./components/consts"); var _utils = require("./core/utils"); var _extend2 = require("../core/utils/extend"); var _type = require("../core/utils/type"); var _iterator = require("../core/utils/iterator"); var _range = require("./translators/range"); var _range2 = _interopRequireDefault(_range); var _component_registrator = require("../core/component_registrator"); var _component_registrator2 = _interopRequireDefault(_component_registrator); var _base_chart = require("./chart_components/base_chart"); var _common = require("../core/utils/common"); var _translator1d = require("./translators/translator1d"); var _translator1d2 = _interopRequireDefault(_translator1d); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj } } var OPTIONS_FOR_REFRESH_SERIES = ["startAngle", "innerRadius", "segmentsDirection", "type"]; var NORMAL_STATE = _consts.states.normalMark; var HOVER_STATE = _consts.states.hoverMark; var SELECTED_STATE = _consts.states.selectedMark; var MAX_RESOLVE_ITERATION_COUNT = 5; var LEGEND_ACTIONS = [_consts.states.resetItem, _consts.states.applyHover, _consts.states.applySelected, _consts.states.applySelected]; function getLegendItemAction(points) { var state = NORMAL_STATE; points.forEach(function(point) { var _point$series; var seriesOptions = null === (_point$series = point.series) || void 0 === _point$series ? void 0 : _point$series.getOptions(); var pointState = point.fullState; if ("none" === (null === seriesOptions || void 0 === seriesOptions ? void 0 : seriesOptions.hoverMode)) { pointState &= ~HOVER_STATE } if ("none" === (null === seriesOptions || void 0 === seriesOptions ? void 0 : seriesOptions.selectionMode)) { pointState &= ~SELECTED_STATE } state |= pointState }); return LEGEND_ACTIONS[state] } function correctPercentValue(value) { if ((0, _type.isNumeric)(value)) { if (value > 1) { value = 1 } else { if (value < 0) { value = 0 } } } else { value = void 0 } return value } var pieSizeEqualizer = function() { function equalize(group, allPies) { var pies = allPies.filter(function(p) { return p._isVisible() && p.getSizeGroup() === group }); var minRadius = Math.min.apply(null, pies.map(function(p) { return p.getSizeGroupLayout().radius })); var minPie = pies.filter(function(p) { return p.getSizeGroupLayout().radius === minRadius }); pies.forEach(function(p) { return p.render({ force: true, sizeGroupLayout: minPie.length ? minPie[0].getSizeGroupLayout() : {} }) }) } function removeFromList(list, item) { return list.filter(function(li) { return li !== item }) } function addToList(list, item) { return removeFromList(list, item).concat(item) } var pies = []; var timers = {}; return { queue: function(pie) { var group = pie.getSizeGroup(); pies = addToList(pies, pie); clearTimeout(timers[group]); timers[group] = setTimeout(function() { equalize(group, pies) }) }, remove: function(pie) { pies = removeFromList(pies, pie); if (!pies.length) { timers = {} } } } }(); var dxPieChart = _base_chart.BaseChart.inherit({ _themeSection: "pie", _layoutManagerOptions: function() { return (0, _extend2.extend)(true, {}, this.callBase(), { piePercentage: correctPercentValue(this._themeManager.getOptions("diameter")), minPiePercentage: correctPercentValue(this._themeManager.getOptions("minDiameter")) }) }, _optionChangesMap: { diameter: "REINIT", minDiameter: "REINIT", sizeGroup: "REINIT" }, _disposeCore: function() { pieSizeEqualizer.remove(this); this.callBase() }, _groupSeries: function() { var series = this.series; this._groupsData = { groups: [{ series: series, valueOptions: { valueType: "numeric" } }], argumentOptions: series[0] && series[0].getOptions() } }, getArgumentAxis: function() { return null }, _getValueAxis: function() { var translator = (new _translator1d2.default.Translator1D).setCodomain(360, 0); return { getTranslator: function() { return translator }, setBusinessRange: function(range) { translator.setDomain(range.min, range.max) } } }, _populateBusinessRange: function() { this.series.map(function(series) { var range = new _range2.default.Range; range.addRange(series.getRangeData().val); series.getValueAxis().setBusinessRange(range); return range }) }, _specialProcessSeries: function() { (0, _iterator.each)(this.series, function(_, singleSeries) { singleSeries.arrangePoints() }) }, _checkPaneName: function() { return true }, _processSingleSeries: function(singleSeries) { this.callBase(singleSeries); singleSeries.arrangePoints() }, _handleSeriesDataUpdated: function() { var maxPointCount = 0; this.series.forEach(function(s) { maxPointCount = Math.max(s.getPointsCount(), maxPointCount) }); this.series.forEach(function(s) { s.setMaxPointsCount(maxPointCount) }); this.callBase() }, _getLegendOptions: function(item) { var legendItem = this.callBase(item); var legendData = legendItem.legendData; legendData.argument = item.argument; legendData.argumentIndex = item.argumentIndex; legendData.points = [item]; return legendItem }, _getLegendTargets: function() { var that = this; var itemsByArgument = {}; (that.series || []).forEach(function(series) { series.getPoints().forEach(function(point) { var argument = point.argument.valueOf(); var index = series.getPointsByArg(argument).indexOf(point); var key = argument.valueOf().toString() + index; itemsByArgument[key] = itemsByArgument[key] || []; var argumentCount = itemsByArgument[key].push(point); point.index = itemsByArgument[key][argumentCount - 2] ? itemsByArgument[key][argumentCount - 2].index : Object.keys(itemsByArgument).length - 1; point.argumentIndex = index }) }); var items = []; (0, _iterator.each)(itemsByArgument, function(_, points) { points.forEach(function(point, index) { if (0 === index) { items.push(that._getLegendOptions(point)); return } var item = items[items.length - 1]; item.legendData.points.push(point); if (!item.visible) { item.visible = point.isVisible() } }) }); return items }, _getLayoutTargets: function() { return [{ canvas: this._canvas }] }, _getLayoutSeries: function(series, drawOptions) { var that = this; var layout; var canvas = that._canvas; var drawnLabels = false; layout = that.layoutManager.applyPieChartSeriesLayout(canvas, series, true); series.forEach(function(singleSeries) { singleSeries.correctPosition(layout, canvas); drawnLabels = singleSeries.drawLabelsWOPoints() || drawnLabels }); if (drawnLabels) { layout = that.layoutManager.applyPieChartSeriesLayout(canvas, series, drawOptions.hideLayoutLabels) } series.forEach(function(singleSeries) { singleSeries.hideLabels() }); that._sizeGroupLayout = { x: layout.centerX, y: layout.centerY, radius: layout.radiusOuter, drawOptions: drawOptions }; return layout }, _getLayoutSeriesForEqualPies: function(series, sizeGroupLayout) { var canvas = this._canvas; var layout = this.layoutManager.applyEqualPieChartLayout(series, sizeGroupLayout); series.forEach(function(s) { s.correctPosition(layout, canvas); s.drawLabelsWOPoints() }); this.layoutManager.correctPieLabelRadius(series, layout, canvas); return layout }, _updateSeriesDimensions: function(drawOptions) { var that = this; var visibleSeries = that._getVisibleSeries(); var lengthVisibleSeries = visibleSeries.length; var innerRad; var delta; var layout; var sizeGroupLayout = drawOptions.sizeGroupLayout; if (lengthVisibleSeries) { layout = sizeGroupLayout ? that._getLayoutSeriesForEqualPies(visibleSeries, sizeGroupLayout) : that._getLayoutSeries(visibleSeries, drawOptions); delta = (layout.radiusOuter - layout.radiusInner - _consts.pieSeriesSpacing * (lengthVisibleSeries - 1)) / lengthVisibleSeries; innerRad = layout.radiusInner; that._setGeometry(layout); visibleSeries.forEach(function(singleSeries) { singleSeries.correctRadius({ radiusInner: innerRad, radiusOuter: innerRad + delta }); innerRad += delta + _consts.pieSeriesSpacing }) } }, _renderSeries: function(drawOptions, isRotated, isLegendInside) { this._calculateSeriesLayout(drawOptions, isRotated); if (!drawOptions.sizeGroupLayout && this.getSizeGroup()) { pieSizeEqualizer.queue(this); this._clearCanvas(); return } this._renderSeriesElements(drawOptions, isLegendInside) }, _renderExtraElements: function() { var _this = this; var template = this.option("centerTemplate"); if (this._centerTemplateGroup) { this._centerTemplateGroup.clear() } if (!template) { return } if (!this._centerTemplateGroup) { this._centerTemplateGroup = this._renderer.g().attr({ "class": "dxc-hole-template" }).css((0, _utils.patchFontOptions)(this._themeManager._font)) } this._centerTemplateGroup.append(this._renderer.root); template = this._getTemplate(template); template.render({ model: this, container: this._centerTemplateGroup.element, onRendered: function() { var bBox = _this._centerTemplateGroup.getBBox(); _this._centerTemplateGroup.move(_this._center.x - (bBox.x + bBox.width / 2), _this._center.y - (bBox.y + bBox.height / 2)) } }) }, getInnerRadius: function() { return this._innerRadius }, _getLegendCallBack: function() { var that = this; var legend = this._legend; var items = this._getLegendTargets().map(function(i) { return i.legendData }); return function(target) { items.forEach(function(data) { var points = []; var callback = legend.getActionCallback({ index: data.id }); that.series.forEach(function(series) { var seriesPoints = series.getPointsByKeys(data.argument, data.argumentIndex); points.push.apply(points, seriesPoints) }); if (target && target.argument === data.argument && target.argumentIndex === data.argumentIndex) { points.push(target) } callback(getLegendItemAction(points)) }) } }, _locateLabels: function(resolveLabelOverlapping) { var iterationCount = 0; var labelsWereOverlapped; var wordWrapApplied; do { wordWrapApplied = this._adjustSeriesLabels("shift" === resolveLabelOverlapping); labelsWereOverlapped = this._resolveLabelOverlapping(resolveLabelOverlapping) } while ((labelsWereOverlapped || wordWrapApplied) && ++iterationCount < MAX_RESOLVE_ITERATION_COUNT) }, _adjustSeriesLabels: function(moveLabelsFromCenter) { return this.series.reduce(function(r, s) { return s.adjustLabels(moveLabelsFromCenter) || r }, false) }, _applyExtraSettings: _common.noop, _resolveLabelOverlappingShift: function() { var that = this; var inverseDirection = "anticlockwise" === that.option("segmentsDirection"); var seriesByPosition = that.series.reduce(function(r, s) { (r[s.getOptions().label.position] || r.outside).push(s); return r }, { inside: [], columns: [], outside: [] }); var labelsOverlapped = false; if (seriesByPosition.inside.length > 0) { labelsOverlapped = resolve(seriesByPosition.inside.reduce(function(r, singleSeries) { return singleSeries.getVisiblePoints().reduce(function(r, point) { r.left.push(point); return r }, r) }, { left: [], right: [] }), shiftInColumnFunction) || labelsOverlapped } labelsOverlapped = seriesByPosition.columns.reduce(function(r, singleSeries) { return resolve(dividePoints(singleSeries), shiftInColumnFunction) || r }, labelsOverlapped); if (seriesByPosition.outside.length > 0) { labelsOverlapped = resolve(seriesByPosition.outside.reduce(function(r, singleSeries) { return dividePoints(singleSeries, r) }, null), shiftFunction) || labelsOverlapped } return labelsOverlapped; function dividePoints(series, points) { return series.getVisiblePoints().reduce(function(r, point) { var angle = (0, _utils.normalizeAngle)(point.middleAngle); (angle <= 90 || angle >= 270 ? r.right : r.left).push(point); return r }, points || { left: [], right: [] }) } function resolve(points, shiftCallback) { var overlapped = false; if (inverseDirection) { points.left.reverse(); points.right.reverse() } overlapped = _base_chart.overlapping.resolveLabelOverlappingInOneDirection(points.left, that._canvas, false, shiftCallback); return _base_chart.overlapping.resolveLabelOverlappingInOneDirection(points.right, that._canvas, false, shiftCallback) || overlapped } function shiftFunction(box, length) { return (0, _utils.getVerticallyShiftedAngularCoords)(box, -length, that._center) } function shiftInColumnFunction(box, length) { return { x: box.x, y: box.y - length } } }, _setGeometry: function(_ref) { var x = _ref.centerX, y = _ref.centerY, radiusInner = _ref.radiusInner; this._center = { x: x, y: y }; this._innerRadius = radiusInner }, _disposeSeries: function(seriesIndex) { this.callBase.apply(this, arguments); this._abstractSeries = null }, _legendDataField: "point", _legendItemTextField: "argument", _applyPointMarkersAutoHiding: _common.noop, _renderTrackers: _common.noop, _trackerType: "PieTracker", _createScrollBar: _common.noop, _updateAxesLayout: _common.noop, _applyClipRects: _common.noop, _appendAdditionalSeriesGroups: _common.noop, _prepareToRender: _common.noop, _isLegendInside: _common.noop, _renderAxes: _common.noop, _shrinkAxes: _common.noop, _isRotated: _common.noop, _seriesPopulatedHandlerCore: _common.noop, _reinitAxes: _common.noop, _correctAxes: _common.noop, _getExtraOptions: function() { var that = this; return { startAngle: that.option("startAngle"), innerRadius: that.option("innerRadius"), segmentsDirection: that.option("segmentsDirection"), type: that.option("type") } }, getSizeGroup: function() { return this._themeManager.getOptions("sizeGroup") }, getSizeGroupLayout: function() { return this._sizeGroupLayout || {} } }); (0, _iterator.each)(OPTIONS_FOR_REFRESH_SERIES, function(_, name) { dxPieChart.prototype._optionChangesMap[name] = "REFRESH_SERIES_DATA_INIT" }); (0, _component_registrator2.default)("dxPieChart", dxPieChart); module.exports = dxPieChart; module.exports.default = module.exports;