@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.
616 lines (615 loc) • 27.2 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { extend, Browser, remove, ChildProperty, Property, Complex } from '@syncfusion/ej2-base';
import { ChartLocation, Point3D } from '../../common/utils/helper';
import { Rect } from '@syncfusion/ej2-svg-base';
import { BaseTooltip } from '../../common/user-interaction/tooltip';
import { tooltipRender } from '../../common/model/constants';
import { isNullOrUndefined } from '@syncfusion/ej2-base';
import { Border, Font } from '../../common/model/base';
import { Location } from '../../common/model/base';
import { valueToCoefficients } from '../utils/chart3dRender';
/**
* Configures the ToolTips in the chart.
*
* @public
*/
var Chart3DTooltipSettings = /** @class */ (function (_super) {
__extends(Chart3DTooltipSettings, _super);
function Chart3DTooltipSettings() {
return _super !== null && _super.apply(this, arguments) || this;
}
__decorate([
Property(false)
], Chart3DTooltipSettings.prototype, "enable", void 0);
__decorate([
Property(true)
], Chart3DTooltipSettings.prototype, "enableMarker", void 0);
__decorate([
Property(null)
], Chart3DTooltipSettings.prototype, "fill", void 0);
__decorate([
Property(null)
], Chart3DTooltipSettings.prototype, "header", void 0);
__decorate([
Property(null)
], Chart3DTooltipSettings.prototype, "opacity", void 0);
__decorate([
Complex({ fontFamily: null, size: '12px', fontStyle: 'Normal', fontWeight: null, color: null }, Font)
], Chart3DTooltipSettings.prototype, "textStyle", void 0);
__decorate([
Property(null)
], Chart3DTooltipSettings.prototype, "format", void 0);
__decorate([
Property(null)
], Chart3DTooltipSettings.prototype, "template", void 0);
__decorate([
Property(true)
], Chart3DTooltipSettings.prototype, "enableAnimation", void 0);
__decorate([
Property(300)
], Chart3DTooltipSettings.prototype, "duration", void 0);
__decorate([
Property(1000)
], Chart3DTooltipSettings.prototype, "fadeOutDuration", void 0);
__decorate([
Property('Move')
], Chart3DTooltipSettings.prototype, "fadeOutMode", void 0);
__decorate([
Property(false)
], Chart3DTooltipSettings.prototype, "enableTextWrap", void 0);
__decorate([
Complex({ color: null, width: null }, Border)
], Chart3DTooltipSettings.prototype, "border", void 0);
__decorate([
Complex({ x: null, y: null }, Location)
], Chart3DTooltipSettings.prototype, "location", void 0);
return Chart3DTooltipSettings;
}(ChildProperty));
export { Chart3DTooltipSettings };
/**
* The `Tooltip` module is used to render the tooltip for chart series.
*/
var Tooltip3D = /** @class */ (function (_super) {
__extends(Tooltip3D, _super);
/**
* Constructor for tooltip module.
*
* @param {Chart3D} chart - Specifies the chart instance
* @private
*/
function Tooltip3D(chart) {
var _this = _super.call(this, chart) || this;
_this.chart3D = chart;
_this.commonXvalues = [];
_this.addEventListener();
return _this;
}
/**
* Adds event listeners for handling mouse and touch events on the chart.
*
* @returns {void}
* @private
*/
Tooltip3D.prototype.addEventListener = function () {
if (this.chart.isDestroyed) {
return;
}
var cancelEvent = Browser.isPointer ? 'pointerleave' : 'mouseleave';
this.chart.on(cancelEvent, this.mouseLeaveHandler, this);
this.chart.on('tapHold', this.longPress, this);
this.chart.on(Browser.touchMoveEvent, this.mouseMoveHandler, this);
this.chart.on(Browser.touchEndEvent, this.mouseUpHandler, this);
};
/**
* Unbinding events for selection module.
*
* @returns {void}
*/
Tooltip3D.prototype.removeEventListener = function () {
if (this.chart.isDestroyed) {
return;
}
this.chart.off('pointerleave' || 'mouseleave', this.mouseLeaveHandler);
this.chart.off('tapHold', this.longPress);
this.chart.off(Browser.touchMoveEvent, this.mouseLeaveHandler);
this.chart.off(Browser.touchMoveEvent, this.mouseMoveHandler);
this.chart.off(Browser.touchEndEvent, this.mouseUpHandler);
};
/**
* Handles the mouse up event for the 3D chart.
*
* @param {MouseEvent | PointerEvent | TouchEvent} event - The mouse or touch event.
* @returns {void}
* @private
*/
Tooltip3D.prototype.mouseUpHandler = function (event) {
var _this = this;
var chart = this.control;
var data = this.get3dData(event);
if (chart.isTouch) {
this.tooltip(event);
if (chart.tooltip.fadeOutMode === 'Move') {
this.removeTooltip(chart.tooltip.fadeOutDuration);
clearTimeout(this.timerId);
this.timerId = +setTimeout(function () {
_this.removeBlurEffect();
}, 500);
}
if (chart.startMove && chart.tooltip.fadeOutMode === 'Move') {
this.removeTooltip(2000);
this.removeBlurEffect();
}
}
else if (!this.findData(data, this.previousPoints[0]) && chart.tooltip.fadeOutMode === 'Click') {
this.removeTooltip(0);
this.removeBlurEffect();
}
};
/**
* Handles the mouse leave event for the 3D chart.
*
* @returns {void}
* @private
*/
Tooltip3D.prototype.mouseLeaveHandler = function () {
this.removeTooltip(this.chart.tooltip.fadeOutDuration);
this.removeBlurEffect();
};
/**
* Handles the mouse move event for the 3D chart.
*
* @param {MouseEvent | PointerEvent | TouchEvent} event - The mouse move event.
* @returns {void}
* @public
*/
Tooltip3D.prototype.mouseMoveHandler = function (event) {
var chart = this.chart3D;
chart.mouseX = chart.mouseX / chart.scaleX;
chart.mouseY = chart.mouseY / chart.scaleY;
// Tooltip for chart series.
if (!chart.disableTrackTooltip && !chart.rotateActivate) {
if (!chart.isTouch || (chart.startMove)) {
this.tooltip(event);
}
}
};
/**
* Handles the long press on chart.
*
* @returns {boolean} false
* @private
*/
Tooltip3D.prototype.longPress = function () {
return false;
};
/**
* To create Tooltip styles for series
*
* @returns {void}
*/
Tooltip3D.prototype.seriesStyles = function () {
if (!this.styleAdded) {
var style = document.createElement('style');
style.setAttribute('id', this.element.id + '_ej2_chart_tooltip');
style.innerText += ' .' + this.element.id + '_ej2_tooltipDeselected { opacity:' + (0.2) + ';} ';
document.body.appendChild(style);
this.styleAdded = true;
}
};
/**
* Handles the tooltip display for the 3D chart.
*
* @param {MouseEvent | PointerEvent | TouchEvent | KeyboardEvent} e - The event triggering the tooltip display.
* @returns {void}
* @public
*/
Tooltip3D.prototype.tooltip = function (e) {
var elementId = this.element.id + '_tooltip_svg';
var svgElement = this.getElement(elementId);
var isTooltip = (svgElement && parseInt(svgElement.getAttribute('opacity'), 10) > 0);
var tooltipDiv = this.getTooltipElement(isTooltip);
if (this.chart3D.tooltip3DModule) {
this.renderSeriesTooltip(this.chart3D, !isTooltip, tooltipDiv, e);
}
};
/**
* Finds the header for the tooltip based on the provided Point3D.
*
* @param {Point3D} data - The Point3D used to find the header.
* @returns {string} - The header for the tooltip.
* @private
*/
Tooltip3D.prototype.findHeader = function (data) {
if (this.header === '') {
return '';
}
this.header = this.parseTemplate(data.point, data.series, this.header, data.series.xAxis, data.series.yAxis);
if (this.header.replace(/<b>/g, '').replace(/<\/b>/g, '').trim() !== '') {
return this.header;
}
return '';
};
/**
* Renders the tooltip for the series in the 3D chart.
*
* @param {Chart3D} chart - The 3D chart instance.
* @param {boolean} isFirst - A boolean indicating whether it is the first series.
* @param {HTMLDivElement} tooltipDiv - The tooltip div element.
* @param {MouseEvent | PointerEvent | TouchEvent | KeyboardEvent} e - The event that triggered the tooltip.
* @returns {void}
* @private
*/
Tooltip3D.prototype.renderSeriesTooltip = function (chart, isFirst, tooltipDiv, e) {
var data = this.get3dData(e);
this.currentPoints = [];
if (this.findData(data, this.previousPoints[0]) &&
((this.previousPoints[0] && !((this.previousPoints[0].point.index === data.point.index && this.previousPoints[0].series.index
=== data.series.index) && this.chart3D.isRemove)) || !this.previousPoints[0])) {
if (this.pushData(data, isFirst, tooltipDiv, true)) {
this.triggerTooltipRender(data, isFirst, this.getTooltipText(data), this.findHeader(data));
}
}
else if (!data.point && this.chart3D.isRemove && chart.tooltip.fadeOutMode === 'Move') {
this.removeTooltip(this.chart.tooltip.fadeOutDuration);
this.removeBlurEffect();
this.chart3D.isRemove = false;
}
if (data && data.point) {
this.findMouseValue(data, chart);
}
};
/**
* Triggers the rendering of the tooltip with the specified point and text information.
*
* @param {Point3D} point - The data point for which the tooltip is triggered.
* @param {boolean} isFirst - A boolean indicating whether it is the first series.
* @param {string} textCollection - The text information to be displayed in the tooltip.
* @param {string} headerText - The header text for the tooltip.
* @returns {void}
* @private
*/
Tooltip3D.prototype.triggerTooltipRender = function (point, isFirst, textCollection, headerText) {
var _this = this;
var tooltipTemplate;
var argsData = {
cancel: false, text: textCollection, headerText: headerText, template: tooltipTemplate,
textStyle: this.textStyle,
data: {
pointX: point.point.x, pointY: point.point.y, seriesIndex: point.series.index, seriesName: point.series.name,
pointIndex: point.point.index, pointText: point.point.text
}
};
var borderWidth = this.chart.border.width;
var padding = 3;
var chartTooltipSuccess = function (argsData) {
if (!argsData.cancel) {
_this.headerText = argsData.headerText;
_this.formattedText = _this.formattedText.concat(argsData.text);
_this.text = _this.formattedText;
_this.createTooltip(_this.chart, isFirst, _this.getSymbolLocation(point), point.series.clipRect, point.point, _this.chart3D.tooltip.enableMarker ? ['Circle'] : [], 0, new Rect(borderWidth, borderWidth, _this.chart.availableSize.width - padding - borderWidth * 2, _this.chart.availableSize.height - padding - borderWidth * 2), false, null, _this.getTemplateText(point), _this.template ? argsData.template : '');
_this.blurEffect(_this.chart3D.visibleSeries, point.series);
}
else {
_this.removeHighlight();
remove(_this.getElement(_this.element.id + '_tooltip'));
}
_this.chart3D.isRemove = true;
};
chartTooltipSuccess.bind(this, point);
this.chart.trigger(tooltipRender, argsData, chartTooltipSuccess);
};
/**
* Applies a blur effect to the specified series while removing the effect from others.
*
* @param {Chart3DSeries[]} visibleSeries - The array of visible series in the 3D chart.
* @param {Chart3DSeries} tooltipSeries - The series associated with the tooltip.
* @returns {void}
* @private
*/
Tooltip3D.prototype.blurEffect = function (visibleSeries, tooltipSeries) {
if (!this.chart3D.highlight3DModule || (this.chart3D.legendSettings.enableHighlight && this.chart3D.highlightMode === 'None')) {
var pointElements_1 = [];
for (var _i = 0, visibleSeries_1 = visibleSeries; _i < visibleSeries_1.length; _i++) {
var series = visibleSeries_1[_i];
if (series.visible && series.index !== tooltipSeries.index) {
var elements = document.querySelectorAll("[id*=\"region-series-" + series.index + "\"]");
elements.forEach(function (el) {
pointElements_1.push(el);
});
}
else if (series.visible) {
var tooltipElements = document.querySelectorAll("[id*=\"region-series-" + series.index + "\"]");
for (var i = 0; i < tooltipElements.length; i++) {
var element = tooltipElements[i];
var elementClassName = element.getAttribute('class') || '';
if (elementClassName.indexOf(this.element.id + '_ej2_tooltipDeselected') > -1) {
element.setAttribute('class', elementClassName.replace(this.element.id + '_ej2_tooltipDeselected', ''));
}
this.chart3D.stopElementAnimation(element, series.index);
}
}
}
for (var i = 0; i < pointElements_1.length; i++) {
if (pointElements_1[i]) {
var elementClassName = pointElements_1[i].getAttribute('class') || '';
elementClassName += ((elementClassName !== '') ? ' ' : '');
if (elementClassName.indexOf('_selection_') === -1 && elementClassName.indexOf(this.element.id + '_ej2_tooltipDeselected') === -1) {
pointElements_1[i].setAttribute('class', elementClassName + this.element.id + '_ej2_tooltipDeselected');
}
}
}
}
};
Tooltip3D.prototype.removeBlurEffect = function () {
if (!this.chart3D.highlight3DModule || (this.chart3D.legendSettings.enableHighlight && this.chart3D.highlightMode === 'None')) {
var elements = document.getElementsByClassName(this.element.id + '_ej2_tooltipDeselected');
while (elements.length > 0) {
var element = elements[0];
var elementClassName = element.getAttribute('class') || '';
if (elementClassName.indexOf(this.element.id + '_ej2_tooltipDeselected') > -1) {
element.setAttribute('class', elementClassName.replace(this.element.id + '_ej2_tooltipDeselected', ''));
var index = parseFloat(element.id.split('-series-')[1].split('-point-')[0]);
this.chart3D.highlightAnimation(element, index, 700, 0.2);
}
}
}
};
/**
* Gets the location of the symbol based on the current mouse position in the chart.
*
* @param {Point3D} point - The tooltip point.
* @returns {ChartLocation} - The location of the tooltip.
* @private
*/
Tooltip3D.prototype.getSymbolLocation = function (point) {
var rect = document.getElementById(this.element.id + '_svg').getBoundingClientRect();
var upperElement;
if (point.series.columnFacet === 'Cylinder') {
upperElement = document.querySelectorAll('[id*="' + this.element.id + '-svg-' + (point.series.type.indexOf('Column') === -1 ? '0' : '1') + '-region-series-' + point.series.index + '-point-' + point.point.index + '"]');
}
else {
upperElement = document.querySelectorAll('[id*="' + this.element.id + '-svg-' + (point.series.type.indexOf('Column') === -1 ? '5' : '2') + '-region-series-' + point.series.index + '-point-' + point.point.index + '"]');
}
var tooltipElement;
if (upperElement) {
if (upperElement.length === 1) {
tooltipElement = upperElement[0].getBoundingClientRect();
}
else {
for (var i = 0; i < upperElement.length; i++) {
var element = upperElement[i];
if (element.id.indexOf('-' + point.point.index + '-back-front') !== -1 || element.id.indexOf('-' + point.point.index + '-front-back') !== -1) {
tooltipElement = element.getBoundingClientRect();
break;
}
}
}
if (upperElement.length !== 0 && !tooltipElement) {
tooltipElement = upperElement[0].getBoundingClientRect();
}
}
var location = new ChartLocation((this.chart3D.tooltip.location.x !== null) ? this.chart3D.tooltip.location.x :
tooltipElement.left - rect.left + (tooltipElement.width / 2), (this.chart3D.tooltip.location.y !== null) ?
this.chart3D.tooltip.location.y : tooltipElement.top - rect.top + (tooltipElement.height / 2));
return location;
};
/**
* Gets the tooltip text based on the provided point data.
*
* @param {Point3D} pointData - The data of the point for which the tooltip is generated.
* @returns {string} - The tooltip text.
* @private
*/
Tooltip3D.prototype.getTooltipText = function (pointData) {
return this.parseTemplate(pointData.point, pointData.series, this.getFormat(this.chart3D, pointData.series), pointData.series.xAxis, pointData.series.yAxis);
};
/**
* Gets the template text based on the provided data.
*
* @param {Point3D} data - The data object for which the template text is generated.
* @returns {Chart3DPoint | Chart3DPoint[]} - The template text.
* @private
*/
Tooltip3D.prototype.getTemplateText = function (data) {
if (this.template) {
var point = extend({}, data.point);
point.x = this.formatPointValue(data.point, data.series.xAxis, 'x', true, false);
point.y = this.formatPointValue(data.point, data.series.yAxis, 'y', false, true);
return point;
}
else {
return data.point;
}
};
/**
* Finds the mouse value based on the provided data and chart.
*
* @param {Point3D} data - The data object containing information about the point.
* @param {Chart3D} chart - The Chart3D instance.
* @returns {void}
* @private
*/
Tooltip3D.prototype.findMouseValue = function (data, chart) {
if (!chart.requireInvertedAxis) {
this.valueX = valueToCoefficients(data.point.xValue, data.series.xAxis) *
data.series.xAxis.rect.width + data.series.xAxis.rect.x;
this.valueY = chart.mouseY;
}
else {
this.valueY = (1 - valueToCoefficients(data.point.xValue, data.series.xAxis)) * data.series.xAxis.rect.height
+ data.series.xAxis.rect.y;
this.valueX = chart.mouseX;
}
};
/**
* Parses the template using the provided point, series, format, xAxis, and yAxis information.
*
* @param {Chart3DPoint} point - The point for which the template needs to be parsed.
* @param {Chart3DSeries} series - The series associated with the point.
* @param {string} format - The format string.
* @param {Chart3DAxis} xAxis - The X-axis of the chart.
* @param {Chart3DAxis} yAxis - The Y-axis of the chart.
* @returns {string} - The parsed template string.
* @private
*/
Tooltip3D.prototype.parseTemplate = function (point, series, format, xAxis, yAxis) {
var val;
var textValue;
var regExp = RegExp;
for (var _i = 0, _a = Object.keys(point); _i < _a.length; _i++) {
var dataValue = _a[_i];
val = new regExp('${point' + '.' + dataValue + '}', 'gm');
format = format.replace(val.source, this.formatPointValue(point, val.source === '${point.x}' ? xAxis : yAxis, dataValue, val.source === '${point.x}', (val.source === '${point.y}')));
}
for (var _b = 0, _c = Object.keys(Object.getPrototypeOf(series)); _b < _c.length; _b++) {
var dataValue = _c[_b];
val = new regExp('${series' + '.' + dataValue + '}', 'gm');
textValue = series[dataValue];
format = format.replace(val.source, textValue);
}
return format;
};
/**
* Formats the point value based on the provided point, axis, dataValue, and other flags.
*
* @param {Chart3DPoint} point - The point for which the value needs to be formatted.
* @param {Chart3DAxis} axis - The axis associated with the point.
* @param {string} dataValue - The data value to be formatted.
* @param {boolean} isXPoint - Indicates whether the point is on the X-axis.
* @param {boolean} isYPoint - Indicates whether the point is on the Y-axis.
* @returns {string} - The formatted point value.
* @private
*/
Tooltip3D.prototype.formatPointValue = function (point, axis, dataValue, isXPoint, isYPoint) {
var textValue;
var customLabelFormat;
var value;
if (axis.valueType !== 'Category' && isXPoint) {
customLabelFormat = axis.labelFormat && axis.labelFormat.match('{value}') !== null;
textValue = customLabelFormat ? axis.labelFormat.replace('{value}', axis.format(point[dataValue])) :
axis.format(point[dataValue]);
}
else if (isYPoint && !isNullOrUndefined(point[dataValue])) {
customLabelFormat = axis.labelFormat && axis.labelFormat.match('{value}') !== null;
value = axis.format(point[dataValue]);
textValue = customLabelFormat ? axis.labelFormat.replace('{value}', value) : value;
}
else {
textValue = point[dataValue];
}
return textValue;
};
/**
* Gets the format for the tooltip based on the provided chart and series.
*
* @param {Chart3D} chart - The 3D chart instance.
* @param {Chart3DSeries} series - The 3D series for which the tooltip format is needed.
* @returns {string} - The tooltip format.
* @private
*/
Tooltip3D.prototype.getFormat = function (chart, series) {
if (series.tooltipFormat) {
return series.tooltipFormat;
}
if (!series.tooltipFormat && chart.tooltip.format) {
return chart.tooltip.format;
}
var textX = '${point.x}';
var format = textX;
return format + ' : ' + (chart.theme.indexOf('Tailwind3') > -1 ? '${point.y}' : '<b>${point.y}</b>');
};
/**
* Gets the 3D data (point and series) associated with the provided event in the chart.
*
* @param {MouseEvent | PointerEvent | TouchEvent | KeyboardEvent} event - The event for which to retrieve 3D data.
* @returns {Point3D} - The 3D data object containing the point and series information.
* @private
*/
Tooltip3D.prototype.get3dData = function (event) {
var chart = this.chart3D;
var point = null;
var series = null;
var currentX = this.chart3D.mouseX;
var currentY = this.chart3D.mouseY;
var rect = this.chart3D.chartAxisLayoutPanel.seriesClipRect;
var index;
var pointIndex;
var seriesIndex;
var targetElement = event.target;
if (targetElement && currentX > rect.x && currentX < (rect.x + rect.width) &&
currentY > rect.y && currentY < (rect.y + rect.height)) {
var nodeName = targetElement.nodeName;
if ((nodeName === 'shape' || nodeName === 'path') && targetElement.id.indexOf('region') > 1) {
index = targetElement.id.match(/(\d+)/g);
pointIndex = parseInt(index[index.length - 1].toString(), 10);
seriesIndex = parseInt(index[index.length - 2].toString(), 10);
}
}
if (!isNullOrUndefined(seriesIndex)) {
series = chart.visibleSeries[seriesIndex];
}
if (series) {
if (series.visible) {
point = series.points[pointIndex];
}
if (point) {
return new Point3D(point, series);
}
}
return new Point3D(point, series);
};
/**
* Finds data based on the provided 3D data and the previous 3D data.
*
* @param {Point3D} data - The current 3D data.
* @param {Point3D} previous - The previous 3D data.
* @returns {boolean} - Returns true if the data is found based on the conditions.
* @private
*/
Tooltip3D.prototype.findData = function (data, previous) {
return data.point && ((!previous || (previous.point !== data.point)) || (previous.point === data.point));
};
/**
* Gets the module name.
*
* @returns {string} - The module name.
*/
Tooltip3D.prototype.getModuleName = function () {
/**
* Returns the module name
*/
return 'Tooltip3D';
};
/**
* To destroy the tooltip.
*
* @returns {void}
* @private
*/
Tooltip3D.prototype.destroy = function () {
/**
* Destroy method performed here
*/
this.removeEventListener();
};
return Tooltip3D;
}(BaseTooltip));
export { Tooltip3D };