Buscamos cualquier SVG y lo eliminamos. Esta línea solo se ocupa en ObservableHQ para que cuando se ejecute esta celda, no solo agregue el SVG sino que elimine el anterior.
*/
d3.select("#graph").selectAll("svg").remove();
// Se agrega un nuevo SVG dentro del div #graph
constSVG=d3
.select("#graph")
.append("svg")
.attr("width",WIDTH)
.attr("height",HEIGHT);
/*
Se agrega un "g" al SVG. Recordar que el elemento g es un contenedor usado para agrupar objetos. Las transformaciones aplicadas al elemento g son realizadas sobre todos los elementos hijos del mismo
*/
constcontainer=SVG.append("g").attr(
"transform",
`translate(${MARGIN.LEFT}, ${MARGIN.TOP})`
);
// Definir el objeto Tooltip con opacidad 0 para que no se vea al inicio
const div = d3
.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
/*
Creamos el ojeto simulation que se encargará de calculas las posiciones de los nodos en base a una simulación física de fuerzas. Se definen 4 atributos:
- center: Indica donde estará el punto central de la fuerza, es decir, la posición central de donde empezar a realizar la simulación.
- collission: es el radio mínimo que los nodos intentarán mantener de distancia entre otros. Esto hace que la distancia entre dos nodos sea igual a la suma de ambos radios. Si d3.forceCollide es 2, implica que tendrán una distancia de 4 pixeles.
- charge: analogo a la carga electroestática, cuanes es negativa va a repeler a los nodos. Esta carga es global, es decir, cada nodo tiene efecto sobre los otros nodos.
- link: atributo para indicarle a la simulación como conectar el identificador que tienen la lista de links (source y target) con los nodos.
// Buscamos cada link y lo trasladamos a la nueva posición x,y según la posición de los nodos a los que está conectado.
container
.selectAll("line")
.attr("x1", (link) => link.source.x)
.attr("y1", (link) => link.source.y)
.attr("x2", (link) => link.target.x)
.attr("y2", (link) => link.target.y);
};
// Cargamos el JSON y luego, con los dataset cargado comenzamos a crear la simulación
d3.json(FILEPATH).then((dataset) => {
/*
Le indicamos a nuestro objeto simulación varias cosas:
- nodes: Lista de nodos a utilizar.
- on: 'tick' le indicamos que cada vez que la simulación haga un "tick", llame a la función "ticked". El tick es cada iteración que realiza la simulación para posicionar los nodos.
- links: Lista de links a utilizar .
- distance: distancia IDEAL que se busca tener entre un nodo y otro que están conectados.
*/
simulation
.nodes(dataset.nodes)
.on("tick", ticked)
.force("link")
.links(dataset.links)
.distance(80);
// Para cada link, agregamos una línea que conecta 2 nodos.
container
.selectAll("line")
.data(dataset.links)
.enter()
.append("line")
.attr("x1", (link) => link.source.x)
.attr("y1", (link) => link.source.y)
.attr("x2", (link) => link.target.x)
.attr("y2", (link) => link.target.y);
// Para cada nodo, agregamos un "g"
const nodes = container
.selectAll(".node")
.data(dataset.nodes)
.enter()
.append("g")
.attr("class", "node");
// Creamos una función llamada mouseover que recibe un nodo y se encarga de crear un div con la información de dicho nodo
<tr><td>Links que apuntan a mi: </td><td style="text-align: right">` +
targetLinks +
`</td></tr>
<tr><td>Links que salen de mi: </td><td style="text-align: right">` +
sourceLinks +
`</td></tr>
</table>`;
// Le pedimos al objeto div (que tiene el tooltop) que en un tiempo de 0.2 segundos cambia su opacidad de 0 a 0.9. el método transition se encargara de ver como variar la opacidad en dicho rango para que dure 0.2 segundos.
// Le indicamos al tooltip su contenido HTML y la posición, que consiste en donde está el mouse (eje x) y un poco más arriba del mouse (eje y). d3.event.pageX te da la posición en el EJE X del mouse y d3.event.pageY en el EJE Y
div
.html(content)
.style("left", d3.event.pageX + "px")
.style("top", d3.event.pageY - 28 + "px");
};
// Creamos una función mouseout encargada de pedirle al tooltip que en un lapso de 0.2 segundos cambie su opacidad a 0
d3.selectAll("#borders").on("change", (_, i, all) => {
borders = all[i].checked;
simulation.alpha(1);
simulation.restart();
});
});
return "Código JS para visualizar";
}
Purpose-built for displays of data
Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.