@syncfusion/ej2-charts
Version:
Feature-rich chart control with built-in support for over 25 chart types, technical indictors, trendline, zooming, tooltip, selection, crosshair and trackball.
299 lines (298 loc) • 15.3 kB
JavaScript
import { Mean, RectOption, pathAnimation, getElement, appendChildElement, appendClipElement } from '../../common/utils/helper';
import { getPoint, sum, templateAnimate } from '../../common/utils/helper';
import { PathOption } from '@syncfusion/ej2-svg-base';
import { animationMode } from '@syncfusion/ej2-base';
/**
* The `ErrorBar` module is used to render the error bar for series.
*/
var ErrorBar = /** @class */ (function () {
/**
* Constructor for the error bar module.
*
* @private
*/
function ErrorBar(chart) {
this.chart = chart;
}
/**
* Render the error bar for series.
*
* @returns {void}
* @private
*/
ErrorBar.prototype.render = function (series) {
if (this.chart.chartAreaType === 'PolarRadar') {
return null;
}
this.createElement(series, this.chart);
this.renderErrorBar(series);
};
ErrorBar.prototype.renderErrorBar = function (series) {
var seriesIndex = series.index;
var symbolId;
var capId;
var errorbar = series.errorBar;
var errorBarCap = series.errorBar.errorBarCap;
var errorDirection = ['', ''];
var redraw = series.chart.redraw;
for (var _i = 0, _a = series.points; _i < _a.length; _i++) {
var point = _a[_i];
if (point.visible && point.symbolLocations[0]) {
var errorX = 0;
var errorY = 0;
switch (errorbar.mode) {
case 'Vertical':
errorY = point.verticalError;
break;
case 'Horizontal':
errorX = point.horizontalError;
break;
case 'Both':
errorX = point.horizontalError;
errorY = point.verticalError;
break;
}
errorDirection = this['calculate' + errorbar.type + 'Value'](point, series, this.chart.requireInvertedAxis, errorX, errorY);
symbolId = this.chart.element.id + '_Series_' + '_ErrorBarGroup_' + seriesIndex + '_Point_' + point.index;
capId = this.chart.element.id + '_Series_' + '_ErrorBarCap_' + seriesIndex + '_Point_' + point.index;
var shapeOption = new PathOption(symbolId, '', errorbar.width, (errorbar.errorBarColorMapping ? point.errorBarColor : errorbar.color || this.chart.themeStyle.errorBar), null, '', errorDirection[0]);
var element = getElement(shapeOption.id);
var previousDirection = element ? element.getAttribute('d') : null;
if (series.errorBarElement) {
series.errorBarElement.appendChild(this.chart.renderer.drawPath(shapeOption));
}
pathAnimation(element, errorDirection[0], redraw, previousDirection, this.chart.duration);
var capOption = new PathOption(capId, '', errorBarCap.width, (errorbar.errorBarCap.color ? errorBarCap.color : (errorbar.errorBarColorMapping ? point.errorBarColor : errorbar.color || this.chart.themeStyle.errorBar)), null, '', errorDirection[1]);
element = getElement(capOption.id);
previousDirection = element ? element.getAttribute('d') : null;
if (series.errorBarElement) {
appendChildElement(this.chart.enableCanvas, series.errorBarElement, this.chart.renderer.drawPath(capOption), redraw);
}
pathAnimation(element, errorDirection[1], redraw, previousDirection, this.chart.duration);
}
}
};
// path calculation for error bar
ErrorBar.prototype.findLocation = function (point, series, isInverted, x1, y1) {
var errorbar = series.errorBar;
var direction = errorbar.direction;
var location = [];
var yValue = series.type.indexOf('Stacking') > -1 ? series.stackedValues.endValues[point.index] :
(series.seriesType === 'HighLow' || series.seriesType === 'HighLowOpenClose') ? (series.points[point.index].high) :
point.yValue;
var startPoint = getPoint(point.xValue + ((direction === 'Plus' || direction === 'Both') ? (errorbar.type === 'Custom' &&
(errorbar.mode === 'Horizontal' || errorbar.mode === 'Both')) ? x1 = point.horizontalPositiveError : x1 : 0), yValue + ((direction === 'Plus' || direction === 'Both') ? (errorbar.type === 'Custom' &&
(errorbar.mode === 'Vertical' || errorbar.mode === 'Both')) ? y1 = point.verticalPositiveError : y1 : 0), series.xAxis, series.yAxis, isInverted);
location.push(startPoint);
if (series.isRectSeries) {
var midPoint = point.symbolLocations[0];
location.push(midPoint);
}
else {
var midPoint = getPoint(point.xValue, point.yValue, series.xAxis, series.yAxis, isInverted);
location.push(midPoint);
}
var endPoint = getPoint(point.xValue - ((direction === 'Minus' || direction === 'Both') ? (errorbar.type === 'Custom' &&
(errorbar.mode === 'Horizontal' || errorbar.mode === 'Both')) ? x1 = point.horizontalNegativeError : x1 : 0), yValue - ((direction === 'Minus' || direction === 'Both') ? (errorbar.type === 'Custom' &&
(errorbar.mode === 'Vertical' || errorbar.mode === 'Both')) ? y1 = point.verticalNegativeError : y1 : 0), series.xAxis, series.yAxis, isInverted);
location.push(endPoint);
// calculate error height for datalabel position alignment
point.error = (errorbar.mode === 'Vertical') ? errorbar.verticalError : errorbar.horizontalError;
this.negativeHeight = (errorbar.mode === 'Vertical' || errorbar.mode === 'Both') ? (isInverted ? (location[1].x - location[2].x) :
(location[2].y - location[1].y)) : 0;
this.positiveHeight = (errorbar.mode === 'Vertical' || errorbar.mode === 'Both') ? (isInverted ? (location[0].x - location[1].x) :
(location[1].y - location[0].y)) : 0;
return this.getErrorDirection(location[0], location[1], location[2], series, isInverted);
};
//calculations for eror bar types
ErrorBar.prototype.calculateFixedValue = function (point, series, isInverted, errorX, errorY) {
// const errorbar: ErrorBarSettingsModel = series.errorBar;
return this.findLocation(point, series, isInverted, errorX, errorY);
};
ErrorBar.prototype.calculatePercentageValue = function (point, series, isInverted, errorX, errorY) {
errorX = (errorX / 100) * point.xValue;
errorY = (errorY / 100) * point.yValue;
return this.findLocation(point, series, isInverted, errorX, errorY);
};
ErrorBar.prototype.calculateStandardDeviationValue = function (point, series, isInverted, errorX, errorY) {
var getMean = this.meanCalculation(series, series.errorBar.mode);
errorX = errorX * (getMean.horizontalSquareRoot + getMean.horizontalMean);
errorY = errorY * (getMean.verticalSquareRoot + getMean.verticalMean);
return this.findLocation(point, series, isInverted, errorX, errorY);
};
ErrorBar.prototype.calculateStandardErrorValue = function (point, series, isInverted, errorX, errorY) {
var length = series.points.length;
var getMean = this.meanCalculation(series, series.errorBar.mode);
errorX = ((errorX * getMean.horizontalSquareRoot) / Math.sqrt(length));
errorY = ((errorY * getMean.verticalSquareRoot) / Math.sqrt(length));
return this.findLocation(point, series, isInverted, errorX, errorY);
};
ErrorBar.prototype.calculateCustomValue = function (point, series, isInverted, errorX, errorY) {
// const errorbar: ErrorBarSettingsModel = series.errorBar;
return this.findLocation(point, series, isInverted, errorX, errorY);
};
ErrorBar.prototype.getHorizontalDirection = function (start, mid, end, direction, errorMode, capLength) {
var path = '';
var capDirection = '';
path += 'M ' + start.x + ' ' + mid.y + ' L ' + end.x + ' ' + mid.y;
capDirection += (direction === 'Plus' || direction === 'Both') ? 'M ' + (start.x) + ' ' + (mid.y - capLength) + ' L '
+ (start.x) + ' ' + (mid.y + capLength) : '';
capDirection += (direction === 'Minus' || direction === 'Both') ? 'M ' + (end.x) + ' ' + (mid.y - capLength) + ' L '
+ (end.x) + ' ' + (mid.y + capLength) : ' ';
return [path, capDirection];
};
ErrorBar.prototype.getVerticalDirection = function (start, mid, end, direction, errorMode, capLength) {
var path = '';
var capDirection = '';
path += 'M ' + mid.x + ' ' + start.y + ' L ' + mid.x + ' ' + end.y;
capDirection += (direction === 'Plus' || direction === 'Both') ? 'M ' + (mid.x - capLength) + ' ' + start.y + ' L '
+ (mid.x + capLength) + ' ' + start.y : '';
capDirection += (direction === 'Minus' || direction === 'Both') ? 'M ' + (mid.x - capLength) + ' ' + end.y + ' L '
+ (mid.x + capLength) + ' ' + end.y : '';
return [path, capDirection];
};
ErrorBar.prototype.getBothDirection = function (start, mid, end, direction, errorMode, capLength) {
var capDirection = '';
var path = '';
var pathH = this.getHorizontalDirection(start, mid, end, direction, errorMode, capLength);
var pathV = this.getVerticalDirection(start, mid, end, direction, errorMode, capLength);
path = pathH[0].concat(pathV[0]);
capDirection = pathH[1].concat(pathV[1]);
return [path, capDirection];
};
ErrorBar.prototype.getErrorDirection = function (start, mid, end, series, isInverted) {
var direction = series.errorBar.direction;
var mode = series.errorBar.mode;
var capLength = series.errorBar.errorBarCap.length;
var paths;
var errorMode = mode;
switch (mode) {
case 'Both':
errorMode = mode;
break;
case 'Horizontal':
errorMode = (isInverted) ? 'Vertical' : mode;
break;
case 'Vertical':
errorMode = (isInverted) ? 'Horizontal' : mode;
break;
}
switch (errorMode) {
case 'Horizontal':
paths = this.getHorizontalDirection(start, mid, end, direction, errorMode, capLength);
break;
case 'Vertical':
paths = this.getVerticalDirection(start, mid, end, direction, errorMode, capLength);
break;
case 'Both':
paths = this.getBothDirection(start, mid, end, direction, errorMode, capLength);
break;
}
return [paths[0], paths[1]];
};
// mean calculation for standard deviation and standard error
ErrorBar.prototype.meanCalculation = function (series, mode) {
var sumOfX = 0;
var sumOfY = 0;
var verticalMean = 0;
var horizontalMean = 0;
var length = series.points.length;
switch (mode) {
case 'Vertical':
sumOfY = sum(series.yData);
verticalMean = sumOfY / length;
break;
case 'Horizontal':
sumOfX = sum(series.xData);
horizontalMean = sumOfX / length;
break;
case 'Both':
sumOfY = sum(series.yData);
verticalMean = sumOfY / length;
sumOfX = sum(series.xData);
horizontalMean = sumOfX / length;
}
for (var _i = 0, _a = series.points; _i < _a.length; _i++) {
var point = _a[_i];
if (mode === 'Vertical') {
sumOfY = sumOfY + Math.pow((point.yValue - verticalMean), 2);
}
else if (mode === 'Horizontal') {
sumOfX = sumOfX + Math.pow((point.xValue - horizontalMean), 2);
}
else {
sumOfY = sumOfY + Math.pow((point.yValue - verticalMean), 2);
sumOfX = sumOfX + Math.pow((point.xValue - horizontalMean), 2);
}
}
var verStandardMean = sumOfY / (length - 1);
var verSquareRoot = Math.sqrt(sumOfY / (length - 1));
var horStandardMean = sumOfX / (length - 1);
var horSquareRoot = Math.sqrt(sumOfX / (length - 1));
return new Mean(verStandardMean, verSquareRoot, horStandardMean, horSquareRoot, verticalMean, horizontalMean);
};
ErrorBar.prototype.createElement = function (series, chart) {
// const explodeValue: number = 5;
var transform = chart.chartAreaType === 'Cartesian' ?
'translate(' + series.clipRect.x + ',' + (series.clipRect.y) + ')' : '';
var markerHeight = (series.marker.height) / 2;
var markerWidth = (series.marker.width) / 2;
if (chart.chartAreaType === 'Cartesian') {
var options = new RectOption(chart.element.id + '_ChartErrorBarClipRect_' + series.index, 'transparent', { width: 1, color: 'Gray' }, 1, {
x: -markerWidth, y: -markerHeight,
width: series.clipRect.width + markerWidth * 2, height: series.clipRect.height + markerHeight * 2
});
series.errorBarElement = chart.renderer.createGroup({
'id': chart.element.id + 'ErrorBarGroup' + series.index,
'transform': transform,
'clip-path': 'url(#' + chart.element.id + '_ChartErrorBarClipRect_' + series.index + ')'
});
if (series.errorBarElement) {
series.errorBarElement.appendChild(appendClipElement(chart.redraw, options, chart.renderer));
}
}
};
/**
* Animates the series.
*
* @param {Series} series - Defines the series to animate.
* @returns {void}
* @private
*/
ErrorBar.prototype.doErrorBarAnimation = function (series) {
var errorBarElements = series.errorBarElement.childNodes;
if (!errorBarElements) {
return null;
}
var delay = series.animation.delay + ((series.animation.duration === 0 && animationMode === 'Enable') ? 1000 : series.animation.duration);
var j = 1;
while (j < errorBarElements.length) {
for (var i = 0; i < series.points.length; i++) {
if (!series.points[i].symbolLocations[0]) {
continue;
}
errorBarElements[j].style.visibility = 'hidden';
templateAnimate(errorBarElements[j], delay, 350, series.chart.requireInvertedAxis ? 'SlideLeftIn' : 'SlideBottomIn', false);
}
j++;
}
};
/**
* Get module name.
*/
ErrorBar.prototype.getModuleName = function () {
// Returns the module name
return 'ErrorBar';
};
/**
* To destroy the errorBar for series.
*
* @returns {void}
* @private
*/
ErrorBar.prototype.destroy = function () {
// Destroy method performed here
};
return ErrorBar;
}());
export { ErrorBar };