@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.
496 lines (495 loc) • 24 kB
JavaScript
/**
* StripLine src
*/
import { isNullOrUndefined } from '@syncfusion/ej2-base';
import { valueToCoefficient, textElement, RectOption, appendChildElement, appendClipElement, withIn, getElement, ImageOption, logBase } from '../../common/utils/helper';
import { measureText, TextOption, PathOption, Rect } from '@syncfusion/ej2-svg-base';
import { DataUtil } from '@syncfusion/ej2-data';
/**
* The `StripLine` module is used to render strip lines in charts.
*/
var StripLine = /** @class */ (function () {
function StripLine() {
}
/**
* Finding x, y, width and height of the strip line
*
* @param {Axis} axis axis
* @param {StripLineSettingsModel} stripline stripline
* @param {Rect} seriesClipRect seriesClipRect
* @param {number} startValue startValue
* @param {Axis} segmentAxis segmentAxis
* @param {Chart} chart chart instance
* @returns {Rect} rect
*/
StripLine.prototype.measureStripLine = function (axis, stripline, seriesClipRect, startValue, segmentAxis, chart) {
var actualStart;
var actualEnd;
var orientation = axis.orientation;
var isDateTimeAxis = axis.valueType === 'DateTime';
if (stripline.isRepeat && stripline.size !== null) {
actualStart = startValue;
actualEnd = null;
}
else {
if (axis.valueType === 'DateTimeCategory') {
var start = stripline.start;
var end = stripline.end;
actualStart = (start != null && typeof start !== 'number') ?
axis.labels.indexOf(this.dateToMilliSeconds(start, chart).toString()) : start;
actualEnd = (end != null && typeof end !== 'number') ?
axis.labels.indexOf(this.dateToMilliSeconds(end, chart).toString()) : end;
}
else {
actualStart = stripline.start === null ? null : isDateTimeAxis && this.isCoreDate(stripline.start) ?
this.dateToMilliSeconds(stripline.start, chart) : +(axis.valueType === 'Logarithmic' ? logBase(stripline.start, axis.logBase) : stripline.start);
actualEnd = stripline.end === null ? null : isDateTimeAxis && this.isCoreDate(stripline.start) ?
this.dateToMilliSeconds(stripline.end, chart) : +(axis.valueType === 'Logarithmic' ? logBase(stripline.end, axis.logBase) : stripline.end);
}
}
var rect = this.getFromTovalue(actualStart, actualEnd, stripline.size, stripline.startFromAxis, axis, stripline);
var height = (orientation === 'Vertical') ? (rect.to - rect.from) * axis.rect.height : seriesClipRect.height;
var width = (orientation === 'Horizontal') ? (rect.to - rect.from) * axis.rect.width : seriesClipRect.width;
var x = (orientation === 'Vertical') ? seriesClipRect.x : ((rect.from * axis.rect.width) + axis.rect.x);
var y = (orientation === 'Horizontal') ? seriesClipRect.y : (axis.rect.y + axis.rect.height -
((stripline.sizeType === 'Pixel' ? rect.from : rect.to) * axis.rect.height));
if (stripline.isSegmented && stripline.segmentStart != null && stripline.segmentEnd != null && stripline.sizeType !== 'Pixel') {
var start = isDateTimeAxis && this.isCoreDate(stripline.segmentStart) ?
this.dateToMilliSeconds(stripline.segmentStart, chart) : +stripline.segmentStart;
var end = isDateTimeAxis && this.isCoreDate(stripline.segmentEnd) ?
this.dateToMilliSeconds(stripline.segmentEnd, chart) : +stripline.segmentEnd;
var segRect = this.getFromTovalue(start, end, null, null, segmentAxis, stripline);
if (segmentAxis.orientation === 'Vertical') {
y = (segmentAxis.rect.y + segmentAxis.rect.height -
(segRect.to * segmentAxis.rect.height));
height = (segRect.to - segRect.from) * segmentAxis.rect.height;
}
else {
x = ((segRect.from * segmentAxis.rect.width) + segmentAxis.rect.x);
width = (segRect.to - segRect.from) * segmentAxis.rect.width;
}
}
if ((height !== 0 && width !== 0) || (stripline.sizeType === 'Pixel' && (stripline.start !== null || stripline.startFromAxis))) {
return new Rect(x, y, width, height);
}
return new Rect(0, 0, 0, 0);
};
/**
* Retrieves the 'from' and 'to' values from start, end, size, starting from the axis.
*
* @param {number} start - The start value.
* @param {number} end - The end value.
* @param {number} size - The size value.
* @param {boolean} startFromAxis - Indicates whether to start from the axis.
* @param {Axis} axis - The axis.
* @param {StripLineSettingsModel} stripline - The strip line settings.
* @returns {{ from: number, to: number }} - The 'from' and 'to' values.
* @private
*/
StripLine.prototype.getFromTovalue = function (start, end, size, startFromAxis, axis, stripline) {
var from = (!stripline.isRepeat && startFromAxis) ? axis.visibleRange.min : start;
if (axis.valueType === 'Double' && size !== null && !startFromAxis && stripline.start == null) {
from += size;
}
var to = this.getToValue(Math.max(start, isNullOrUndefined(end) ? start : end), from, size, axis, end, stripline);
from = this.findValue(from, axis);
to = this.findValue(to, axis);
return { from: valueToCoefficient(axis.isAxisInverse ? to : from, axis),
to: valueToCoefficient(axis.isAxisInverse ? from : to, axis) };
};
/**
* Finding end value of the strip line
*
* @param {number} to to
* @param {number} from from
* @param {number} size size
* @param {Axis} axis axis
* @param {number} end end
* @param {StripLineSettingsModel} stripline stripline
* @returns {number} number
*/
StripLine.prototype.getToValue = function (to, from, size, axis, end, stripline) {
var sizeType = stripline.sizeType;
var isEnd = (end === null);
if (axis.valueType === 'DateTime') {
var fromValue = new Date(from);
if (sizeType === 'Auto') {
sizeType = axis.actualIntervalType;
size *= axis.visibleRange.interval;
}
switch (sizeType) {
case 'Years':
return (isEnd ? new Date(fromValue.setFullYear(fromValue.getFullYear() + size)) : to);
case 'Months':
return (isEnd ? new Date(fromValue.setMonth(fromValue.getMonth() + size)) : to);
case 'Days':
return (isEnd ? new Date(fromValue.setDate(fromValue.getDate() + size)) : to);
case 'Hours':
return (isEnd ? new Date(fromValue.setHours(fromValue.getHours() + size)) : to);
case 'Minutes':
return (isEnd ? new Date(fromValue.setMinutes(fromValue.getMinutes() + size)) : to);
case 'Seconds':
return (isEnd ? new Date(fromValue.setSeconds(fromValue.getSeconds() + size)) : to);
default:
return from;
}
}
else {
return stripline.sizeType === 'Pixel' ? from : (isEnd ? (from + size) : to);
}
};
/**
* To check the strip line values within range
*
* @param {number} value value
* @param {Axis} axis axis
* @returns {number} - To returns a strip line value.
*/
StripLine.prototype.findValue = function (value, axis) {
if (value < axis.visibleRange.min) {
value = axis.visibleRange.min;
}
else if (value > axis.visibleRange.max) {
value = axis.visibleRange.max;
}
return value;
};
/**
* Date parse
*
* @param {Date} value date
* @param {Chart} chart chart instance
* @returns {Date} parsed date
*/
StripLine.prototype.dateParse = function (value, chart) {
var dateParser = chart.intl.getDateParser({ skeleton: 'full', type: 'dateTime' });
var dateFormatter = chart.intl.getDateFormat({ skeleton: 'full', type: 'dateTime' });
return new Date((Date.parse(dateParser(dateFormatter(new Date(DataUtil.parse.parseJson({ val: value }).val))))));
};
/**
* To render strip lines based start and end.
*
* @param {Chart} chart chart
* @param {ZIndex} position position
* @param {Axis[]} axes axes
* @returns {void}
* @private
*/
StripLine.prototype.renderStripLine = function (chart, position, axes) {
var id = chart.element.id + '_stripline_' + position + '_';
var seriesClipRect = chart.chartAxisLayoutPanel.seriesClipRect;
var end = 0;
var limit = 0;
var startValue = 0;
var segmentAxis = null;
var range;
var options = new RectOption(id + 'ClipRect', 'transparent', { width: 1, color: 'Gray' }, 1, {
x: seriesClipRect.x, y: seriesClipRect.y,
width: seriesClipRect.width,
height: seriesClipRect.height
});
var striplineGroup = chart.renderer.createGroup({
id: id + 'collections',
'clip-path': 'url(#' + id + 'ClipRect' + ')'
});
if (!chart.enableCanvas) {
striplineGroup.appendChild(appendClipElement(chart.redraw, options, chart.renderer));
}
for (var _i = 0, axes_1 = axes; _i < axes_1.length; _i++) {
var axis = axes_1[_i];
var count = 0;
for (var _a = 0, _b = axis.stripLines; _a < _b.length; _a++) {
var stripline = _b[_a];
if (stripline.visible && stripline.zIndex === position) {
if (stripline.isSegmented && stripline.segmentStart != null && stripline.segmentEnd != null &&
stripline.sizeType !== 'Pixel') {
segmentAxis = this.getSegmentAxis(axes, axis, stripline);
}
if (stripline.isRepeat && stripline.repeatEvery != null && stripline.size !== null && stripline.sizeType !== 'Pixel') {
limit = (stripline.repeatUntil != null) ? ((axis.valueType === 'DateTime') ?
this.dateToMilliSeconds(stripline.repeatUntil, chart) : +stripline.repeatUntil) : axis.actualRange.max;
startValue = axis.valueType === 'DateTime' && this.isCoreDate(stripline.start) ?
this.dateToMilliSeconds(stripline.start, chart) : stripline.start;
if ((stripline.startFromAxis && axis.valueType === 'DateTime' && stripline.sizeType === 'Auto') ||
(stripline.start < axis.visibleRange.min)) {
startValue = axis.visibleLabels[0] &&
axis.visibleLabels[0].value === axis.visibleRange.min ? axis.visibleRange.min :
axis.visibleLabels[0] && axis.visibleLabels[0].value - (axis.valueType === 'DateTime' ? axis.dateTimeInterval :
axis.visibleRange.interval);
}
startValue = stripline.startFromAxis && axis.valueType !== 'DateTime' ? axis.visibleRange.min : startValue;
while (startValue < limit) {
end = (startValue + (axis.valueType === 'DateTime' ? axis.dateTimeInterval * +stripline.size : stripline.size));
range = withIn(end, axis.visibleRange);
if ((startValue >= axis.visibleRange.min && startValue < axis.visibleRange.max) || range) {
this.renderStripLineElement(axis, stripline, seriesClipRect, id, striplineGroup, chart, startValue, segmentAxis, count);
}
count++;
startValue = this.getStartValue(axis, stripline, startValue);
}
}
else {
this.renderStripLineElement(axis, stripline, seriesClipRect, id, striplineGroup, chart, null, segmentAxis, count);
count++;
}
}
}
}
appendChildElement(chart.enableCanvas, chart.svgObject, striplineGroup, chart.redraw);
};
/**
* To convert the C# date to js date
*
* @param {string | number | Object} value date value
* @returns {boolean} returns true if datetime value type is string(for asp platform)
*/
StripLine.prototype.isCoreDate = function (value) {
return typeof value === 'string' ? true : false;
};
/**
* To get the total milli seconds
*
* @param {Date | number | Object} value date value
* @param {Chart} chart chart instance
* @returns {number} returns milliseconds
*/
StripLine.prototype.dateToMilliSeconds = function (value, chart) {
return this.dateParse(value, chart).getTime();
};
/**
* To draw the single line strip line
*
* @param {StripLineSettingsModel} stripline stripline
* @param {Rect} rect rect
* @param {string} id id
* @param {Element} parent parent
* @param {Chart} chart chart
* @param {Axis} axis axis
* @returns {void}
*/
StripLine.prototype.renderPath = function (stripline, rect, id, parent, chart, axis) {
var element = getElement(id);
var direction = element ? element.getAttribute('d') : '';
var strokeWidth = stripline.size;
var d = (axis.orientation === 'Vertical') ? ('M ' + rect.x + ' ' + rect.y + ' ' + 'L ' + (rect.x + rect.width)
+ ' ' + rect.y) :
('M ' + rect.x + ' ' + rect.y + ' ' + 'L ' + rect.x + ' ' + (rect.y + rect.height));
if (stripline.sizeType !== 'Pixel') {
d = (axis.orientation === 'Vertical') ? ('M ' + rect.x + ' ' + (rect.y + (rect.height / 2)) + ' ' + 'L ' + (rect.x + rect.width)
+ ' ' + (rect.y + (rect.height / 2))) :
('M ' + (rect.x + (rect.width / 2)) + ' ' + rect.y + ' ' + 'L ' + (rect.x + (rect.width / 2)) + ' ' + (rect.y + rect.height));
strokeWidth = axis.orientation === 'Vertical' ? rect.height : rect.width;
}
appendChildElement(chart.enableCanvas, parent, chart.renderer.drawPath(new PathOption(id, 'none', strokeWidth, stripline.color, stripline.opacity, stripline.dashArray, d)), chart.redraw, true, 'x', 'y', null, direction, true, null, null, chart.duration);
};
/**
* To draw the rectangle
*
* @param {StripLineSettingsModel} stripline stripline
* @param {Rect} rect rect
* @param {string} id id
* @param {Element} parent parent
* @param {Chart} chart chart
* @returns {void}
*/
StripLine.prototype.renderRectangle = function (stripline, rect, id, parent, chart) {
var element = getElement(id);
var previousRect = element ? new Rect(+element.getAttribute('x'), +element.getAttribute('y'), +element.getAttribute('width'), +element.getAttribute('height')) : null;
appendChildElement(chart.enableCanvas, parent, chart.renderer.drawRectangle(new RectOption(id, 'none', stripline.border, stripline.opacity, rect, 0, 0, '', stripline.border.dashArray)), chart.redraw, true, 'x', 'y', null, null, true, true, previousRect, chart.duration);
};
/**
* To draw the Image
*
* @param {StripLineSettingsModel} stripline stripline
* @param {Rect} rect rect
* @param {string} id id
* @param {Element} parent parent
* @param {Chart} chart chart
* @returns {void}
*/
StripLine.prototype.drawImage = function (stripline, rect, id, parent, chart) {
if (stripline.sizeType === 'Pixel') {
rect.width = rect.width ? rect.width : stripline.size;
rect.height = rect.height ? rect.height : stripline.size;
}
var image = new ImageOption(rect.height, rect.width, stripline.imageUrl, rect.x, rect.y, id, 'visible', 'none');
var htmlObject = chart.renderer.drawImage(image);
appendChildElement(chart.enableCanvas, parent, htmlObject, chart.redraw, true, 'x', 'y', null, null, true, true);
};
/**
* To create the text on strip line
*
* @param {StripLineSettingsModel} stripline stripline
* @param {Rect} rect rect
* @param {string} id id
* @param {Element} parent parent
* @param {Chart} chart chart
* @param {Axis} axis axis
* @returns {void}
*/
StripLine.prototype.renderText = function (stripline, rect, id, parent, chart, axis) {
var textSize = measureText(stripline.text, stripline.textStyle, chart.themeStyle.stripLineLabelFont);
var isRotationNull = (stripline.rotation === null);
var textMid = isRotationNull ? 3 * (textSize.height / 8) : 0;
var ty = rect.y + (rect.height / 2) + textMid;
var rotation = isRotationNull ? ((axis.orientation === 'Vertical') ? 0 : -90) : stripline.rotation;
var tx = rect.x + (rect.width / 2);
var anchor;
var padding = 5;
if (axis.orientation === 'Horizontal') {
tx = this.getTextStart(tx + (textMid * this.factor(stripline.horizontalAlignment)), rect.width, stripline.horizontalAlignment);
ty = this.getTextStart(ty - textMid, rect.height, stripline.verticalAlignment) +
(stripline.verticalAlignment === 'Start' && !isRotationNull ? (textSize.height / 4) : 0);
anchor = isRotationNull ? this.invertAlignment(stripline.verticalAlignment) : stripline.horizontalAlignment;
var isVertical = Math.abs(stripline.rotation) === 90 || Math.abs(stripline.rotation) === 270;
var halfSize = isVertical ? textSize.height / 2 : textSize.width / 2;
anchor = (tx - halfSize < axis.rect.x) ? 'Start' :
(tx + halfSize > axis.rect.x + axis.rect.width) ? 'End' : anchor;
}
else {
tx = this.getTextStart(tx, rect.width, stripline.horizontalAlignment);
ty = this.getTextStart(ty + (textMid * this.factor(stripline.verticalAlignment)) - padding, rect.height, stripline.verticalAlignment);
anchor = stripline.horizontalAlignment;
anchor = chart.enableRtl ? (anchor === 'End' ? 'Start' : anchor === 'Start' ? 'End' : anchor) : anchor;
}
textElement(chart.renderer, new TextOption(id, tx, ty, anchor, stripline.text, 'rotate(' + rotation + ' ' + tx + ',' + ty + ')', 'middle'), stripline.textStyle, stripline.textStyle.color || chart.themeStyle.stripLineLabelFont.color, parent, null, null, null, null, null, null, null, null, chart.enableCanvas, null, chart.themeStyle.stripLineLabelFont);
};
StripLine.prototype.invertAlignment = function (anchor) {
switch (anchor) {
case 'Start':
anchor = 'End';
break;
case 'End':
anchor = 'Start';
break;
}
return anchor;
};
/**
* To find the next value of the recurrence strip line
*
* @param {Axis} axis axis
* @param {StripLineSettingsModel} stripline stripline
* @param {number} startValue startValue
* @returns {number} next start value of the recurrence strip line
*/
StripLine.prototype.getStartValue = function (axis, stripline, startValue) {
if (axis.valueType === 'DateTime') {
return (this.getToValue(null, startValue, +stripline.repeatEvery, axis, null, stripline));
}
else {
return startValue + (+stripline.repeatEvery);
}
};
/**
* Finds the segment axis for a segmented strip line.
*
* @param {Axis[]} axes - The collection of axes.
* @param {Axis} axis - The axis.
* @param {StripLineSettingsModel} stripline - The strip line settings.
* @returns {Axis} - The segment axis.
* @private
*/
StripLine.prototype.getSegmentAxis = function (axes, axis, stripline) {
var segment;
if (stripline.segmentAxisName == null) {
return (axis.orientation === 'Horizontal') ? axes[1] : axes[0];
}
else {
for (var i = 0; i < axes.length; i++) {
if (stripline.segmentAxisName === axes[i].name) {
segment = axes[i];
}
}
return segment;
}
};
/**
* To render strip line on chart
*
* @param {Axis} axis axis
* @param {StripLineSettingsModel} stripline stripline
* @param {Rect} seriesClipRect seriesClipRect
* @param {string} id id
* @param {Element} striplineGroup striplineGroup
* @param {Chart} chart chart
* @param {number} startValue startValue
* @param {Axis} segmentAxis segmentAxis
* @param {number} count count
* @returns {void}
*/
StripLine.prototype.renderStripLineElement = function (axis, stripline, seriesClipRect, id, striplineGroup, chart, startValue, segmentAxis, count) {
var rect = this.measureStripLine(axis, stripline, seriesClipRect, startValue, segmentAxis, chart);
if (stripline.imageUrl) {
this.drawImage(stripline, rect, id + 'rect_' + axis.name + '_' + count, striplineGroup, chart);
}
else {
this.renderPath(stripline, rect, id + (stripline.sizeType === 'Pixel' ? 'path_' : 'rect_') + axis.name + '_' + count, striplineGroup, chart, axis);
var pixelRect = new Rect(axis.orientation === 'Horizontal' ? (rect.x - stripline.size / 2) : rect.x, axis.orientation === 'Vertical' ? (rect.y - stripline.size / 2) : rect.y, rect.width ? rect.width : stripline.size, rect.height ? rect.height : stripline.size);
this.renderRectangle(stripline, stripline.sizeType === 'Pixel' ? pixelRect : rect, id + 'border_' + axis.name + '_' + count, striplineGroup, chart);
}
if (stripline.text !== '') {
this.renderText(stripline, rect, id + 'text_' + axis.name + '_' + count, striplineGroup, chart, axis);
}
};
/**
* Finds the factor of the text based on its anchor position.
*
* @param {Anchor} anchor - The text anchor position.
* @returns {number} - The factor.
* @private
*/
StripLine.prototype.factor = function (anchor) {
var factor = 0;
switch (anchor) {
case 'Start':
factor = 1;
break;
case 'End':
factor = -1;
break;
}
return factor;
};
/**
* Finds the start value of the text based on its alignment.
*
* @param {number} xy - The coordinate value.
* @param {number} size - The size of the text.
* @param {Anchor} textAlignment - The text alignment.
* @returns {number} - The start value.
* @private
*/
StripLine.prototype.getTextStart = function (xy, size, textAlignment) {
var padding = 5;
switch (textAlignment) {
case 'Start':
xy = xy - (size / 2) + padding;
break;
case 'End':
xy = xy + (size / 2) - padding;
break;
}
return xy;
};
/**
* To get the module name for `StripLine`.
*
* @private
* @returns {string} - Returns the module name.
*/
StripLine.prototype.getModuleName = function () {
return 'StripLine';
};
/**
* To destroy the `StripLine` module.
*
* @private
* @returns {void}
*/
StripLine.prototype.destroy = function () {
// destroy peform here
};
return StripLine;
}());
export { StripLine };