Я попытался воссоздать пример на странице при использовании TypeScript. Дерево создается, однако, когда я нажимаю, чтобы свернуть/расширить его, переход, кажется, воссоздает все дерево вместо только добавления/удаления узлов из «нажимаемого» родителя. /> Я не смог быстро подумать о лучшем способе предоставить код для примера, так что вот все это. Treenodedata - это просто тип, который я создал для упражнения: < /p>
export interface TreeNodeData {
name: string;
fill?: string;
children?: TreeNodeData[];
value?: number;
id?: string | number;
}
< /code>
код здесь: < /p>
const root = d3.hierarchy(data);
const dx = 40;
const dy = (this.width - this.marginRight - this.marginLeft) / (1 + root.height);
// Define the tree layout and the shape for links.
const tree = d3.tree().nodeSize([dx, dy]);
const diagonal: d3.Link = d3.linkHorizontal()
.x(d => d.y!)
.y(d => d.x!);
// Create the SVG container, a layer for the links and a layer for the nodes.
const svg = d3.create("svg")
.attr("width", this.width)
.attr("height", this.height)
.attr("viewBox", [-this.marginLeft, -this.marginTop, this.width, dx])
.attr("style", "max-width: 100%; height: auto; font: 20px sans-serif; user-select: none;");
const gLink = svg.append("g")
.attr("fill", "none")
.attr("stroke", "#555")
.attr("stroke-opacity", 0.4)
.attr("stroke-width", 1.5);
const gNode = svg.append("g")
.attr("cursor", "pointer")
.attr("pointer-events", "all");
const update = (event: KeyboardEvent | MouseEvent | null, source: d3.HierarchyNode) => {
const duration = event?.altKey ? 2500 : 250; // hold the alt key to slow down the transition
const nodes = root.descendants().reverse();
const links = root.links();
// Compute the new tree layout.
tree(root);
let left = root;
let right = root;
root.eachBefore(node => {
if(node.x !== undefined){
if(left.x !== undefined){
if (node.x < left.x) left = node;
}
if(right.x !== undefined){
if (node.x > right.x) right = node;
}
}
});
const height = right.x! - left.x! + this.marginTop + this.marginBottom;
const transition = svg.transition()
.duration(duration)
.attr("height", height)
.attr("viewBox", [-this.marginLeft, left.x! - this.marginTop, this.width, height].join(" "));
if (window.ResizeObserver) {
transition.tween("resize", null);
} else {
const tweenFactory = () => {
// This is the "factory" function.
svg.dispatch("toggle"); // Perform your action here.
// The factory MUST return an "interpolator" function.
return () => {
};
};
transition.tween("resize", tweenFactory);
}
const node = gNode.selectAll("g")
.data(nodes, (d) => {
if (d && d.id !== undefined) {
return d.id;
}
// You might need to handle cases where d.id is missing based on your data structure.
// Returning a fallback value or throwing an error might be appropriate.
return String(Math.random()); // Example fallback: a unique string
});
// Enter any new nodes at the parent's previous position.
const nodeEnter = node.enter().append("g")
.attr("transform", d => `translate(${source.y0},${source.x0})`)
.attr("fill-opacity", 0)
.attr("stroke-opacity", 0)
.on("click", (event, d: d3.HierarchyNode) => {
d.children = d.children ? undefined : d._children;
update(event, d);
});
nodeEnter.append("circle")
.attr("r", 2.5)
.attr("fill", d => d._children ? "#555" : "#999")
.attr("stroke-width", 10);
nodeEnter.append("text")
.attr("dy", "0.31em")
.attr("x", (d : d3.HierarchyNode) => d._children ? -6 : 6)
.attr("text-anchor", d => d._children ? "end" : "start")
.text((d : d3.HierarchyNode) => d.data.name)
.attr("stroke-linejoin", "round")
.attr("stroke-width", 3)
.attr("stroke", "white")
.attr("paint-order", "stroke");
// Transition nodes to their new position.
const nodeUpdate = node.merge(nodeEnter).transition(transition)
.attr("transform", d => `translate(${d.y},${d.x})`)
.attr("fill-opacity", 1)
.attr("stroke-opacity", 1);
// Transition exiting nodes to the parent's new position.
const nodeExit = node.exit().transition(transition).remove()
.attr("transform", d => `translate(${source.y},${source.x})`)
.attr("fill-opacity", 0)
.attr("stroke-opacity", 0);
// Update the links…
const link = gLink.selectAll("path")
.data(links, (d : d3.HierarchyLink) => d.target.id!); // non-null assertion do caralho
// Enter any new links at the parent's previous position.
const linkEnter = link.enter().append("path")
.attr("d", d => {
return diagonal({ source: source, target: source });
});
// Transition links to their new position.
link.merge(linkEnter).transition(transition)
.attr("d", diagonal);
// Transition exiting nodes to the parent's new position.
link.exit().transition(transition).remove()
.attr("d", d => {
return diagonal({ source: source, target: source })});
// Stash the old positions for transition.
root.eachBefore(d => {
d.x0 = d.x;
d.y0 = d.y;
});
}
// Do the first update to the initial configuration of the tree — where a number of nodes
// are open (arbitrarily selected as the root, plus nodes with 7 letters).
root.x0 = dy / 2;
root.y0 = 0;
root.descendants().forEach((d : d3.HierarchyNode, i) => {
d._children = d.children;
if (d.depth && d.data.name.length !== 7) d.children = undefined;
});
update(null, root);
document.querySelector("body")?.appendChild(svg.node()!);
Подробнее здесь: https://stackoverflow.com/questions/796 ... n-updating
D3.JS Иерархия дерево воссоздает все дерево при обновлении ⇐ Javascript
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
В чем может быть причина того, что openmp постоянно воссоздает пул потоков?
Anonymous » » в форуме Linux - 0 Ответы
- 12 Просмотры
-
Последнее сообщение Anonymous
-