@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.
485 lines (484 loc) • 25.1 kB
JavaScript
import { isNullOrUndefined } from '@syncfusion/ej2-base';
import { Rect, measureText, textElement, PathOption } from '@syncfusion/ej2-svg-base';
import { RectOption, CircleOption } from '../../common/utils/helper';
import { Animation, animationMode } from '@syncfusion/ej2-base';
import { getAnimationFunction } from '../../common/utils/helper';
/**
* class for Bullet chart Scale Group
*/
var ScaleGroup = /** @class */ (function () {
function ScaleGroup(bulletChart) {
this.comparative = [];
//super();
this.dataSource = bulletChart.dataSource;
this.isVertical = (bulletChart.orientation === 'Vertical');
this.isTicksInside = (bulletChart.tickPosition === 'Inside');
this.isLabelsInside = (bulletChart.labelPosition === 'Inside');
this.isHorizontal = (bulletChart.orientation === 'Horizontal');
this.isLeft = bulletChart.titlePosition === 'Left';
this.isRight = bulletChart.titlePosition === 'Right';
this.isTop = bulletChart.titlePosition === 'Top';
this.location = 10;
this.featureBarBounds = [];
this.majorTickSize = bulletChart.majorTickLines.height;
this.labelOffset = 15;
this.labelSize = 12;
this.bulletChart = bulletChart;
this.isLabelBelow = !this.bulletChart.opposedPosition;
this.scaleOrientation = this.bulletChart.orientation;
this.rangeColor = [];
}
/**
* To render range scale of the bulletChart graph.
*
* @param {Element} scaleGroup - The group element to contain the scale.
* @returns {number[]} - Array representing the range scale.
*/
ScaleGroup.prototype.drawScaleGroup = function (scaleGroup) {
var rangeGroup = this.bulletChart.renderer.createGroup({ 'id': this.bulletChart.svgObject.id + '_rangeGroup' });
var max = this.bulletChart.maximum;
var ranges = this.bulletChart.ranges;
this.scaleSettingsGroup = scaleGroup;
var rect;
var bullet = this.bulletChart;
var enableRtl = bullet.enableRtl;
var initialRect = bullet.initialClipRect;
var locX = initialRect.x + ((enableRtl && bullet.orientation === 'Horizontal') ? initialRect.width : 0);
var locY = initialRect.y + ((!enableRtl && bullet.orientation === 'Vertical') ? initialRect.height : 0);
var area = 0;
bullet.rangeCollection = [];
var start = 0;
var range = (bullet.orientation === 'Horizontal') ? initialRect.width : initialRect.height;
var fillRange = (bullet.orientation === 'Horizontal') ? initialRect.height : initialRect.width;
for (var i = 0; i < ranges.length; i++) {
area = (range) * ((ranges[i].end - start) / max);
if (bullet.orientation === 'Horizontal') {
locX -= (enableRtl) ? area : 0;
}
else {
locY -= (!enableRtl) ? area : 0;
}
rect = new RectOption(bullet.svgObject.id + '_range_' + i, ranges[i].color || this.bulletChart.themeStyle.rangeStrokes[i]['color'], { width: 1 }, ranges[i].opacity, new Rect(locX, locY, ((bullet.orientation === 'Horizontal') ? area : fillRange), ((bullet.orientation === 'Horizontal') ? fillRange : area)));
var svgRect = bullet.renderer.drawRectangle(rect);
rangeGroup.appendChild(svgRect);
scaleGroup.appendChild(rangeGroup);
if (bullet.orientation === 'Horizontal') {
locX += (enableRtl) ? 0 : area;
}
else {
locY += (!enableRtl) ? 0 : area;
}
bullet.rangeCollection.push(area);
start = ranges[i].end;
}
return this.bulletChart.rangeCollection;
};
ScaleGroup.prototype.sortRangeCollection = function (a, b) {
return (a - b);
};
/**
* To render the feature bar of the bulletChart chart.
*
* @param {number} dataCount - Count of the bars.
* @returns {void}
*/
ScaleGroup.prototype.renderFeatureBar = function (dataCount) {
if (dataCount === 0) {
return;
}
this.renderCommonFeatureBar(dataCount, this.isHorizontal);
};
/**
* To render the horizontal feature bar of the bulletChart chart.
*
* @param {number} dataCount - Count of the bars.
* @param {boolean} isHorizontal - Indicates whether the bars are horizontal.
* @returns {void}
*/
ScaleGroup.prototype.renderCommonFeatureBar = function (dataCount, isHorizontal) {
var categoryValue;
var dotWidth = 6;
var padding = 5;
var bulletChart = this.bulletChart;
var initialBoundsStart = isHorizontal ? (bulletChart.initialClipRect.y + bulletChart.initialClipRect.height) :
bulletChart.initialClipRect.x;
var lPoint;
var featueGroup = bulletChart.renderer.createGroup({ 'id': bulletChart.svgObject.id + '_featureGroup' });
var data;
var featureBarSize = (isHorizontal ? bulletChart.initialClipRect.height : bulletChart.initialClipRect.width) / dataCount;
var bounds;
for (var i = 0; i < dataCount; i++) {
data = bulletChart.dataSource[i];
categoryValue = data[bulletChart.categoryField];
if (isHorizontal) {
lPoint = initialBoundsStart - (featureBarSize * i) - (featureBarSize + bulletChart.valueHeight) / 2;
}
else {
lPoint = initialBoundsStart + (featureBarSize * i) + (featureBarSize / 2) - bulletChart.valueHeight / 2;
}
bounds = this.calculateFeatureMeasureBounds(data[bulletChart.valueField], categoryValue, isHorizontal);
if (data && bulletChart.type === 'Dot') {
var value = data[bulletChart.valueField];
if (isHorizontal) {
bounds.pointX = bounds.pointX + (((value > 0) && !bulletChart.enableRtl) ||
((value < 0) && bulletChart.enableRtl) ? (bounds.width) : 0) - dotWidth / 2;
}
else {
bounds.pointX = bounds.pointX + (((value > 0) && bulletChart.enableRtl) ||
((value < 0) && !bulletChart.enableRtl) ? (bounds.width) : 0) - dotWidth / 2;
}
bounds.width = dotWidth;
}
// Drawing feature bar rect element
if (bounds) {
var svgRect = isHorizontal ? this.featureBar(bounds.pointX, lPoint, bounds.width, i) :
this.verticalFeatureBar(lPoint, bounds.pointX, bounds.width, i);
featueGroup.appendChild(svgRect);
this.feature = svgRect;
this.scaleSettingsGroup.appendChild(featueGroup);
this.featureBarBounds[i] = { x: bounds.pointX, y: lPoint, width: bounds.width, height: bulletChart.valueHeight };
// Drawing category text element
if (!isNullOrUndefined(categoryValue)) {
var categoryTextSize = measureText(categoryValue, bulletChart.categoryLabelStyle, bulletChart.themeStyle.axisLabelFont);
var categorySize = isHorizontal ? categoryTextSize.width : categoryTextSize.height;
var initialRect = bulletChart.initialClipRect;
var x = void 0;
var categoryOptions = void 0;
if (isHorizontal) {
x = (bulletChart.enableRtl) ? (initialRect.x + initialRect.width + padding + categorySize / 2) :
initialRect.x - padding - categorySize / 2;
categoryOptions = this.drawcategory(x, lPoint, categoryValue);
}
else {
x = (bulletChart.enableRtl) ? (initialRect.y - padding - categorySize / 2) :
initialRect.y + initialRect.height + padding + categorySize / 2;
categoryOptions = this.drawcategory(lPoint + bulletChart.valueHeight / 2, x, categoryValue);
}
bulletChart.categoryLabelStyle.fontFamily = bulletChart.categoryLabelStyle.fontFamily ||
bulletChart.themeStyle.axisLabelFont.fontFamily;
textElement(categoryOptions, bulletChart.categoryLabelStyle, bulletChart.categoryLabelStyle.color ||
bulletChart.themeStyle.categoryFontColor, this.scaleSettingsGroup);
}
}
if ((bulletChart.animation.enable && animationMode !== 'Disable') || animationMode === 'Enable') {
this.doValueBarAnimation();
}
}
};
ScaleGroup.prototype.featureBar = function (pointX, pointY, width, i) {
var featureBarOptions = new RectOption(this.bulletChart.svgObject.id + '_FeatureMeasure_' + i, this.bulletChart.dataSource[i][this.bulletChart.valueFill] || this.bulletChart.valueFill, this.bulletChart.valueBorder, 1, new Rect(pointX, pointY, width, this.bulletChart.valueHeight), 0, 0, '', this.bulletChart.valueBorder.dashArray);
var svgRect = this.bulletChart.renderer.drawRectangle(featureBarOptions);
svgRect.setAttribute('class', this.bulletChart.svgObject.id + '_FeatureMeasure');
svgRect.id = this.bulletChart.svgObject.id + '_FeatureMeasure_' + i;
svgRect.setAttribute('role', 'img');
svgRect.setAttribute('tabindex', '0');
svgRect.style.outline = 'none';
svgRect.setAttribute('aria-label', (this.bulletChart.title + ', value: ' + this.bulletChart.dataSource[i].value + ', target: ' + this.bulletChart.dataSource[i].target));
return svgRect;
};
ScaleGroup.prototype.verticalFeatureBar = function (pointX, pointY, width, i) {
var featureBarOptions = new RectOption(this.bulletChart.svgObject.id + '_FeatureMeasure_' + i, this.bulletChart.dataSource[i][this.bulletChart.valueFill] || this.bulletChart.valueFill, this.bulletChart.valueBorder, 1, new Rect(pointX, pointY, this.bulletChart.valueHeight, width));
var svgRect = this.bulletChart.renderer.drawRectangle(featureBarOptions);
svgRect.setAttribute('class', this.bulletChart.svgObject.id + '_FeatureMeasure');
svgRect.id = this.bulletChart.svgObject.id + '_FeatureMeasure_' + i;
svgRect.setAttribute('role', 'img');
svgRect.setAttribute('tabindex', '0');
svgRect.style.outline = 'none';
svgRect.setAttribute('aria-label', (this.bulletChart.title + ', value: ' + this.bulletChart.dataSource[i].value + ', target: ' + this.bulletChart.dataSource[i].target));
return svgRect;
};
ScaleGroup.prototype.drawcategory = function (lPointX, lPointY, categoryValue) {
var fontsize = parseInt(this.bulletChart.categoryLabelStyle.size, 10);
var categoryOptions = {
'id': '',
'anchor': 'middle',
'x': lPointX,
'y': lPointY + (fontsize / 4 + this.bulletChart.valueHeight / 2),
'transform': '',
'text': categoryValue,
'baseLine': '',
'labelRotation': 0
};
return categoryOptions;
};
/**
* To render comparative symbol of the bulletChart chart.
*
* @param {number} dataCount - Data count value.
* @returns {void}
*/
ScaleGroup.prototype.renderComparativeSymbol = function (dataCount) {
if (dataCount === 0) {
return;
}
this.renderCommonComparativeSymbol(dataCount, this.isHorizontal);
};
ScaleGroup.prototype.renderCommonComparativeSymbol = function (dataCount, isHorizontal) {
var bulletChart = this.bulletChart;
var value;
var rect = bulletChart.initialClipRect;
var scaleLength = isHorizontal ? rect.width : rect.height;
var y1;
var y2;
var x1;
var pointY = isHorizontal ? (rect.y + rect.height) : rect.x;
var comparativeGroup = bulletChart.renderer.createGroup({ 'id': bulletChart.svgObject.id + '_comparativeGroup' });
var minimum = bulletChart.minimum;
var maximum = bulletChart.maximum;
var delta = maximum - minimum;
var targetWidth = 5;
var pointX = isHorizontal ? (rect.x - (targetWidth / 2)) : (rect.y + rect.height);
var temp;
var values = [];
var targetTypes = bulletChart.targetTypes;
var targetType = 'Rect';
var targetTypeLength = targetTypes.length;
var featureBarSize = (isHorizontal ? rect.height : rect.width) / dataCount;
var svgElement;
for (var k = 0; k < dataCount; k++) {
value = bulletChart.dataSource[k][bulletChart.targetField];
values = values.concat(value);
for (var i = 0; i < values.length; i++) {
targetType = targetTypes[i % targetTypeLength];
if (values[i] >= minimum && values[i] <= maximum) {
if (isHorizontal) {
temp = pointY - (featureBarSize * k) - (featureBarSize / 2);
}
else {
temp = pointY + (featureBarSize * k) + (featureBarSize / 2);
}
y1 = temp - targetWidth * 1.5;
y2 = temp + targetWidth * 1.5;
temp = (scaleLength / (delta / (delta - (maximum - values[i]))));
if (isHorizontal) {
x1 = pointX + (bulletChart.enableRtl ? (scaleLength - temp) : temp);
}
else {
x1 = pointX - (bulletChart.enableRtl ? (scaleLength - temp) : temp);
}
svgElement = this.getTargetElement(targetType, isHorizontal, x1, y1, y2, values[i], k);
this.comparative.push(svgElement);
comparativeGroup.appendChild(svgElement);
y1 = 0;
y2 = 0;
}
this.scaleSettingsGroup.appendChild(comparativeGroup);
}
values = [];
if ((bulletChart.animation.enable && animationMode !== 'Disable') || animationMode === 'Enable') {
this.doTargetBarAnimation(0);
}
}
};
ScaleGroup.prototype.getTargetElement = function (targetType, isHorizontal, x1, y1, y2, value, k) {
var shapeObject;
var shapeElement;
var bulletChart = this.bulletChart;
var strokeWidth = (targetType === 'Cross') ? bulletChart.targetWidth - 1 : 1;
var size = (targetType === 'Circle') ? bulletChart.targetWidth - 1 : bulletChart.targetWidth;
var lx = isHorizontal ? x1 + (size / 2) : y1 + ((y2 - y1) / 2);
var ly = isHorizontal ? y1 + ((y2 - y1) / 2) : x1;
var id = bulletChart.svgObject.id + '_ComparativeMeasure_' + k;
var className = bulletChart.svgObject.id + '_ComparativeMeasure';
var targetColor = bulletChart.dataSource[k][bulletChart.targetColor] || bulletChart.targetColor;
if (targetType === 'Rect') {
shapeObject = isHorizontal ? this.compareMeasure(x1, y1, y2, k, value) : this.compareVMeasure(y1, y2, x1, k);
shapeElement = bulletChart.renderer.drawLine(shapeObject);
}
else if (targetType === 'Circle') {
shapeObject = new CircleOption(id, targetColor, { width: 1, color: targetColor || 'black' }, 1, lx, ly, size);
shapeElement = bulletChart.renderer.drawCircle(shapeObject);
}
else {
var crossDirection = 'M ' + (lx - size) + ' ' + (ly - size) + ' L ' + (lx + size) + ' ' + (ly + size) + ' M ' +
(lx - size) + ' ' + (ly + size) + ' L ' + (lx + size) + ' ' + (ly - size);
shapeObject = new PathOption(id, 'transparent', strokeWidth, targetColor, 1, '', crossDirection);
shapeElement = bulletChart.renderer.drawPath(shapeObject);
}
shapeElement.setAttribute('class', className);
return shapeElement;
};
ScaleGroup.prototype.compareMeasure = function (x1, y1, y2, i, value) {
var bulletChart = this.bulletChart;
var compareMeasureOptions = {
'class': bulletChart.svgObject.id + '_ComparativeMeasure',
'id': bulletChart.svgObject.id + '_ComparativeMeasure_' + i,
'x1': (value === bulletChart.maximum) ? x1 - (bulletChart.targetWidth / 2) :
(value === bulletChart.minimum) ? x1 + (bulletChart.targetWidth / 2) : x1,
'y1': y1,
'x2': (value === bulletChart.maximum) ? x1 - (bulletChart.targetWidth / 2) :
(value === bulletChart.minimum) ? x1 + (bulletChart.targetWidth / 2) : x1,
'y2': y2,
'stroke-width': bulletChart.targetWidth,
'stroke': bulletChart.dataSource[i][bulletChart.targetColor] || bulletChart.targetColor || 'black'
};
return compareMeasureOptions;
};
ScaleGroup.prototype.compareVMeasure = function (x1, x2, y1, i) {
var bulletChart = this.bulletChart;
var compareMeasureOptions = {
'class': bulletChart.svgObject.id + '_ComparativeMeasure',
'id': bulletChart.svgObject.id + '_ComparativeMeasure_' + i,
'x1': x1,
'y1': y1,
'x2': x2,
'y2': y1,
'stroke-width': bulletChart.targetWidth,
'stroke': bulletChart.dataSource[i][bulletChart.targetColor] || bulletChart.targetColor || 'black'
};
return compareMeasureOptions;
};
/**
* To calculate the bounds on vertical and horizontal orientation changes
*
* @param {number} value Value of the scale.
* @param {string} categoryValue Value of the category.
* @param {boolean} isHorizontal Boolean value.
* @returns {IFeatureMeasureType} calculateFeatureMeasureBounds
*/
ScaleGroup.prototype.calculateFeatureMeasureBounds = function (value, categoryValue, isHorizontal) {
var bulletChart = this.bulletChart;
var min = bulletChart.minimum;
value = (value < min && min <= 0) ? min : value;
if (value >= min) {
var pointX = void 0;
var lastPointX = void 0;
var width = void 0;
var loc = isHorizontal ? bulletChart.initialClipRect.x : bulletChart.initialClipRect.y;
var scaleLength = isHorizontal ? bulletChart.initialClipRect.width : bulletChart.initialClipRect.height;
var delta = bulletChart.maximum - bulletChart.minimum;
var valueDiff = bulletChart.maximum - value;
var orientation_1 = ((!bulletChart.enableRtl) ? 'forward' : 'backward') + this.scaleOrientation.toLowerCase();
categoryValue = isNullOrUndefined(categoryValue) ? '' : categoryValue;
var stringLength = measureText(categoryValue.toString(), bulletChart.labelStyle, this.bulletChart.themeStyle.axisLabelFont).width;
switch (orientation_1) {
case 'forwardhorizontal':
case 'backwardvertical':
pointX = loc + ((min > 0) ? 0 : scaleLength / delta * Math.abs(min));
width = scaleLength / (delta / ((min > 0) ? delta - valueDiff : value));
if (value < 0) {
width = Math.abs(width);
pointX -= width;
}
width = (pointX + width < loc + scaleLength) ? width : loc + scaleLength - pointX;
lastPointX = loc - ((orientation_1 === 'forwardhorizontal') ? (stringLength / 2 + 5) :
this.labelOffset);
break;
default:
pointX = loc + (scaleLength - scaleLength / (delta / (delta - valueDiff)));
width = (min > 0) ? scaleLength / (delta / (delta - valueDiff)) : scaleLength / (delta / (value));
if (value < 0) {
width = Math.abs(width);
pointX -= width;
}
if (pointX < loc) {
width = pointX + width - loc;
pointX = loc;
}
lastPointX = loc + scaleLength + ((orientation_1 === 'backwardhorizontal') ? (stringLength / 2 +
5) : 5);
break;
}
return { pointX: pointX, width: width, lastPointX: lastPointX };
}
return null;
};
/**
* Animates the feature bar.
*
* @returns {void}
*/
ScaleGroup.prototype.doValueBarAnimation = function () {
var valueBarElement = this.feature;
if (!valueBarElement) {
return null;
}
var animateOption = this.bulletChart.animation;
var animateDuration = this.bulletChart.animateSeries ? this.bulletChart.animation.duration : animateOption.duration;
var effectType = getAnimationFunction('Linear');
var isValuePlot = this.bulletChart.dataSource < 0;
var valueX;
var valueY;
var elementBarHeight = valueBarElement.getBoundingClientRect().height;
var elementBarWidth = valueBarElement.getBoundingClientRect().width;
var centerX;
var centerY;
var valueActual;
if (this.bulletChart.orientation === 'Horizontal' && valueBarElement) {
valueY = parseInt(valueBarElement.getAttribute('height'), 10);
valueX = parseInt(valueBarElement.getAttribute('x'), 10);
centerY = isValuePlot ? valueY : valueY + elementBarHeight;
centerX = valueX;
}
valueBarElement.style.visibility = 'hidden';
new Animation({}).animate(valueBarElement, {
duration: (animateDuration === 0 && animationMode === 'Enable') ? 1000 : animateDuration,
delay: animateOption.delay,
progress: function (args) {
if (args.timeStamp >= args.delay) {
valueBarElement.style.visibility = 'visible';
elementBarWidth = elementBarWidth ? elementBarWidth : 1;
valueActual = effectType(args.timeStamp - args.delay, 0, elementBarWidth, args.duration);
valueBarElement.setAttribute('transform', 'translate(' + centerX + ' ' + centerY +
') scale(' + (valueActual / elementBarWidth) + ', 1) translate(' + (-centerX) + ' ' + (-centerY) + ')');
}
},
end: function () {
valueBarElement.setAttribute('transform', 'translate(0,0)');
valueBarElement.style.visibility = 'visible';
}
});
};
/**
* Animates the comparative bar.
*
* @param {number} index Defines the feature bar to animate.
* @returns {void}
*/
ScaleGroup.prototype.doTargetBarAnimation = function (index) {
var x;
var y;
var centerX;
var centerY;
var targetBarelement = this.comparative[index];
if (!targetBarelement) {
return null;
}
if (this.bulletChart.orientation === 'Horizontal' && targetBarelement) {
y = parseFloat(targetBarelement.getAttribute('y1')) + parseFloat(targetBarelement.getAttribute('y2'));
x = parseFloat(targetBarelement.getAttribute('x1'));
centerY = y;
centerX = x;
}
targetBarelement.style.visibility = 'hidden';
this.animateRect(targetBarelement, centerX, centerY, index + 1);
};
ScaleGroup.prototype.animateRect = function (targetBarelement, centerX, centerY, index) {
var _this = this;
var effect = getAnimationFunction('Linear');
var value;
var option = this.bulletChart.animation;
var threshold = this.comparative.length;
var duration = this.bulletChart.animateSeries ? this.bulletChart.animation.duration : option.duration;
new Animation({}).animate(targetBarelement, {
duration: (duration === 0 && animationMode === 'Enable') ? 1000 : duration,
delay: option.delay,
progress: function (args) {
if (args.timeStamp >= args.delay) {
targetBarelement.style.visibility = 'visible';
value = effect(args.timeStamp - args.delay, 0, 1, args.duration);
targetBarelement.setAttribute('transform', 'translate(' + centerX + ' ' + centerY / 2 +
') scale(1,' + (value) + ') translate(' + (-centerX) + ' ' + (-centerY / 2) + ')');
}
},
end: function () {
targetBarelement.setAttribute('transform', 'translate(0,0)');
if (index < threshold) {
_this.doTargetBarAnimation(index + 1);
}
}
});
};
return ScaleGroup;
}());
export { ScaleGroup };