@amcharts/amcharts5
Version:
amCharts 5
316 lines • 11.8 kB
JavaScript
import { Hierarchy } from "./Hierarchy";
import { Container } from "../../core/render/Container";
import { LinkedHierarchyNode } from "./LinkedHierarchyNode";
import { HierarchyLink } from "./HierarchyLink";
import { Template } from "../../core/util/Template";
import { Circle } from "../../core/render/Circle";
import { ListTemplate } from "../../core/util/List";
import { List } from "../../core/util/List";
import * as $array from "../../core/util/Array";
import * as $utils from "../../core/util/Utils";
;
/**
* A base class for linked hierarchy series.
*/
export class LinkedHierarchy extends Hierarchy {
constructor() {
super(...arguments);
this.linkBullets = new List();
/**
* A list of nodes in a [[LinkedHierarchy]] chart.
*
* @default new ListTemplate<LinkedHierarchyNode>
*/
this.nodes = this.addDisposer(new ListTemplate(Template.new({}), () => LinkedHierarchyNode._new(this._root, {
themeTags: $utils.mergeTags(this.nodes.template.get("themeTags", []), [this._tag, "linkedhierarchy", "hierarchy", "node"]),
x: this.width() / 2,
y: this.height() / 2
}, [this.nodes.template])));
/**
* A list of node circle elements in a [[LinkedHierarchy]] chart.
*
* @default new ListTemplate<Circle>
*/
this.circles = this.addDisposer(new ListTemplate(Template.new({}), () => Circle._new(this._root, {
themeTags: $utils.mergeTags(this.circles.template.get("themeTags", []), [this._tag, "shape"])
}, [this.circles.template])));
/**
* A list of node outer circle elements in a [[LinkedHierarchy]] chart.
*
* @default new ListTemplate<Circle>
*/
this.outerCircles = this.addDisposer(new ListTemplate(Template.new({}), () => Circle._new(this._root, {
themeTags: $utils.mergeTags(this.outerCircles.template.get("themeTags", []), [this._tag, "outer", "shape"])
}, [this.outerCircles.template])));
/**
* A list of link elements in a [[LinkedHierarchy]] chart.
*
* @default new ListTemplate<HierarchyLink>
*/
this.links = this.addDisposer(new ListTemplate(Template.new({}), () => HierarchyLink._new(this._root, {
themeTags: $utils.mergeTags(this.links.template.get("themeTags", []), [this._tag, "linkedhierarchy", "hierarchy", "link"])
}, [this.links.template])));
/**
* A [[Container]] that link elements are placed in.
*
* @default Container.new()
*/
this.linksContainer = this.children.moveValue(Container.new(this._root, {}), 0);
}
_afterNew() {
this.fields.push("linkWith", "x", "y");
this._disposers.push(this.linkBullets.events.onAll(() => {
this.links.each((link) => {
link._handleBullets(this.linkBullets);
});
}));
super._afterNew();
}
/**
* @ignore
*/
makeNode(dataItem) {
const node = super.makeNode(dataItem);
const circle = node.children.moveValue(this.circles.make(), 0);
this.circles.push(circle);
node.setPrivate("tooltipTarget", circle);
dataItem.setRaw("circle", circle);
const outerCircle = node.children.moveValue(this.outerCircles.make(), 0);
this.outerCircles.push(outerCircle);
dataItem.setRaw("outerCircle", outerCircle);
const label = dataItem.get("label");
circle.on("radius", () => {
const d = circle.get("radius", this.width()) * 2;
label.setAll({ maxWidth: d, maxHeight: d });
outerCircle.set("radius", d / 2);
this._handleRadiusChange();
});
const d = circle.get("radius", this.width()) * 2;
label.setAll({ maxWidth: d, maxHeight: d });
circle._setDataItem(dataItem);
outerCircle._setDataItem(dataItem);
return node;
}
_handleRadiusChange() {
}
processDataItem(dataItem) {
dataItem.setRaw("childLinks", []);
dataItem.setRaw("links", []);
super.processDataItem(dataItem);
// Run updateLinkWith once after the entire tree is processed, not per-node
if (!dataItem.get("parent")) {
this.updateLinkWith(this.dataItems);
}
}
addChildData(dataItem, data) {
super.addChildData(dataItem, data);
this.updateLinkWith(this.dataItems);
}
_processDataItem(dataItem) {
super._processDataItem(dataItem);
const parentDataItem = dataItem.get("parent");
if (parentDataItem && parentDataItem.get("depth") >= this.get("topDepth", 0)) {
const link = this.linkDataItems(parentDataItem, dataItem);
dataItem.setRaw("parentLink", link);
}
const node = dataItem.get("node");
node._updateLinks(0);
}
/**
* @ignore
*/
updateLinkWith(dataItems) {
$array.each(dataItems, (dataItem) => {
const linkWith = dataItem.get("linkWith");
if (linkWith) {
$array.each(linkWith, (id) => {
const linkWithDataItem = this._getDataItemById(this.dataItems, id);
if (linkWithDataItem) {
this.linkDataItems(dataItem, linkWithDataItem);
}
});
}
const children = dataItem.get("children");
if (children) {
this.updateLinkWith(children);
}
});
}
_getPoint(hierarchyNode) {
return { x: hierarchyNode.x, y: hierarchyNode.y };
}
_animatePositions(dataItem) {
const node = dataItem.get("node");
const hierarchyNode = dataItem.get("d3HierarchyNode");
const point = this._getPoint(hierarchyNode);
const duration = this.get("animationDuration", 0);
const easing = this.get("animationEasing");
node.animate({ key: "x", to: point.x, duration: duration, easing: easing });
node.animate({ key: "y", to: point.y, duration: duration, easing: easing });
}
_updateNode(dataItem) {
super._updateNode(dataItem);
this._animatePositions(dataItem);
const fill = dataItem.get("fill");
const fillPattern = dataItem.get("fillPattern");
const circle = dataItem.get("circle");
const children = dataItem.get("children");
if (circle) {
circle._setDefault("fill", fill);
circle._setDefault("fillPattern", fillPattern);
circle._setDefault("stroke", fill);
}
const outerCircle = dataItem.get("outerCircle");
if (outerCircle) {
outerCircle._setDefault("fill", fill);
outerCircle._setDefault("stroke", fill);
if (!children || children.length == 0) {
outerCircle.setPrivate("visible", false);
}
else {
outerCircle.setPrivate("visible", true);
}
}
}
/**
* Link two data items with a link element.
*
* @param source Source node data item
* @param target Target node data item
* @param strength Link strength
* @return Link element
*/
linkDataItems(source, target, strength) {
let link;
const sourceLinks = source.get("links");
if (sourceLinks) {
$array.each(sourceLinks, (lnk) => {
if (lnk.get("target") == target) {
link = lnk;
}
});
}
const targetLinks = target.get("links");
if (targetLinks) {
$array.each(targetLinks, (lnk) => {
if (lnk.get("target") == source) {
link = lnk;
}
});
}
if (!link) {
link = this.links.make();
link.series = this;
this.links.push(link);
this.linksContainer.children.push(link);
link.set("source", source);
link.set("target", target);
link._setDataItem(source);
link._handleBullets(this.linkBullets);
link.set("stroke", source.get("fill"));
if (strength != null) {
link.set("strength", strength);
}
source.get("childLinks").push(link);
$array.move(source.get("links"), link);
$array.move(target.get("links"), link);
this._processLink(link, source, target);
}
return link;
}
/**
* Unlink two linked data items.
*
* @param source Source node data item
* @param target Target node data item
*/
unlinkDataItems(source, target) {
let link;
const sourceLinks = source.get("links");
if (sourceLinks) {
$array.each(sourceLinks, (lnk) => {
if (lnk && lnk.get("target") == target) {
link = lnk;
$array.remove(sourceLinks, link);
}
});
}
const targetLinks = target.get("links");
if (targetLinks) {
$array.each(targetLinks, (lnk) => {
if (lnk && lnk.get("target") == source) {
link = lnk;
$array.remove(targetLinks, link);
}
});
}
if (link) {
this._disposeLink(link);
}
this._handleUnlink();
}
_handleUnlink() {
}
_disposeLink(link) {
this.links.removeValue(link);
link.dispose();
}
/**
* Returns `true` if two nodes are linked with each other.
*/
areLinked(source, target) {
const sourceLinks = source.get("links");
let linked = false;
if (sourceLinks) {
$array.each(sourceLinks, (lnk) => {
if (lnk.get("target") == target) {
linked = true;
}
});
}
const targetLinks = target.get("links");
if (targetLinks) {
$array.each(targetLinks, (lnk) => {
if (lnk.get("target") == source) {
linked = true;
}
});
}
return linked;
}
_processLink(_link, _source, _target) {
}
/**
* @ignore
*/
disposeDataItem(dataItem) {
super.disposeDataItem(dataItem);
const links = dataItem.get("links");
if (links) {
$array.each(links, (link) => {
this._disposeLink(link);
});
}
}
/**
* Select a data item.
* @param dataItem Data item
*/
selectDataItem(dataItem) {
const parent = dataItem.get("parent");
if (!dataItem.get("disabled")) {
this._setC("selectedDataItem", dataItem);
}
else {
if (parent) {
this.setRaw("selectedDataItem", parent);
const type = "dataitemselected";
this.events.dispatch(type, { type: type, target: this, dataItem: parent });
this.disableDataItem(dataItem);
}
}
}
}
LinkedHierarchy.className = "LinkedHierarchy";
LinkedHierarchy.classNames = Hierarchy.classNames.concat([LinkedHierarchy.className]);
//# sourceMappingURL=LinkedHierarchy.js.map