javascript - examples - D3.js Agregar enlaces entre elementos en un árbol radial(elementos de agrupamiento de bordes jerárquicos)
jquery d3 (2)
Hace un par de meses, traté de combinar Hierarchical Edge Bundling y Radial Reingold-Tilford Tree usando d3.js
Empecé desde el HEB e intenté convertirlo en un árbol. Las cosas no han funcionado como yo quería, y me di cuenta de que podría ser mejor comenzar desde un árbol radial plegable (no Reingold Tilford), con un ángulo diferente.
Aquí hay un JSFiddle del árbol radial
El modelo de datos también ha cambiado, ya que los elementos ahora tienen un nombre, hijos e importaciones (enlaces).
var flare =
{
"name": "root",
"children": [
{
"name": "test1.parent1","children": [
{"name": "test1.child11","children": [
{"name": "test1.child111"},
{"name": "test1.child112"}
]}
],"imports": ["test2.parent2","test3.parent3","test4.parent4"]
},
{
"name": "test2.parent2","children": [
{"name": "test2.child21"},
{"name": "test2.child22"},
{"name": "test2.child28","children":[
{"name": "test2.child281"},
{"name": "test2.child282"}
]}
],"imports": ["test3.parent3"]
},
{"name": "test3.parent3","imports": ["test4.parent4"]},
{
"name": "test4.parent4","children": [
{"name": "test4.child41"},
{"name": "test4.child42"}
]
}
]
};
Para comenzar lentamente, me gustaría combinar la agrupación de bordes jerárquicos no interactivos de Mike Bostock con el JSFiddle actual, pero teniendo en cuenta que las interacciones serán parte de esto más adelante.
Además, solo el primer nivel debe tener enlaces (enlace entre padres y padres) como se muestra a continuación (el resultado que deseo):
Mi mayor problema actual es que el HEB no tiene "raíz", pero el árbol comienza con un solo elemento. Entonces, todo lo que he intentado hasta ahora me ha llevado a un gran lío en el centro del árbol.
Tenga en cuenta que hay un círculo en el centro del árbol para cubrir la raíz de los enlaces de nivel 1, por lo que el árbol comienza en el nivel 1 (padres).
var circle = svg.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", diameter - 725.3)
.style("fill", "#F3F5F6")
.style("stroke-width", 0.2)
.style("stroke", "black");
Idealmente, los enlaces entre padres deben actualizarse cuando un nivel está (sin) colapsado, como lo hace para los nodos y los enlaces entre niveles, pero eso puede ocurrir más tarde y puede no ser tan difícil después de obtener inicialmente los enlaces de primer nivel para mostrar . Además, la plantilla de datos puede cambiar si es necesario, pero los 3 elementos de información son importantes (nombre, hijos e importaciones).
Otra forma de hacerlo sería poder cambiar los datos para no incluir la parte raíz, y que se comporta exactamente como lo hace ahora. Las respuestas parciales también son bienvenidas.
He logrado agregar enlaces entre los elementos en este JSFiddle utilizando partes del código encontrado en la agrupación de bordes jerárquicos original por Mike Bostock y los he añadido a la versión radial del árbol plegable. Sin embargo, ¡no se actualizan al colapsar o expandir los niños!
var bundle = d3.layout.bundle();
var line = d3.svg.line.radial()
.interpolate("bundle")
.tension(.85)
.radius(function(d) { return d.y; })
.angle(function(d) { return d.x / 180 * Math.PI; });
luego en update(source)
:
var middleLinks = packageImports(root);
svg.selectAll("path.middleLink")
.data(bundle(middleLinks))
.enter().append("path")
.attr("class", "middleLink")
.attr("d", line);
La función "packageImport" se puede encontrar en la parte inferior.
function packageImports(json) {
var map = {},
imports = [];
console.log(json.children);
// Compute a map from name to node.
json.children.forEach(function(d) {
console.log(d.name)
map[d.name] = d;
});
// For each import, construct a link from the source to target node.
json.children.forEach(function(d) {
if (d.imports) d.imports.forEach(function(i) {
imports.push({source: map[d.name], target: map[i]});
});
});
console.log(imports);
return imports;
}
Mi mayor problema actual es que el HEB no tiene "raíz", pero el árbol comienza con un solo elemento. Entonces, todo lo que he intentado hasta ahora me ha llevado a un gran lío en el centro del árbol.
Dado que tienes una raíz, ¿por qué no establecer eso como el "nodo" central y convertirlo en un árbol radial, como este ? Aquí hay otro ejemplo, pero con múltiples raíces.
Dicho esto, no solicitó un árbol radial, incluso si parece que eso responderá a su pregunta. Si está decidido a mantener las cosas arregladas en círculos de radio variable, tal vez el problema a resolver sea el cruzamiento de las líneas que se ven tan "desordenadas". Si ese es el caso, entonces un algoritmo de clasificación diferente podría hacer el truco. Aquí hay un artículo que se expande al usar diferentes algoritmos de clasificación en un escenario similar con D3.js. Los algoritmos de diseño D3 también son de código abierto en línea .
El mejor recurso que pude encontrar para ti fue esta Stack Mathematics Answer . Algunos puntos se destacan especialmente para mí en esto:
- Puede tener un desorden total de conexiones / ramas, pero si es interactivo y las ramas hacia y desde un nodo específico se iluminan cuando se desplaza sobre ese nodo, puede seguir siendo un gráfico legible / utilizable.
- Puede probar diferentes algoritmos de clasificación hasta que encuentre uno que funcione bien con sus datos.
- Puede tener uno o más nodos dentro del círculo, y en este caso poner el nodo raíz en el medio podría tener mucho sentido.
No es una respuesta práctica, ya que está en Mathematica, pero creo que su explicación de las teorías y técnicas subyacentes es útil.
Un enfoque quizás más artístico, si no quiere poner la raíz del árbol en el centro, sería hacer que todas las ramas desde los padres hasta el padre raíz sean semitransparentes, y posiblemente de un color diferente.
¡Espero que esto ayude!