devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
388 lines (334 loc) • 13.8 kB
JavaScript
"use strict";
var extend = require("../../../core/utils/extend").extend,
symbolPoint = require("./symbol_point"),
_extend = extend,
_round = Math.round,
_sqrt = Math.sqrt,
_acos = Math.acos,
DEG = 180 / Math.PI,
_abs = Math.abs,
vizUtils = require("../../core/utils"),
_normalizeAngle = vizUtils.normalizeAngle,
_getCosAndSin = vizUtils.getCosAndSin,
_isDefined = require("../../../core/utils/type").isDefined,
getVerticallyShiftedAngularCoords = vizUtils.getVerticallyShiftedAngularCoords,
RADIAL_LABEL_INDENT = require("../../components/consts").radialLabelIndent;
module.exports = _extend({}, symbolPoint, {
_updateData: function _updateData(data) {
var that = this;
symbolPoint._updateData.call(this, data);
that._visible = true;
that.minValue = that.initialMinValue = that.originalMinValue = _isDefined(data.minValue) ? data.minValue : 0;
},
animate: function animate(complete, duration, delay) {
var that = this;
that.graphic.animate({
x: that.centerX,
y: that.centerY,
outerRadius: that.radiusOuter,
innerRadius: that.radiusInner,
startAngle: that.toAngle,
endAngle: that.fromAngle
}, {
delay: delay,
partitionDuration: duration
}, complete);
},
correctPosition: function correctPosition(correction) {
var that = this;
that.correctRadius(correction);
that.correctLabelRadius(correction.radiusOuter + RADIAL_LABEL_INDENT);
that.centerX = correction.centerX;
that.centerY = correction.centerY;
},
correctRadius: function correctRadius(correction) {
this.radiusInner = correction.radiusInner;
this.radiusOuter = correction.radiusOuter;
},
correctLabelRadius: function correctLabelRadius(radiusLabels) {
this.radiusLabels = radiusLabels;
},
correctValue: function correctValue(correction, percent, base) {
var that = this;
that.value = (base || that.normalInitialValue) + correction;
that.minValue = correction;
that.percent = percent;
that._label.setDataField("percent", percent);
},
_updateLabelData: function _updateLabelData() {
this._label.setData(this._getLabelFormatObject());
},
_getShiftLabelCoords: function _getShiftLabelCoords() {
var that = this,
bBox = that._label.getBoundingRect(),
coord = that._getLabelCoords(that._label),
visibleArea = that._getVisibleArea();
if (that._isLabelDrawingWithoutPoints) {
return that._checkLabelPosition(coord, bBox, visibleArea);
} else {
return that._getLabelExtraCoord(coord, that._checkVerticalLabelPosition(coord, bBox, visibleArea), bBox);
}
},
_getLabelPosition: function _getLabelPosition(options) {
return options.position;
},
_getLabelCoords: function _getLabelCoords(label) {
var that = this,
bBox = label.getBoundingRect(),
options = label.getLayoutOptions(),
angleFunctions = _getCosAndSin(that.middleAngle),
position = that._getLabelPosition(options),
radiusInner = that.radiusInner,
radiusOuter = that.radiusOuter,
radiusLabels = that.radiusLabels,
columnsPosition = position === 'columns',
rad,
x;
if (position === 'inside') {
rad = radiusInner + (radiusOuter - radiusInner) / 2 + options.radialOffset;
x = that.centerX + rad * angleFunctions.cos - bBox.width / 2;
} else {
rad = radiusLabels + options.radialOffset;
if (angleFunctions.cos > 0.1 || columnsPosition && angleFunctions.cos >= 0) {
x = that.centerX + rad * angleFunctions.cos;
} else if (angleFunctions.cos < -0.1 || columnsPosition && angleFunctions.cos < 0) {
x = that.centerX + rad * angleFunctions.cos - bBox.width;
} else {
x = that.centerX + rad * angleFunctions.cos - bBox.width / 2;
}
}
return {
x: x,
y: _round(that.centerY - rad * angleFunctions.sin - bBox.height / 2)
};
},
_correctLabelCoord: function _correctLabelCoord(coord, moveLabelsFromCenter) {
var that = this,
label = that._label,
bBox = label.getBoundingRect(),
labelWidth = bBox.width,
options = label.getLayoutOptions(),
visibleArea = that._getVisibleArea(),
rightBorderX = visibleArea.maxX - labelWidth,
leftBorderX = visibleArea.minX,
angleOfPoint = _normalizeAngle(that.middleAngle),
centerX = that.centerX,
connectorOffset = options.connectorOffset,
x = coord.x;
if (options.position === "columns") {
if (angleOfPoint <= 90 || angleOfPoint >= 270) {
x = rightBorderX;
} else {
x = leftBorderX;
}
coord.x = x;
} else if (options.position !== "inside" && moveLabelsFromCenter) {
if (angleOfPoint <= 90 || angleOfPoint >= 270) {
if (x - connectorOffset < centerX) {
x = centerX + connectorOffset;
}
} else {
if (x + labelWidth + connectorOffset > centerX) {
x = centerX - labelWidth - connectorOffset;
}
}
coord.x = x;
}
return coord;
},
drawLabel: function drawLabel() {
this.translate();
// this function is called for drawing labels without points for checking size of labels
this._isLabelDrawingWithoutPoints = true;
this._drawLabel();
this._isLabelDrawingWithoutPoints = false;
},
updateLabelCoord: function updateLabelCoord(moveLabelsFromCenter) {
var that = this,
bBox = that._label.getBoundingRect(),
coord = that._correctLabelCoord(bBox, moveLabelsFromCenter);
coord = that._checkHorizontalLabelPosition(coord, bBox, that._getVisibleArea());
that._label.shift(_round(coord.x), _round(bBox.y));
},
_checkVerticalLabelPosition: function _checkVerticalLabelPosition(coord, box, visibleArea) {
var x = coord.x,
y = coord.y;
if (coord.y + box.height > visibleArea.maxY) {
y = visibleArea.maxY - box.height;
} else if (coord.y < visibleArea.minY) {
y = visibleArea.minY;
}
return { x: x, y: y };
},
_getLabelExtraCoord: function _getLabelExtraCoord(coord, shiftCoord, box) {
return coord.y !== shiftCoord.y ? getVerticallyShiftedAngularCoords({ x: coord.x, y: coord.y, width: box.width, height: box.height }, shiftCoord.y - coord.y, { x: this.centerX, y: this.centerY }) : coord;
},
_checkHorizontalLabelPosition: function _checkHorizontalLabelPosition(coord, box, visibleArea) {
var x = coord.x,
y = coord.y;
if (coord.x + box.width > visibleArea.maxX) {
x = visibleArea.maxX - box.width;
} else if (coord.x < visibleArea.minX) {
x = visibleArea.minX;
}
return { x: x, y: y };
},
setLabelEllipsis: function setLabelEllipsis() {
var that = this,
label = that._label,
box = label.getBoundingRect(),
visibleArea = that._getVisibleArea(),
position = label.getLayoutOptions().position,
width = box.width;
if (position === "columns" && that.series.index > 0) {
width = visibleArea.maxX - that.centerX - that.radiusLabels;
} else if (position === "inside") {
if (width > visibleArea.maxX - visibleArea.minX) {
width = visibleArea.maxX - visibleArea.minX;
}
} else {
if (box.x + width > visibleArea.maxX) {
width = visibleArea.maxX - box.x;
} else if (box.x < visibleArea.minX) {
width = box.x + width - visibleArea.minX;
}
}
if (width < box.width) {
label.fit(width);
}
},
setLabelTrackerData: function setLabelTrackerData() {
this._label.setTrackerData(this);
},
_checkLabelPosition: function _checkLabelPosition(coord, bBox, visibleArea) {
coord = this._checkHorizontalLabelPosition(coord, bBox, visibleArea);
return this._checkVerticalLabelPosition(coord, bBox, visibleArea);
},
_getLabelConnector: function _getLabelConnector() {
var that = this,
rad = that.radiusOuter,
seriesStyle = that._options.styles.normal,
strokeWidthBy2 = seriesStyle["stroke-width"] / 2,
borderWidth = that.series.getOptions().containerBackgroundColor === seriesStyle.stroke ? _round(strokeWidthBy2) : _round(-strokeWidthBy2),
angleFunctions = _getCosAndSin(_round(that.middleAngle));
return {
x: _round(that.centerX + (rad - borderWidth) * angleFunctions.cos),
y: _round(that.centerY - (rad - borderWidth) * angleFunctions.sin),
angle: that.middleAngle
};
},
_drawMarker: function _drawMarker(renderer, group, animationEnabled, firstDrawing) {
var that = this,
radiusOuter = that.radiusOuter,
radiusInner = that.radiusInner,
fromAngle = that.fromAngle,
toAngle = that.toAngle;
if (animationEnabled) {
radiusInner = radiusOuter = 0;
if (!firstDrawing) {
fromAngle = toAngle = that.shiftedAngle;
}
}
that.graphic = renderer.arc(that.centerX, that.centerY, radiusInner, radiusOuter, toAngle, fromAngle).attr({ "stroke-linejoin": "round" }).smartAttr(that._getStyle()).data({ "chart-data-point": that }).sharp().append(group);
},
getTooltipParams: function getTooltipParams() {
var that = this,
angleFunctions = _getCosAndSin(that.middleAngle),
radiusInner = that.radiusInner,
radiusOuter = that.radiusOuter;
return {
x: that.centerX + (radiusInner + (radiusOuter - radiusInner) / 2) * angleFunctions.cos,
y: that.centerY - (radiusInner + (radiusOuter - radiusInner) / 2) * angleFunctions.sin,
offset: 0
};
},
_translate: function _translate() {
var that = this,
angle = that.shiftedAngle || 0,
value = that.value,
minValue = that.minValue,
translator = that._getValTranslator();
that.fromAngle = translator.translate(minValue) + angle;
that.toAngle = translator.translate(value) + angle;
that.middleAngle = translator.translate((value - minValue) / 2 + minValue) + angle;
if (!that.isVisible()) {
that.middleAngle = that.toAngle = that.fromAngle = that.fromAngle || angle;
}
},
_getMarkerVisibility: function _getMarkerVisibility() {
return true;
},
_updateMarker: function _updateMarker(animationEnabled, style, _, callback) {
var that = this;
if (!animationEnabled) {
style = _extend({
x: that.centerX,
y: that.centerY,
outerRadius: that.radiusOuter,
innerRadius: that.radiusInner,
startAngle: that.toAngle,
endAngle: that.fromAngle
}, style);
}
that.graphic.smartAttr(style).sharp();
callback && callback();
},
getLegendStyles: function getLegendStyles() {
return this._styles.legendStyles;
},
isInVisibleArea: function isInVisibleArea() {
return true;
},
hide: function hide() {
var that = this;
if (that._visible) {
that._visible = false;
that.hideTooltip();
that._options.visibilityChanged(that);
}
},
show: function show() {
var that = this;
if (!that._visible) {
that._visible = true;
that._options.visibilityChanged(that);
}
},
setInvisibility: function setInvisibility() {
this._label.draw(false);
},
isVisible: function isVisible() {
return this._visible;
},
_getFormatObject: function _getFormatObject(tooltip) {
var formatObject = symbolPoint._getFormatObject.call(this, tooltip),
percent = this.percent;
formatObject.percent = percent;
formatObject.percentText = tooltip.formatValue(percent, "percent");
return formatObject;
},
getColor: function getColor() {
return this._styles.normal.fill;
},
coordsIn: function coordsIn(x, y) {
var that = this,
lx = x - that.centerX,
ly = y - that.centerY,
r = _sqrt(lx * lx + ly * ly),
fromAngle = that.fromAngle % 360,
toAngle = that.toAngle % 360,
angle;
if (r < that.radiusInner || r > that.radiusOuter || r === 0) {
return false;
}
angle = _acos(lx / r) * DEG * (ly > 0 ? -1 : 1);
if (angle < 0) {
angle += 360;
}
if (fromAngle === toAngle && _abs(that.toAngle - that.fromAngle) > 1E-4) {
return true;
} else {
return fromAngle >= toAngle ? angle <= fromAngle && angle >= toAngle : !(angle >= fromAngle && angle <= toAngle);
}
}
});