@amcharts/amcharts5
Version:
amCharts 5
382 lines • 15.4 kB
JavaScript
import { __awaiter } from "tslib";
import { FlowDefaultTheme } from "./FlowDefaultTheme";
import { Series } from "../../core/render/Series";
import { Container } from "../../core/render/Container";
import { LinearGradient } from "../../core/render/gradients/LinearGradient";
import * as $array from "../../core/util/Array";
import * as $type from "../../core/util/Type";
/**
* A base class for all flow type series: [[Sankey]] and [[Chord]].
*
* @see {@link https://www.amcharts.com/docs/v5/charts/flow-charts/} for more info
*/
export class Flow extends Series {
constructor() {
super(...arguments);
/**
* Container series will place their links in.
*
* @default Container.new()
*/
Object.defineProperty(this, "linksContainer", {
enumerable: true,
configurable: true,
writable: true,
value: this.children.push(Container.new(this._root, {}))
});
Object.defineProperty(this, "_nodesData", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
Object.defineProperty(this, "_linksData", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
Object.defineProperty(this, "_index", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "_nodesDataSet", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
Object.defineProperty(this, "_linksByIndex", {
enumerable: true,
configurable: true,
writable: true,
value: {}
});
}
_afterNew() {
this._defaultThemes.push(FlowDefaultTheme.new(this._root));
this.fields.push("disabled", "sourceId", "targetId");
if (this.nodes) {
this.nodes.flow = this;
}
super._afterNew();
this.children.push(this.bulletsContainer);
}
processDataItem(dataItem) {
super.processDataItem(dataItem);
const nodes = this.nodes;
if (nodes) {
let unknown = false;
let sourceId = dataItem.get("sourceId");
let sourceDataItem = nodes.getDataItemById(sourceId);
if (!sourceDataItem) {
if (sourceId == null) {
sourceId = "undefined" + this._index;
this._index++;
unknown = true;
}
nodes.data.push({ id: sourceId, unknown: unknown });
sourceDataItem = nodes.getDataItemById(sourceId);
if (!unknown) {
sourceDataItem.set("name", sourceId);
}
}
unknown = false;
let targetId = dataItem.get("targetId");
let targetDataItem = nodes.getDataItemById(targetId);
if (!targetDataItem) {
if (targetId == null) {
targetId = "undefined" + this._index;
this._index++;
unknown = true;
}
nodes.data.push({ id: targetId, unknown: unknown });
targetDataItem = nodes.getDataItemById(targetId);
if (!unknown) {
targetDataItem.set("name", targetId);
}
}
if (sourceDataItem) {
dataItem.set("source", sourceDataItem);
nodes.addOutgoingLink(sourceDataItem, dataItem);
}
if (targetDataItem) {
dataItem.set("target", targetDataItem);
nodes.addincomingLink(targetDataItem, dataItem);
}
dataItem.set("link", this.makeLink(dataItem));
const sourceIndex = this.nodes.dataItems.indexOf(sourceDataItem);
const targetIndex = this.nodes.dataItems.indexOf(targetDataItem);
this._linksByIndex[sourceIndex + "_" + targetIndex] = dataItem;
if (sourceDataItem.get("unknown")) {
if (targetDataItem) {
sourceDataItem.set("fill", targetDataItem.get("fill"));
}
dataItem.get("link").set("fillStyle", "gradient");
}
if (targetDataItem.get("unknown")) {
if (sourceDataItem) {
targetDataItem.set("fill", sourceDataItem.get("fill"));
}
dataItem.get("link").set("fillStyle", "gradient");
}
this._updateLinkColor(dataItem);
}
}
_onDataClear() {
if (!this.nodes._userDataSet) {
this.nodes.data.setAll([]);
this.nodes._userDataSet = false;
}
}
_prepareChildren() {
super._prepareChildren();
let valueLow = Infinity;
let valueHigh = -Infinity;
let valueSum = 0;
if (this._valuesDirty) {
this._nodesData = [];
const nodes = this.nodes;
if (nodes) {
$array.each(nodes.dataItems, (dataItem) => {
const d3SankeyNode = dataItem.get("d3SankeyNode");
this._nodesData.push(d3SankeyNode);
const incoming = dataItem.get("incomingLinks");
let sumIncoming = 0;
let sumIncomingWorking = 0;
if (incoming) {
$array.each(incoming, (link) => {
const value = link.get("value");
const workingValue = link.get("valueWorking");
sumIncoming += value;
sumIncomingWorking += workingValue;
});
}
dataItem.set("sumIncoming", sumIncoming);
dataItem.set("sumIncomingWorking", sumIncomingWorking);
const outgoing = dataItem.get("outgoingLinks");
let sumOutgoing = 0;
let sumOutgoingWorking = 0;
if (outgoing) {
$array.each(outgoing, (link) => {
const value = link.get("value");
const workingValue = link.get("valueWorking");
sumOutgoing += value;
sumOutgoingWorking += workingValue;
});
}
dataItem.set("sumOutgoing", sumOutgoing);
dataItem.set("sumOutgoingWorking", sumOutgoingWorking);
dataItem.set("sum", sumIncoming + sumOutgoing);
dataItem.set("sumWorking", sumIncomingWorking + sumOutgoingWorking);
nodes.updateLegendValue(dataItem);
});
}
this._linksData = [];
$array.each(this.dataItems, (dataItem) => {
let value = dataItem.get("value");
if ($type.isNumber(value)) {
if (value < valueLow) {
valueLow = value;
}
if (value > valueHigh) {
valueHigh = value;
}
valueSum += value;
}
});
$array.each(this.dataItems, (dataItem) => {
let value = dataItem.get("value");
if ($type.isNumber(value)) {
let valueWorking = dataItem.get("valueWorking");
let minSize = this.get("minSize", 0);
if (minSize > 0) {
if (valueWorking < minSize * valueSum) {
valueWorking = minSize * valueSum;
}
}
let d3SankeyLink = { source: dataItem.get("source").get("d3SankeyNode"), target: dataItem.get("target").get("d3SankeyNode"), value: valueWorking };
dataItem.setRaw("d3SankeyLink", d3SankeyLink);
this._linksData.push(d3SankeyLink);
this.updateLegendValue(dataItem);
}
});
this.setPrivateRaw("valueHigh", valueHigh);
this.setPrivateRaw("valueLow", valueLow);
this.setPrivateRaw("valueSum", valueSum);
}
}
_updateLinkColor(dataItem) {
const link = dataItem.get("link");
const fillStyle = link.get("fillStyle");
const strokeStyle = link.get("strokeStyle");
const source = dataItem.get("source");
const target = dataItem.get("target");
const sourceFill = source.get("fill");
const targetFill = target.get("fill");
link.remove("fillGradient");
link.remove("strokeGradient");
switch (fillStyle) {
case "solid":
link._applyTemplates();
break;
case "source":
link.set("fill", sourceFill);
break;
case "target":
link.set("fill", targetFill);
break;
case "gradient":
let gradient = link._fillGradient;
if (!gradient) {
gradient = LinearGradient.new(this._root, {});
}
const sourceStop = { color: sourceFill };
if (source.get("unknown")) {
sourceStop.opacity = 0;
}
const targetStop = { color: targetFill };
if (target.get("unknown")) {
targetStop.opacity = 0;
}
gradient.set("stops", [sourceStop, targetStop]);
link._fillGradient = gradient;
link.set("fillGradient", gradient);
break;
case "none":
link.set("fill", undefined); // do not use remove!
break;
}
switch (strokeStyle) {
case "solid":
link._applyTemplates();
break;
case "source":
link.set("stroke", sourceFill);
break;
case "target":
link.set("stroke", targetFill);
break;
case "gradient":
let gradient = link._strokeGradient;
if (!gradient) {
gradient = LinearGradient.new(this._root, {});
const sourceStop = { color: sourceFill };
if (source.get("unknown")) {
sourceStop.opacity = 0;
}
const targetStop = { color: targetFill };
if (target.get("unknown")) {
targetStop.opacity = 0;
}
gradient.set("stops", [sourceStop, targetStop]);
link._strokeGradient = gradient;
}
link.set("strokeGradient", gradient);
break;
case "none":
link.remove("stroke");
break;
}
}
/**
* @ignore
*/
disposeDataItem(dataItem) {
super.disposeDataItem(dataItem);
let link = dataItem.get("link");
if (link) {
this.links.removeValue(link);
link.dispose();
}
}
/**
* Shows diagram's data item.
*
* @param dataItem Data item
* @param duration Animation duration in milliseconds
* @return Promise
*/
hideDataItem(dataItem, duration) {
const _super = Object.create(null, {
hideDataItem: { get: () => super.hideDataItem }
});
return __awaiter(this, void 0, void 0, function* () {
const promises = [_super.hideDataItem.call(this, dataItem, duration)];
const hiddenState = this.states.create("hidden", {});
const stateAnimationDuration = "stateAnimationDuration";
const stateAnimationEasing = "stateAnimationEasing";
if (!$type.isNumber(duration)) {
duration = hiddenState.get(stateAnimationDuration, this.get(stateAnimationDuration, 0));
}
const easing = hiddenState.get(stateAnimationEasing, this.get(stateAnimationEasing));
promises.push(dataItem.animate({
key: "valueWorking",
to: Math.max(this.get("minHiddenValue", 0), this.get("hiddenSize", 0) * dataItem.get("value")),
duration: duration,
easing: easing
}).waitForStop());
const linkGraphics = dataItem.get("link");
linkGraphics.hide();
yield Promise.all(promises);
});
}
/**
* Shows diagram's data item.
*
* @param dataItem Data item
* @param duration Animation duration in milliseconds
* @return Promise
*/
showDataItem(dataItem, duration) {
const _super = Object.create(null, {
showDataItem: { get: () => super.showDataItem }
});
return __awaiter(this, void 0, void 0, function* () {
const promises = [_super.showDataItem.call(this, dataItem, duration)];
if (!$type.isNumber(duration)) {
duration = this.get("stateAnimationDuration", 0);
}
const easing = this.get("stateAnimationEasing");
promises.push(dataItem.animate({ key: "valueWorking", to: dataItem.get("value"), duration: duration, easing: easing }).waitForStop());
const linkGraphics = dataItem.get("link");
linkGraphics.show();
yield Promise.all(promises);
});
}
_positionBullet(bullet) {
const sprite = bullet.get("sprite");
if (sprite) {
const dataItem = sprite.dataItem;
if (dataItem) {
const link = dataItem.get("link");
const sprite = bullet.get("sprite");
if (sprite) {
const point = link.getPoint(this._getBulletLocation(bullet));
sprite.setAll({ x: point.x, y: point.y });
if (bullet.get("autoRotate")) {
sprite.set("rotation", point.angle + bullet.get("autoRotateAngle", 0));
}
}
}
}
}
_getBulletLocation(bullet) {
return bullet.get("locationY", 0);
}
}
Object.defineProperty(Flow, "className", {
enumerable: true,
configurable: true,
writable: true,
value: "Flow"
});
Object.defineProperty(Flow, "classNames", {
enumerable: true,
configurable: true,
writable: true,
value: Series.classNames.concat([Flow.className])
});
//# sourceMappingURL=Flow.js.map