@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.
422 lines (421 loc) • 21.7 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 __());
};
})();
import { drawSymbol } from '../../common/utils/helper';
import { PathOption, Size } from '@syncfusion/ej2-svg-base';
import { Browser, extend, remove, isNullOrUndefined, Animation } from '@syncfusion/ej2-base';
import { ChartData } from '../../chart/utils/get-data';
import { withInBounds, PointData, stopTimer, getElement } from '../../common/utils/helper';
import { colorNameToHex, convertHexToColor } from '../../common/utils/helper';
/**
* The `Marker` module is used to render markers for line-type series.
*
* @private
*/
var MarkerExplode = /** @class */ (function (_super) {
__extends(MarkerExplode, _super);
/**
* Constructor for the marker module.
*
* @private
*/
function MarkerExplode(chart) {
var _this = _super.call(this, chart) || this;
_this.elementId = chart.element.id;
_this.commonXvalues = [];
return _this;
}
/**
* Adds event listeners for the series.
*
* @returns {void}
* @private
*/
MarkerExplode.prototype.addEventListener = function () {
if (this.chart.isDestroyed) {
return;
}
this.chart.on(Browser.touchMoveEvent, this.mouseMoveHandler, this);
this.chart.on(Browser.touchEndEvent, this.mouseUpHandler, this);
};
/**
* Removes event listeners for the series.
*
* @private
*
* @returns {void}
*/
MarkerExplode.prototype.removeEventListener = function () {
if (this.chart.isDestroyed) {
return;
}
this.chart.off(Browser.touchMoveEvent, this.mouseMoveHandler);
this.chart.off(Browser.touchEndEvent, this.mouseUpHandler);
};
/**
* Handles the mouse up event.
*
* @returns {void}
*/
MarkerExplode.prototype.mouseUpHandler = function () {
var chart = this.chart;
if (chart.isTouch && !chart.crosshair.enable && !this.isSelected(chart) && !(this.chart.zoomModule && getElement(this.elementId + '_ZoomArea'))) {
this.markerMove(true);
}
};
/**
* Handles the mouse move event.
*
* @returns {void}
* @private
*/
MarkerExplode.prototype.mouseMoveHandler = function () {
var chart = this.chart;
if ((chart.highlightMode !== 'None' || (chart.tooltip.enable)) && (!chart.isTouch || chart.startMove) && !this.isSelected(chart)
&& !(this.chart.zoomModule && (getElement(this.elementId + '_ZoomArea') || this.chart.zoomModule.startPanning))) {
this.markerMove(false);
}
};
MarkerExplode.prototype.markerMove = function (remove) {
var _this = this;
var chart = this.chart;
this.currentPoints = [];
var data;
var previous;
var explodeSeries;
var series;
if (!chart.tooltip.shared || !chart.tooltip.enable) {
data = this.getData();
series = data.series;
previous = this.previousPoints[0];
explodeSeries = series && ((series.type === 'Bubble' || series.drawType === 'Scatter' || series.type === 'Scatter') ||
(((series.type !== 'Candle') && (series.type !== 'Hilo') && (series.type !== 'HiloOpenClose')) &&
(series.marker.visible && series.marker.width !== 0 && series.marker.height !== 0)));
data.lierIndex = this.lierIndex;
if (data.point && explodeSeries && ((!previous || (previous.point !== data.point)) ||
(previous && previous.lierIndex > 3 && previous.lierIndex !== this.lierIndex))) {
this.currentPoints.push(data);
}
if (data.point && explodeSeries && chart.isPointMouseDown) {
this.currentPoints.push(data);
}
if (this.currentPoints.length === 0 && data.point && !explodeSeries && !isNullOrUndefined(previous) &&
previous.point !== data.point) {
this.removeHighlightedMarker(previous.series, previous.point);
this.previousPoints = extend([], data, null, true);
}
if (chart.tooltip.showNearestTooltip && this.chart.tooltipModule && this.chart.tooltipModule.currentPoints && (explodeSeries || (series.type === 'Pareto' && series.paretoOptions.marker.visible)) &&
this.currentPoints.length === 0 && withInBounds(chart.mouseX, chart.mouseY, chart.chartAxisLayoutPanel.seriesClipRect)) {
this.currentPoints = this.chart.tooltipModule.currentPoints;
}
}
else {
if (!withInBounds(chart.mouseX, chart.mouseY, chart.chartAxisLayoutPanel.seriesClipRect)) {
return null;
}
if (chart.tooltip.enable) {
var pointData = chart.chartAreaType === 'PolarRadar' ? this.getData() : null;
if (!this.chart.tooltip.showNearestPoint) {
this.currentPoints = this.chart.tooltipModule.currentPoints;
}
else {
for (var _i = 0, _a = chart.visibleSeries; _i < _a.length; _i++) {
var chartSeries = _a[_i];
if (!chartSeries.enableTooltip || chartSeries.category === 'Indicator') {
continue;
}
if (chart.chartAreaType === 'Cartesian' && chartSeries.visible) {
data = this.getClosestX(chart, chartSeries, this.commonXValue(this.chart.visibleSeries));
}
else if (chart.chartAreaType === 'PolarRadar' && chartSeries.visible && pointData.point !== null) {
data = new PointData(chartSeries.points[pointData.point.index], chartSeries);
}
if (data) {
this.currentPoints.push(data);
data = null;
}
}
}
}
}
var length = this.previousPoints.length;
if (this.currentPoints.length > 0 || (length > 0 && chart.tooltip.shared)) {
if (length === 0 || chart.isPointMouseDown || (length > 0 && (this.currentPoints.length === 0 ||
(this.previousPoints[0].point !== this.currentPoints[0].point)))) {
if (length > 0) {
for (var _b = 0, _c = this.previousPoints; _b < _c.length; _b++) {
var previousPoint = _c[_b];
if (!isNullOrUndefined(previousPoint)) {
this.removeHighlightedMarker(previousPoint.series, previousPoint.point);
}
}
}
var _loop_1 = function (data_1) {
if ((data_1 && data_1.point) || ((series.type !== 'Candle') &&
(series.type !== 'Hilo') && (series.type !== 'HiloOpenClose'))) {
stopTimer(this_1.markerExplode);
this_1.isRemove = true;
data_1.point.symbolLocations.map(function (location, index) {
if (data_1.series.marker.allowHighlight && (!data_1.series.isRectSeries || data_1.point.marker.visible)) {
_this.drawTrackBall(data_1.series, data_1.point, location, index);
}
});
}
};
var this_1 = this;
for (var _d = 0, _e = this.currentPoints; _d < _e.length; _d++) {
var data_1 = _e[_d];
_loop_1(data_1);
}
this.previousPoints = extend([], this.currentPoints, null, true);
}
}
if (!chart.tooltip.enable && ((this.currentPoints.length === 0 && this.isRemove) || (remove && this.isRemove) ||
!withInBounds(chart.mouseX, chart.mouseY, chart.chartAxisLayoutPanel.seriesClipRect))) {
this.isRemove = false;
if (!isNullOrUndefined(this.previousPoints[0])) {
this.markerExplode = +setTimeout(function () {
if (_this.previousPoints[0]) {
_this.removeHighlightedMarker(_this.previousPoints[0].series, _this.previousPoints[0].point);
}
}, 2000);
}
}
this.currentPoints = [];
};
MarkerExplode.prototype.animationDuration = function () {
var duration = 200;
if (this.chart.maxPointCount > 100) {
duration = 10;
}
else if (this.chart.maxPointCount > 50) {
duration = 100;
}
return duration;
};
MarkerExplode.prototype.drawTrackBall = function (series, point, location, index) {
var marker = point.marker;
var seriesMarker = series.marker;
var shape = marker.shape || seriesMarker.shape || 'Circle';
var svg;
if (shape === 'None' || shape === 'Image') {
return null;
}
var element = series.symbolElement || series.seriesElement;
var className;
if (this.chart.highlightModule && this.chart.highlightMode !== 'None') {
className = this.chart.highlightModule.generateStyle(series);
}
if (this.chart.selectionModule && this.chart.selectionMode !== 'None') {
className = this.chart.selectionModule.generateStyle(series);
}
var symbolId = this.elementId + '_Series_' + series.index + '_Point_' + point.index + '_Trackball' +
(index ? index : '');
if (getElement(symbolId + '_1') && getElement(symbolId + '_1').getAttribute('e-animate')) {
Animation.stop(getElement(symbolId + '_1'));
remove(getElement(symbolId + '_1'));
}
var size = new Size((marker.width || seriesMarker.width) + 3, (marker.height || seriesMarker.height) + 3);
var border = (marker.border || series.border);
var explodeSeries = (series.type === 'BoxAndWhisker' || series.type === 'Bubble' || series.type === 'Scatter');
var borderColor = (border.color && border.color !== 'transparent') ? border.color :
marker.fill || point.interior || (explodeSeries ? point.color : series.interior);
var colorValue = convertHexToColor(colorNameToHex(borderColor));
var borderWidth = marker.border ? marker.border.width : seriesMarker.border.width;
var markerShadow = series.chart.themeStyle.markerShadow ||
'rgba(' + colorValue.r + ',' + colorValue.g + ',' + colorValue.b + ',0.2)';
var markerElement = document.getElementById(this.elementId + '_Series_' + series.index + '_Point_' +
point.index + '_Symbol');
if (!isNullOrUndefined(markerElement)) {
markerElement.setAttribute('visibility', 'visible');
}
if (this.chart.enableCanvas) {
var trackElement = document.getElementById(this.chart.element.id + '_Secondary_Element');
svg = this.chart.svgRenderer.createSvg({
id: this.chart.element.id + '_trackball_svg',
width: this.chart.availableSize.width,
height: this.chart.availableSize.height
});
svg.style.cssText = 'position: absolute; display:block; pointer-events: none';
trackElement.appendChild(svg);
}
for (var i = 0; i < 2; i++) {
var options = new PathOption(symbolId + '_' + i, i ? (marker.fill || point.color || (explodeSeries ? series.interior : '#ffffff')) : 'transparent', borderWidth + (i ? 0 : 8), i ? borderColor : markerShadow, (marker.opacity || seriesMarker.opacity), series.marker.border.dashArray, '');
var symbol = drawSymbol(location, shape, size, marker.imageUrl, options, '', this.chart.svgRenderer, series.clipRect);
// incident: 252450 point click selection not working while maker explode
//symbol.setAttribute('style', 'pointer-events:none');
symbol.setAttribute('class', this.elementId + '_EJ2-Trackball_Series_' + series.index + '_Point_' + point.index);
var selectionId = element.id.indexOf('Symbol') !== -1 ? '_Symbol' : '';
var seletionElem = document.getElementById(this.elementId + '_Series_' + series.index + '_Point_' +
point.index + selectionId);
if (className !== '' && !isNullOrUndefined(className) && !isNullOrUndefined(seletionElem) &&
seletionElem.hasAttribute('class') && (className === seletionElem.getAttribute('class'))) {
symbol.classList.add(className);
}
symbol.setAttribute('clip-path', element.getAttribute('clip-path'));
symbol.setAttribute('transform', element.getAttribute('transform'));
if (this.chart.enableCanvas) {
svg.appendChild(symbol);
}
else {
this.chart.svgObject.appendChild(symbol);
}
if (point.symbolLocations.length > 1 && series.marker.visible && (series.type !== 'Bubble' && series.type !== 'Scatter')) {
this.trackballAnimate(symbol, 0, this.animationDuration(), series, point.index, location, false, false);
}
}
if (point.symbolLocations.length < 2 && series.marker.visible) {
this.doAnimation(series, point, false);
}
};
/**
* Perform animation for the series.
*
* @param {Series} series - The series to animate.
* @param {Points} point - The point to animate.
* @param {boolean} [endAnimate=false] - Flag to indicate if the animation is ending.
* @returns {void}
* @private
*/
MarkerExplode.prototype.doAnimation = function (series, point, endAnimate) {
if (endAnimate === void 0) { endAnimate = false; }
if (series.type === 'Bubble' || series.type === 'Scatter') {
return;
}
var duration = this.animationDuration();
var delay = 0;
var rectElements = document.getElementsByClassName(this.elementId + '_EJ2-Trackball_Series_' + series.index + '_Point_' + point.index);
for (var i = 0, len = rectElements.length; i < len; i++) {
this.trackballAnimate(rectElements[i], delay, duration, series, point.index, point.symbolLocations[0], false, endAnimate);
}
};
/**
* Perform animation for the trackball.
*
* @param {Element} elements - The elements to animate.
* @param {number} delays - The delay duration for the animation.
* @param {number} durations - The duration of the animation.
* @param {Series} series - The series associated with the trackball.
* @param {number} pointIndex - The index of the point to animate.
* @param {ChartLocation} point - The location of the point to animate.
* @param {boolean} isLabel - Flag to indicate if the animated element is a label.
* @param {boolean} [endAnimate=false] - Flag to indicate if the animation is ending.
* @param {boolean} [isRemove=false] - Flag to indicate if element need to remove.
* @returns {void}
* @private
*/
MarkerExplode.prototype.trackballAnimate = function (elements, delays, durations, series, pointIndex, point, isLabel, endAnimate, isRemove) {
var centerX = point.x;
var centerY = point.y;
var clipX = (series.type !== 'Polar' && series.type !== 'Radar') ? series.clipRect.x : 0;
var clipY = (series.type !== 'Polar' && series.type !== 'Radar') ? series.clipRect.y : 0;
// let height: number = 0;
//(<HTMLElement>elements).style.visibility = 'hidden';
var transform = elements.getAttribute('transform');
var scaleX = (series.marker.width / (series.marker.width + 3));
var scaleY = (series.marker.height / (series.marker.height + 3));
var scaleValue = Math.min(scaleX, scaleY);
if (!isRemove) {
elements.setAttribute('transform', "translate(" + (centerX + clipX) + " " + (centerY + clipY) + ") scale(" + scaleValue + ") translate(" + -centerX + " " + -centerY + ")");
}
new Animation({}).animate(elements, {
duration: durations,
delay: delays,
progress: function (args) {
args.element.style.animation = '';
if (args.timeStamp > args.delay) {
if (!series.visible && isRemove) {
remove(elements);
return;
}
var progress = args.timeStamp / args.duration;
var currentScale = isRemove
? Math.max(scaleValue, 1 - ((1 - scaleValue) * progress))
: Math.min(1, scaleValue + ((1 - scaleValue) * progress));
elements.setAttribute('transform', "translate(" + (centerX + clipX) + " " + (centerY + clipY) + ") scale(" + currentScale + ") translate(" + -centerX + " " + -centerY + ")");
}
},
end: function () {
elements.style.visibility = '';
elements.setAttribute('transform', transform);
if (!isLabel && (pointIndex === series.points.length - 1)) {
series.chart.trigger('animationComplete', { series: series.chart.isBlazor ? {} : series });
}
if (isRemove || endAnimate) {
remove(elements);
}
}
});
};
/**
* Remove the highlighted marker.
*
* @param {Series} [series=null] - The series associated with the marker to remove. Defaults to null.
* @param {Points} [point=null] - The point associated with the marker to remove. Defaults to null.
* @param {boolean} [fadeOut=false] - Flag to indicate if the removal should be faded out. Defaults to false.
* @returns {void}
* @private
*/
MarkerExplode.prototype.removeHighlightedMarker = function (series, point, fadeOut) {
if (series === void 0) { series = null; }
if (point === void 0) { point = null; }
if (fadeOut === void 0) { fadeOut = false; }
if (!isNullOrUndefined(series) && !isNullOrUndefined(point)) {
var markerElement = document.getElementById(this.elementId + '_Series_' + series.index + '_Point_' +
point.index + '_Symbol');
var trackballElements = document.getElementsByClassName(this.elementId + '_EJ2-Trackball_Series_' + series.index + '_Point_' + point.index);
if (trackballElements.length === 0) {
var elements = document.querySelectorAll("[class*=\"" + (this.elementId + '_EJ2-Trackball_Series_' + series.index + '_Point_' + point.index) + "\"]");
if (elements[1]) {
elements[1].remove();
}
if (elements[0]) {
elements[0].remove();
}
}
for (var i = trackballElements.length - 1; i >= 0; i--) {
if (!series.marker.visible || trackballElements[i] && trackballElements[i].id[trackballElements[i].id.length - 1] === '0') {
remove(trackballElements[i]);
}
}
for (var i = trackballElements.length - 1; i >= 0; i--) {
if (trackballElements[i] && trackballElements[i].id[trackballElements[i].id.length - 1] === '1' && (series.type !== 'Bubble' && series.type !== 'Scatter') && series.marker.visible) {
trackballElements[i].setAttribute('opacity', markerElement ? markerElement.getAttribute('opacity') : trackballElements[i].getAttribute('opacity'));
this.trackballAnimate(trackballElements[i], 0, this.animationDuration(), series, point.index, point.symbolLocations[i], null, null, true);
}
}
if (!isNullOrUndefined(markerElement)) {
markerElement.setAttribute('visibility', 'visible');
}
}
else {
for (var _i = 0, _a = series.points; _i < _a.length; _i++) {
var point_1 = _a[_i];
var elements = document.getElementsByClassName(this.elementId + '_EJ2-Trackball_Series_' + series.index + '_Point_' + point_1.index);
var markerElement = document.getElementById(this.elementId + '_Series_' + series.index + '_Point_' +
point_1.index + '_Symbol');
for (var i = 0, len = elements.length; i < len; i++) {
if (!isNullOrUndefined(markerElement)) {
markerElement.setAttribute('visibility', 'visible');
}
remove(elements[0]);
}
}
}
if (fadeOut) {
this.previousPoints = [];
}
};
return MarkerExplode;
}(ChartData));
export { MarkerExplode };