ag-charts-community
Version:
Advanced Charting / Charts supporting Javascript / Typescript / React / Angular / Vue
510 lines • 21.6 kB
JavaScript
"use strict";
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;
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
Object.defineProperty(exports, "__esModule", { value: true });
var path_1 = require("../../../scene/shape/path");
var continuousScale_1 = require("../../../scale/continuousScale");
var selection_1 = require("../../../scene/selection");
var group_1 = require("../../../scene/group");
var series_1 = require("../series");
var array_1 = require("../../../util/array");
var node_1 = require("../../../scene/node");
var text_1 = require("../../../scene/shape/text");
var cartesianSeries_1 = require("./cartesianSeries");
var chartAxis_1 = require("../../chartAxis");
var util_1 = require("../../marker/util");
var observable_1 = require("../../../util/observable");
var chart_1 = require("../../chart");
var string_1 = require("../../../util/string");
var label_1 = require("../../label");
var sanitize_1 = require("../../../util/sanitize");
var value_1 = require("../../../util/value");
var LineSeriesLabel = /** @class */ (function (_super) {
__extends(LineSeriesLabel, _super);
function LineSeriesLabel() {
return _super !== null && _super.apply(this, arguments) || this;
}
__decorate([
observable_1.reactive('change')
], LineSeriesLabel.prototype, "formatter", void 0);
return LineSeriesLabel;
}(label_1.Label));
var LineSeriesTooltip = /** @class */ (function (_super) {
__extends(LineSeriesTooltip, _super);
function LineSeriesTooltip() {
return _super !== null && _super.apply(this, arguments) || this;
}
__decorate([
observable_1.reactive('change')
], LineSeriesTooltip.prototype, "renderer", void 0);
__decorate([
observable_1.reactive('change')
], LineSeriesTooltip.prototype, "format", void 0);
return LineSeriesTooltip;
}(series_1.SeriesTooltip));
exports.LineSeriesTooltip = LineSeriesTooltip;
var LineSeries = /** @class */ (function (_super) {
__extends(LineSeries, _super);
function LineSeries() {
var _this = _super.call(this) || this;
_this.xDomain = [];
_this.yDomain = [];
_this.xData = [];
_this.yData = [];
_this.lineNode = new path_1.Path();
// We use groups for this selection even though each group only contains a marker ATM
// because in the future we might want to add label support as well.
_this.nodeSelection = selection_1.Selection.select(_this.pickGroup).selectAll();
_this.nodeData = [];
_this.marker = new cartesianSeries_1.CartesianSeriesMarker();
_this.label = new LineSeriesLabel();
_this.stroke = '#874349';
_this.lineDash = [0];
_this.lineDashOffset = 0;
_this.strokeWidth = 2;
_this.strokeOpacity = 1;
_this.tooltip = new LineSeriesTooltip();
_this._xKey = '';
_this.xName = '';
_this._yKey = '';
_this.yName = '';
var lineNode = _this.lineNode;
lineNode.fill = undefined;
lineNode.lineJoin = 'round';
lineNode.pointerEvents = node_1.PointerEvents.None;
// Make line render before markers in the pick group.
_this.group.insertBefore(lineNode, _this.pickGroup);
_this.addEventListener('update', _this.scheduleUpdate);
var _a = _this, marker = _a.marker, label = _a.label;
marker.fill = '#c16068';
marker.stroke = '#874349';
marker.addPropertyListener('shape', _this.onMarkerShapeChange, _this);
marker.addEventListener('change', _this.scheduleUpdate, _this);
label.enabled = false;
label.addEventListener('change', _this.scheduleUpdate, _this);
return _this;
}
LineSeries.prototype.onMarkerShapeChange = function () {
this.nodeSelection = this.nodeSelection.setData([]);
this.nodeSelection.exit.remove();
this.fireEvent({ type: 'legendChange' });
};
LineSeries.prototype.setColors = function (fills, strokes) {
this.stroke = fills[0];
this.marker.stroke = strokes[0];
this.marker.fill = fills[0];
};
Object.defineProperty(LineSeries.prototype, "xKey", {
get: function () {
return this._xKey;
},
set: function (value) {
if (this._xKey !== value) {
this._xKey = value;
this.xData = [];
this.scheduleData();
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(LineSeries.prototype, "yKey", {
get: function () {
return this._yKey;
},
set: function (value) {
if (this._yKey !== value) {
this._yKey = value;
this.yData = [];
this.scheduleData();
}
},
enumerable: true,
configurable: true
});
LineSeries.prototype.processData = function () {
var _a = this, xAxis = _a.xAxis, yAxis = _a.yAxis, xKey = _a.xKey, yKey = _a.yKey, xData = _a.xData, yData = _a.yData;
var data = xKey && yKey && this.data ? this.data : [];
if (!xAxis || !yAxis) {
return false;
}
var isContinuousX = xAxis.scale instanceof continuousScale_1.ContinuousScale;
var isContinuousY = yAxis.scale instanceof continuousScale_1.ContinuousScale;
xData.length = 0;
yData.length = 0;
for (var i = 0, n = data.length; i < n; i++) {
var datum = data[i];
var x = datum[xKey];
var y = datum[yKey];
if (isContinuousX) {
xData.push(x);
}
else {
// i.e. category axis
xData.push(value_1.isDiscrete(x) ? x : String(x));
}
if (isContinuousY) {
yData.push(y);
}
else {
yData.push(value_1.isDiscrete(y) ? y : String(y));
}
}
this.xDomain = isContinuousX ? this.fixNumericExtent(array_1.extent(xData, value_1.isContinuous), 'x') : xData;
this.yDomain = isContinuousY ? this.fixNumericExtent(array_1.extent(yData, value_1.isContinuous), 'y') : yData;
return true;
};
LineSeries.prototype.getDomain = function (direction) {
if (direction === chartAxis_1.ChartAxisDirection.X) {
return this.xDomain;
}
return this.yDomain;
};
LineSeries.prototype.onHighlightChange = function () {
this.updateNodes();
};
LineSeries.prototype.resetHighlight = function () {
this.lineNode.strokeWidth = this.strokeWidth;
};
LineSeries.prototype.update = function () {
this.updatePending = false;
this.updateSelections();
this.updateNodes();
};
LineSeries.prototype.updateSelections = function () {
if (!this.nodeDataPending) {
return;
}
this.nodeDataPending = false;
this.updateLinePath(); // this will create node data too
this.updateNodeSelection();
};
LineSeries.prototype.updateLinePath = function () {
var _a = this, data = _a.data, xAxis = _a.xAxis, yAxis = _a.yAxis;
if (!data || !xAxis || !yAxis) {
return;
}
var _b = this, xData = _b.xData, yData = _b.yData, lineNode = _b.lineNode, label = _b.label;
var xScale = xAxis.scale;
var yScale = yAxis.scale;
var isContinuousX = xScale instanceof continuousScale_1.ContinuousScale;
var isContinuousY = yScale instanceof continuousScale_1.ContinuousScale;
var xOffset = (xScale.bandwidth || 0) / 2;
var yOffset = (yScale.bandwidth || 0) / 2;
var linePath = lineNode.path;
var nodeData = [];
linePath.clear();
var moveTo = true;
var prevXInRange = undefined;
var nextXYDatums = undefined;
for (var i = 0; i < xData.length; i++) {
var xyDatums = nextXYDatums || this.checkDomainXY(xData[i], yData[i], isContinuousX, isContinuousY);
if (!xyDatums) {
prevXInRange = undefined;
moveTo = true;
}
else {
var _c = __read(xyDatums, 2), xDatum = _c[0], yDatum = _c[1];
var x = xScale.convert(xDatum) + xOffset;
if (isNaN(x)) {
prevXInRange = undefined;
moveTo = true;
continue;
}
var tolerance = (xScale.bandwidth || (this.marker.size * 0.5 + (this.marker.strokeWidth || 0))) + 1;
nextXYDatums = this.checkDomainXY(xData[i + 1], yData[i + 1], isContinuousX, isContinuousY);
var xInRange = xAxis.inRangeEx(x, 0, tolerance);
var nextXInRange = nextXYDatums && xAxis.inRangeEx(xScale.convert(nextXYDatums[0]) + xOffset, 0, tolerance);
if (xInRange === -1 && nextXInRange === -1) {
moveTo = true;
continue;
}
if (xInRange === 1 && prevXInRange === 1) {
moveTo = true;
continue;
}
prevXInRange = xInRange;
var y = yScale.convert(yDatum) + yOffset;
if (moveTo) {
linePath.moveTo(x, y);
moveTo = false;
}
else {
linePath.lineTo(x, y);
}
var labelText = void 0;
if (label.formatter) {
labelText = label.formatter({ value: yDatum });
}
else {
labelText = typeof yDatum === 'number' && isFinite(yDatum) ? yDatum.toFixed(2) : yDatum ? String(yDatum) : '';
}
nodeData.push({
series: this,
datum: data[i],
point: { x: x, y: y },
label: labelText ? {
text: labelText,
fontStyle: label.fontStyle,
fontWeight: label.fontWeight,
fontSize: label.fontSize,
fontFamily: label.fontFamily,
textAlign: 'center',
textBaseline: 'bottom',
fill: label.color
} : undefined
});
}
}
// Used by marker nodes and for hit-testing even when not using markers
// when `chart.tooltip.tracking` is true.
this.nodeData = nodeData;
};
LineSeries.prototype.updateNodeSelection = function () {
var marker = this.marker;
var nodeData = marker.shape ? this.nodeData : [];
var MarkerShape = util_1.getMarker(marker.shape);
var updateSelection = this.nodeSelection.setData(nodeData);
updateSelection.exit.remove();
var enterSelection = updateSelection.enter.append(group_1.Group);
enterSelection.append(MarkerShape);
enterSelection.append(text_1.Text);
this.nodeSelection = updateSelection.merge(enterSelection);
};
LineSeries.prototype.updateNodes = function () {
this.group.visible = this.visible;
this.updateLineNode();
this.updateMarkerNodes();
this.updateTextNodes();
};
LineSeries.prototype.updateLineNode = function () {
var lineNode = this.lineNode;
lineNode.stroke = this.stroke;
lineNode.strokeWidth = this.getStrokeWidth(this.strokeWidth);
lineNode.strokeOpacity = this.strokeOpacity;
lineNode.lineDash = this.lineDash;
lineNode.lineDashOffset = this.lineDashOffset;
lineNode.opacity = this.getOpacity();
};
LineSeries.prototype.updateMarkerNodes = function () {
var _this = this;
if (!this.chart) {
return;
}
var _a = this, marker = _a.marker, xKey = _a.xKey, yKey = _a.yKey, lineStroke = _a.stroke, highlightedDatum = _a.chart.highlightedDatum, _b = _a.highlightStyle, deprecatedFill = _b.fill, deprecatedStroke = _b.stroke, deprecatedStrokeWidth = _b.strokeWidth, _c = _b.item, _d = _c.fill, highlightedFill = _d === void 0 ? deprecatedFill : _d, _e = _c.stroke, highlightedStroke = _e === void 0 ? deprecatedStroke : _e, _f = _c.strokeWidth, highlightedDatumStrokeWidth = _f === void 0 ? deprecatedStrokeWidth : _f;
var size = marker.size, formatter = marker.formatter;
var markerStrokeWidth = marker.strokeWidth !== undefined ? marker.strokeWidth : this.strokeWidth;
var MarkerShape = util_1.getMarker(marker.shape);
this.nodeSelection.selectByClass(MarkerShape)
.each(function (node, datum) {
var isDatumHighlighted = datum === highlightedDatum;
var fill = isDatumHighlighted && highlightedFill !== undefined ? highlightedFill : marker.fill;
var stroke = isDatumHighlighted && highlightedStroke !== undefined ? highlightedStroke : marker.stroke || lineStroke;
var strokeWidth = isDatumHighlighted && highlightedDatumStrokeWidth !== undefined
? highlightedDatumStrokeWidth
: markerStrokeWidth;
var format = undefined;
if (formatter) {
format = formatter({
datum: datum.datum,
xKey: xKey,
yKey: yKey,
fill: fill,
stroke: stroke,
strokeWidth: strokeWidth,
size: size,
highlighted: isDatumHighlighted
});
}
node.fill = format && format.fill || fill;
node.stroke = format && format.stroke || stroke;
node.strokeWidth = format && format.strokeWidth !== undefined
? format.strokeWidth
: strokeWidth;
node.size = format && format.size !== undefined
? format.size
: size;
node.translationX = datum.point.x;
node.translationY = datum.point.y;
node.opacity = _this.getOpacity(datum);
node.visible = marker.enabled && node.size > 0;
});
};
LineSeries.prototype.updateTextNodes = function () {
var _this = this;
this.nodeSelection.selectByClass(text_1.Text)
.each(function (text, datum) {
var point = datum.point, label = datum.label;
var _a = _this.label, labelEnabled = _a.enabled, fontStyle = _a.fontStyle, fontWeight = _a.fontWeight, fontSize = _a.fontSize, fontFamily = _a.fontFamily, color = _a.color;
if (label && labelEnabled) {
text.fontStyle = fontStyle;
text.fontWeight = fontWeight;
text.fontSize = fontSize;
text.fontFamily = fontFamily;
text.textAlign = label.textAlign;
text.textBaseline = label.textBaseline;
text.text = label.text;
text.x = point.x;
text.y = point.y - 10;
text.fill = color;
text.visible = true;
}
else {
text.visible = false;
}
});
};
LineSeries.prototype.getNodeData = function () {
return this.nodeData;
};
LineSeries.prototype.fireNodeClickEvent = function (event, datum) {
this.fireEvent({
type: 'nodeClick',
event: event,
series: this,
datum: datum.datum,
xKey: this.xKey,
yKey: this.yKey
});
};
LineSeries.prototype.getTooltipHtml = function (nodeDatum) {
var _a = this, xKey = _a.xKey, yKey = _a.yKey, xAxis = _a.xAxis, yAxis = _a.yAxis;
if (!xKey || !yKey || !xAxis || !yAxis) {
return '';
}
var _b = this, xName = _b.xName, yName = _b.yName, tooltip = _b.tooltip, marker = _b.marker;
var tooltipRenderer = tooltip.renderer, tooltipFormat = tooltip.format;
var datum = nodeDatum.datum;
var xValue = datum[xKey];
var yValue = datum[yKey];
var xString = xAxis.formatDatum(xValue);
var yString = yAxis.formatDatum(yValue);
var title = sanitize_1.sanitizeHtml(this.title || yName);
var content = sanitize_1.sanitizeHtml(xString + ': ' + yString);
var markerFormatter = marker.formatter, fill = marker.fill, stroke = marker.stroke, markerStrokeWidth = marker.strokeWidth, size = marker.size;
var strokeWidth = markerStrokeWidth !== undefined ? markerStrokeWidth : this.strokeWidth;
var format = undefined;
if (markerFormatter) {
format = markerFormatter({
datum: datum,
xKey: xKey,
yKey: yKey,
fill: fill,
stroke: stroke,
strokeWidth: strokeWidth,
size: size,
highlighted: false
});
}
var color = format && format.fill || fill;
var defaults = {
title: title,
backgroundColor: color,
content: content
};
if (tooltipFormat || tooltipRenderer) {
var params = {
datum: datum,
xKey: xKey,
xValue: xValue,
xName: xName,
yKey: yKey,
yValue: yValue,
yName: yName,
title: title,
color: color
};
if (tooltipFormat) {
return chart_1.toTooltipHtml({
content: string_1.interpolate(tooltipFormat, params)
}, defaults);
}
if (tooltipRenderer) {
return chart_1.toTooltipHtml(tooltipRenderer(params), defaults);
}
}
return chart_1.toTooltipHtml(defaults);
};
LineSeries.prototype.listSeriesItems = function (legendData) {
var _a = this, id = _a.id, data = _a.data, xKey = _a.xKey, yKey = _a.yKey, yName = _a.yName, visible = _a.visible, title = _a.title, marker = _a.marker, stroke = _a.stroke, strokeOpacity = _a.strokeOpacity;
if (data && data.length && xKey && yKey) {
legendData.push({
id: id,
itemId: undefined,
enabled: visible,
label: {
text: title || yName || yKey
},
marker: {
shape: marker.shape,
fill: marker.fill || 'rgba(0, 0, 0, 0)',
stroke: marker.stroke || stroke || 'rgba(0, 0, 0, 0)',
fillOpacity: 1,
strokeOpacity: strokeOpacity
}
});
}
};
LineSeries.className = 'LineSeries';
LineSeries.type = 'line';
__decorate([
observable_1.reactive('layoutChange')
], LineSeries.prototype, "title", void 0);
__decorate([
observable_1.reactive('update')
], LineSeries.prototype, "stroke", void 0);
__decorate([
observable_1.reactive('update')
], LineSeries.prototype, "lineDash", void 0);
__decorate([
observable_1.reactive('update')
], LineSeries.prototype, "lineDashOffset", void 0);
__decorate([
observable_1.reactive('update')
], LineSeries.prototype, "strokeWidth", void 0);
__decorate([
observable_1.reactive('update')
], LineSeries.prototype, "strokeOpacity", void 0);
__decorate([
observable_1.reactive('update')
], LineSeries.prototype, "xName", void 0);
__decorate([
observable_1.reactive('update')
], LineSeries.prototype, "yName", void 0);
return LineSeries;
}(cartesianSeries_1.CartesianSeries));
exports.LineSeries = LineSeries;
//# sourceMappingURL=lineSeries.js.map