devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
475 lines (383 loc) • 15.4 kB
JavaScript
var errors = require("../core/errors"),
seriesConsts = require("./components/consts"),
vizUtils = require("./core/utils"),
extend = require("../core/utils/extend").extend,
isNumeric = require("../core/utils/type").isNumeric,
each = require("../core/utils/iterator").each,
rangeModule = require("./translators/range"),
registerComponent = require("../core/component_registrator"),
baseChartModule = require("./chart_components/base_chart"),
BaseChart = baseChartModule.BaseChart,
overlapping = baseChartModule.overlapping,
seriesSpacing = seriesConsts.pieSeriesSpacing,
translator1DModule = require("./translators/translator1d"),
OPTIONS_FOR_REFRESH_SERIES = ["startAngle", "innerRadius", "segmentsDirection", "type"],
_extend = extend,
_each = each,
_noop = require("../core/utils/common").noop,
_getVerticallyShiftedAngularCoords = require("./core/utils").getVerticallyShiftedAngularCoords,
states = seriesConsts.states,
NORMAL_STATE = states.normalMark,
LEGEND_ACTIONS = [states.resetItem, states.applyHover, states.applySelected, states.applySelected];
function getLegendItemAction(points) {
var state = NORMAL_STATE;
points.forEach(function (point) {
state = state | point.fullState;
});
return LEGEND_ACTIONS[state];
}
function correctPercentValue(value) {
if (isNumeric(value)) {
if (value > 1) {
value = 1;
} else if (value < 0) {
value = 0;
}
} else {
value = undefined;
}
return value;
}
var dxPieChart = BaseChart.inherit({
_setDeprecatedOptions: function _setDeprecatedOptions() {
this.callBase.apply(this, arguments);
_extend(this._deprecatedOptions, {
"series.innerRadius": { since: "15.2", message: "Use the 'innerRadius' option instead" },
"series.startAngle": { since: "15.2", message: "Use the 'startAngle' option instead" },
"series.segmentsDirection": { since: "15.2", message: "Use the 'segmentsDirection' option instead" },
"series.type": { since: "15.2", message: "Use the 'type' option instead" }
});
},
_chartType: "pie",
_layoutManagerOptions: function _layoutManagerOptions() {
return _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 _disposeCore() {
pieSizeEqualizer.remove(this);
this.callBase();
},
_groupSeries: function _groupSeries() {
var series = this.series;
this._groupsData = {
groups: [{
series: series,
valueOptions: { valueType: "numeric" }
}],
argumentOptions: series[0] && series[0].getOptions()
};
},
_getArgumentAxis: function _getArgumentAxis() {
return null;
},
_getValueAxis: function _getValueAxis() {
var translator = new translator1DModule.Translator1D().setCodomain(360, 0);
return {
getTranslator: function getTranslator() {
return translator;
},
setBusinessRange: function setBusinessRange(range) {
translator.setDomain(range.min, range.max);
}
};
},
_populateBusinessRange: function _populateBusinessRange() {
this.businessRanges = this.series.map(function (series) {
var range = new rangeModule.Range();
range.addRange(series.getRangeData().val);
if (!range.isDefined()) {
range.setStubData();
}
series.getValueAxis().setBusinessRange(range);
return range;
});
},
_specialProcessSeries: function _specialProcessSeries() {
_each(this.series, function (_, singleSeries) {
singleSeries.arrangePoints();
});
},
_checkPaneName: function _checkPaneName() {
return true;
},
_processSingleSeries: function _processSingleSeries(singleSeries) {
this.callBase(singleSeries);
singleSeries.arrangePoints();
},
_handleSeriesDataUpdated: function _handleSeriesDataUpdated() {
var maxPointCount = 0;
this.series.forEach(function (s) {
maxPointCount = Math.max(s.getPointsCount(), maxPointCount);
});
this.series.forEach(function (s) {
s.setMaxPointsCount(maxPointCount);
});
this.callBase();
},
_getLegendTargets: function _getLegendTargets() {
var that = this,
itemsByArgument = {},
items = [];
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;
});
});
_each(itemsByArgument, function (_, points) {
points.forEach(function (point, index) {
if (index === 0) {
items.push(that._getLegendOptions(point));
} else if (!items[items.length - 1].visible) {
items[items.length - 1].visible = point.isVisible();
}
});
});
return items;
},
_getLayoutTargets: function _getLayoutTargets() {
return [{ canvas: this._canvas }];
},
_getLayoutSeries: function _getLayoutSeries(series, drawOptions) {
var that = this,
layout,
canvas = that._canvas,
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 _getLayoutSeriesForEqualPies(series, sizeGroupLayout) {
var canvas = this._canvas,
layout = this.layoutManager.applyEqualPieChartLayout(series, sizeGroupLayout);
series.forEach(function (s) {
s.correctPosition(layout, canvas);
});
return layout;
},
_updateSeriesDimensions: function _updateSeriesDimensions(drawOptions) {
var that = this,
visibleSeries = that._getVisibleSeries(),
lengthVisibleSeries = visibleSeries.length,
innerRad,
delta,
layout,
sizeGroupLayout = drawOptions.sizeGroupLayout;
if (lengthVisibleSeries) {
layout = sizeGroupLayout ? that._getLayoutSeriesForEqualPies(visibleSeries, sizeGroupLayout) : that._getLayoutSeries(visibleSeries, drawOptions);
delta = (layout.radiusOuter - layout.radiusInner - seriesSpacing * (lengthVisibleSeries - 1)) / lengthVisibleSeries;
innerRad = layout.radiusInner;
that._setCenter({ x: layout.centerX, y: layout.centerY });
_each(visibleSeries, function (_, singleSeries) {
singleSeries.correctRadius({ radiusInner: innerRad, radiusOuter: innerRad + delta });
innerRad += delta + seriesSpacing;
});
}
},
_renderSeries: function _renderSeries(drawOptions, isRotated, isLegendInside) {
this._calculateSeriesLayout(drawOptions, isRotated);
if (!drawOptions.sizeGroupLayout && this.getSizeGroup()) {
pieSizeEqualizer.queue(this);
this._clearCanvas();
return;
}
this._renderSeriesElements(drawOptions, isRotated, isLegendInside);
},
_getLegendCallBack: function _getLegendCallBack() {
var that = this,
legend = this._legend,
items = this._getLegendTargets().map(function (i) {
return i.legendData;
});
return function (target) {
items.forEach(function (data) {
var points = [],
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));
});
};
},
_adjustSeriesLabels: function _adjustSeriesLabels(moveLabelsFromCenter) {
this.series.forEach(function (series) {
series.adjustLabels(moveLabelsFromCenter);
});
},
_prepareStackPoints: _noop,
_resetStackPoints: _noop,
_applyExtraSettings: _noop,
_resolveLabelOverlappingShift: function _resolveLabelOverlappingShift() {
var that = this,
inverseDirection = that.option("segmentsDirection") === "anticlockwise",
seriesByPosition = that.series.reduce(function (r, s) {
(r[s.getOptions().label.position] || r.outside).push(s);
return r;
}, { inside: [], columns: [], outside: [] });
if (seriesByPosition.inside.length > 0) {
resolve(seriesByPosition.inside.reduce(function (r, singleSeries) {
return singleSeries.getVisiblePoints().reduce(function (r, point) {
r.left.push(point);
return r;
}, r);
}, { left: [], right: [] }), shiftInColumnFunction);
}
seriesByPosition.columns.forEach(function (singleSeries) {
resolve(dividePoints(singleSeries), shiftInColumnFunction);
});
if (seriesByPosition.outside.length > 0) {
resolve(seriesByPosition.outside.reduce(function (r, singleSeries) {
return dividePoints(singleSeries, r);
}, null), shiftFunction);
that._adjustSeriesLabels(true);
}
function dividePoints(series, points) {
return series.getVisiblePoints().reduce(function (r, point) {
var angle = vizUtils.normalizeAngle(point.middleAngle);
(angle <= 90 || angle >= 270 ? r.right : r.left).push(point);
return r;
}, points || { left: [], right: [] });
}
function resolve(points, shiftCallback) {
if (inverseDirection) {
points.left.reverse();
points.right.reverse();
}
overlapping.resolveLabelOverlappingInOneDirection(points.left, that._canvas, false, shiftCallback);
overlapping.resolveLabelOverlappingInOneDirection(points.right, that._canvas, false, shiftCallback);
}
function shiftFunction(box, length) {
return _getVerticallyShiftedAngularCoords(box, -length, that._center);
}
function shiftInColumnFunction(box, length) {
return { x: box.x, y: box.y - length };
}
},
_setCenter: function _setCenter(center) {
this._center = center;
},
_disposeSeries: function _disposeSeries() {
this.callBase.apply(this, arguments);
this._abstractSeries = null;
},
// DEPRECATED_15_2
getSeries: function getSeries() {
errors.log("W0002", "dxPieChart", "getSeries", "15.2", "Use the 'getAllSeries' method instead");
return this.series[0];
},
_legendDataField: "point",
_legendItemTextField: "argument",
_updateLegendPosition: _noop,
_renderTrackers: _noop,
_trackerType: "PieTracker",
_createScrollBar: _noop,
_updateAxesLayout: _noop,
_applyClipRects: _noop,
_appendAdditionalSeriesGroups: _noop,
_prepareToRender: _noop,
_isLegendInside: _noop,
_renderAxes: _noop,
_shrinkAxes: _noop,
_isRotated: _noop,
_seriesPopulatedHandlerCore: _noop,
_reinitAxes: _noop,
_correctAxes: _noop,
_getExtraOptions: function _getExtraOptions() {
var that = this;
return {
startAngle: that.option("startAngle"),
innerRadius: that.option("innerRadius"),
segmentsDirection: that.option("segmentsDirection"),
type: that.option("type")
};
},
getSizeGroup: function getSizeGroup() {
return this._themeManager.getOptions("sizeGroup");
},
getSizeGroupLayout: function getSizeGroupLayout() {
return this._sizeGroupLayout || {};
}
});
_each(OPTIONS_FOR_REFRESH_SERIES, function (_, name) {
dxPieChart.prototype._optionChangesMap[name] = "REFRESH_SERIES_DATA_INIT";
});
registerComponent("dxPieChart", dxPieChart);
module.exports = dxPieChart;
var pieSizeEqualizer = function () {
function equalize(group, allPies) {
var pies = allPies.filter(function (p) {
return p.getSizeGroup() === group;
}),
minRadius = Math.min.apply(null, pies.map(function (p) {
return p.getSizeGroupLayout().radius;
})),
minPie = pies.filter(function (p) {
return p.getSizeGroupLayout().radius === minRadius;
});
pies.forEach(function (p) {
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 = [],
timers = {};
return {
queue: function queue(pie) {
var group = pie.getSizeGroup();
pies = addToList(pies, pie);
clearTimeout(timers[group]);
timers[group] = setTimeout(function () {
equalize(group, pies);
});
},
remove: function remove(pie) {
pies = removeFromList(pies, pie);
if (!pies.length) {
timers = {};
}
}
};
}();
;