En aquest tema, aprendrem a crear visualitzacions utilitzant disposicions de força amb D3.js. Les disposicions de força són útils per crear gràfics de xarxa, on els nodes i els enllaços es distribueixen de manera dinàmica segons forces simulades, com la gravetat, la repulsió i l'atracció.

Conceptes Clau

Abans de començar amb els exemples pràctics, és important entendre alguns conceptes clau:

  • Nodes: Representen els elements individuals de la xarxa.
  • Enllaços: Representen les connexions entre els nodes.
  • Força: Simulació física que determina com es distribueixen els nodes i els enllaços.

Configuració Bàsica

HTML

Comencem amb una estructura HTML bàsica:

<!DOCTYPE html>
<html lang="ca">
<head>
    <meta charset="UTF-8">
    <title>Disposició de Força amb D3.js</title>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <style>
        .node {
            fill: #69b3a2;
            stroke: #fff;
            stroke-width: 1.5px;
        }
        .link {
            stroke: #999;
            stroke-opacity: 0.6;
        }
    </style>
</head>
<body>
    <svg width="800" height="600"></svg>
    <script src="force-layout.js"></script>
</body>
</html>

JavaScript

Creem un fitxer force-layout.js per a la nostra lògica D3.js:

// Dimensions del SVG
const width = 800;
const height = 600;

// Dades de nodes i enllaços
const nodes = [
    { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }
];

const links = [
    { source: 1, target: 2 },
    { source: 1, target: 3 },
    { source: 2, target: 4 },
    { source: 3, target: 5 }
];

// Crear SVG
const svg = d3.select("svg")
    .attr("width", width)
    .attr("height", height);

// Crear simulació de força
const simulation = d3.forceSimulation(nodes)
    .force("link", d3.forceLink(links).id(d => d.id))
    .force("charge", d3.forceManyBody().strength(-200))
    .force("center", d3.forceCenter(width / 2, height / 2));

// Crear enllaços
const link = svg.append("g")
    .attr("class", "links")
    .selectAll("line")
    .data(links)
    .enter().append("line")
    .attr("class", "link");

// Crear nodes
const node = svg.append("g")
    .attr("class", "nodes")
    .selectAll("circle")
    .data(nodes)
    .enter().append("circle")
    .attr("class", "node")
    .attr("r", 10)
    .call(d3.drag()
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended));

// Actualitzar posicions en cada tick
simulation.on("tick", () => {
    link
        .attr("x1", d => d.source.x)
        .attr("y1", d => d.source.y)
        .attr("x2", d => d.target.x)
        .attr("y2", d => d.target.y);

    node
        .attr("cx", d => d.x)
        .attr("cy", d => d.y);
});

// Funcions de drag
function dragstarted(event, d) {
    if (!event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
}

function dragged(event, d) {
    d.fx = event.x;
    d.fy = event.y;
}

function dragended(event, d) {
    if (!event.active) simulation.alphaTarget(0);
    d.fx = null;
    d.fy = null;
}

Explicació del Codi

  1. Configuració del SVG: Definim les dimensions del nostre SVG i el seleccionem amb D3.js.
  2. Dades de Nodes i Enllaços: Definim els nodes i els enllaços que formaran la nostra xarxa.
  3. Simulació de Força: Creem una simulació de força amb d3.forceSimulation(), afegint forces de link, charge i center.
  4. Creació d'Enllaços: Afegim els enllaços al SVG com a elements line.
  5. Creació de Nodes: Afegim els nodes al SVG com a elements circle i configurem el comportament de drag.
  6. Actualització de Posicions: Utilitzem la funció tick per actualitzar les posicions dels nodes i enllaços en cada tick de la simulació.
  7. Funcions de Drag: Definim les funcions per gestionar el drag dels nodes.

Exercici Pràctic

Exercici

Modifica el codi per afegir etiquetes de text als nodes que mostrin el seu id.

Solució

Afegim el següent codi al fitxer force-layout.js:

// Crear etiquetes de text
const label = svg.append("g")
    .attr("class", "labels")
    .selectAll("text")
    .data(nodes)
    .enter().append("text")
    .attr("class", "label")
    .text(d => d.id);

// Actualitzar posicions de les etiquetes en cada tick
simulation.on("tick", () => {
    link
        .attr("x1", d => d.source.x)
        .attr("y1", d => d.source.y)
        .attr("x2", d => d.target.x)
        .attr("y2", d => d.target.y);

    node
        .attr("cx", d => d.x)
        .attr("cy", d => d.y);

    label
        .attr("x", d => d.x + 12)
        .attr("y", d => d.y + 3);
});

Resum

En aquesta secció, hem après a crear una disposició de força amb D3.js, utilitzant nodes i enllaços per formar una xarxa dinàmica. Hem explorat com configurar la simulació de força, crear elements SVG per als nodes i enllaços, i afegir interactivitat amb funcions de drag. A més, hem practicat afegint etiquetes de text als nodes.

En el següent tema, explorarem com crear mapes geo utilitzant D3.js.

D3.js: De Principiant a Avançat

Mòdul 1: Introducció a D3.js

Mòdul 2: Treballant amb Seleccions

Mòdul 3: Dades i Escales

Mòdul 4: Creant Visualitzacions Bàsiques

Mòdul 5: Visualitzacions Avançades

Mòdul 6: Interactivitat i Animació

Mòdul 7: Treballant amb Dades Reals

Mòdul 8: Rendiment i Optimització

Mòdul 9: Millors Pràctiques i Tècniques Avançades

Mòdul 10: Projecte Final

© Copyright 2024. Tots els drets reservats