La interactividad es una de las características más poderosas de D3.js, permitiendo a los usuarios interactuar con las visualizaciones de datos de manera dinámica. En esta sección, aprenderemos cómo añadir interactividad a nuestras visualizaciones utilizando D3.js.

Conceptos Clave

  1. Eventos del DOM: D3.js permite manejar eventos del DOM como click, mouseover, mouseout, etc.
  2. Manejadores de Eventos: Funciones que se ejecutan en respuesta a eventos del DOM.
  3. Transiciones: Cambios animados en los atributos de los elementos del DOM.

Ejemplo Práctico: Añadiendo Interactividad a un Gráfico de Barras

Paso 1: Crear un Gráfico de Barras Básico

Primero, crearemos un gráfico de barras básico. Si no estás familiarizado con la creación de gráficos de barras en D3.js, revisa la sección "Creando Gráficos de Barras" del Módulo 4.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Gráfico de Barras Interactivo</title>
    <script src="https://d3js.org/d3.v6.min.js"></script>
    <style>
        .bar {
            fill: steelblue;
        }
        .bar:hover {
            fill: orange;
        }
    </style>
</head>
<body>
    <svg width="600" height="400"></svg>
    <script>
        const data = [30, 86, 168, 281, 303, 365];

        const svg = d3.select("svg");
        const width = +svg.attr("width");
        const height = +svg.attr("height");

        const x = d3.scaleBand()
            .domain(d3.range(data.length))
            .range([0, width])
            .padding(0.1);

        const y = d3.scaleLinear()
            .domain([0, d3.max(data)])
            .nice()
            .range([height, 0]);

        svg.selectAll(".bar")
            .data(data)
            .enter().append("rect")
            .attr("class", "bar")
            .attr("x", (d, i) => x(i))
            .attr("y", d => y(d))
            .attr("width", x.bandwidth())
            .attr("height", d => height - y(d));
    </script>
</body>
</html>

Paso 2: Añadir Interactividad

Ahora, añadiremos interactividad al gráfico de barras. Queremos que las barras cambien de color cuando el usuario pase el ratón sobre ellas y que muestren un tooltip con el valor de la barra.

Añadir Manejadores de Eventos

Utilizaremos los eventos mouseover y mouseout para cambiar el color de las barras y mostrar/ocultar el tooltip.

// Añadir manejadores de eventos
svg.selectAll(".bar")
    .on("mouseover", function(event, d) {
        d3.select(this).attr("fill", "orange");
        tooltip.style("display", null);
    })
    .on("mouseout", function(event, d) {
        d3.select(this).attr("fill", "steelblue");
        tooltip.style("display", "none");
    })
    .on("mousemove", function(event, d) {
        const [x, y] = d3.pointer(event);
        tooltip.attr("transform", `translate(${x},${y})`);
        tooltip.select("text").text(d);
    });

Crear el Tooltip

Añadiremos un grupo g al SVG para el tooltip, que contendrá un rectángulo y un texto.

// Crear el tooltip
const tooltip = svg.append("g")
    .attr("class", "tooltip")
    .style("display", "none");

tooltip.append("rect")
    .attr("width", 30)
    .attr("height", 20)
    .attr("fill", "white")
    .style("opacity", 0.5);

tooltip.append("text")
    .attr("x", 15)
    .attr("dy", "1.2em")
    .style("text-anchor", "middle")
    .attr("font-size", "12px")
    .attr("font-family", "sans-serif");

Código Completo

Aquí está el código completo con la interactividad añadida:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Gráfico de Barras Interactivo</title>
    <script src="https://d3js.org/d3.v6.min.js"></script>
    <style>
        .bar {
            fill: steelblue;
        }
        .bar:hover {
            fill: orange;
        }
    </style>
</head>
<body>
    <svg width="600" height="400"></svg>
    <script>
        const data = [30, 86, 168, 281, 303, 365];

        const svg = d3.select("svg");
        const width = +svg.attr("width");
        const height = +svg.attr("height");

        const x = d3.scaleBand()
            .domain(d3.range(data.length))
            .range([0, width])
            .padding(0.1);

        const y = d3.scaleLinear()
            .domain([0, d3.max(data)])
            .nice()
            .range([height, 0]);

        svg.selectAll(".bar")
            .data(data)
            .enter().append("rect")
            .attr("class", "bar")
            .attr("x", (d, i) => x(i))
            .attr("y", d => y(d))
            .attr("width", x.bandwidth())
            .attr("height", d => height - y(d))
            .on("mouseover", function(event, d) {
                d3.select(this).attr("fill", "orange");
                tooltip.style("display", null);
            })
            .on("mouseout", function(event, d) {
                d3.select(this).attr("fill", "steelblue");
                tooltip.style("display", "none");
            })
            .on("mousemove", function(event, d) {
                const [x, y] = d3.pointer(event);
                tooltip.attr("transform", `translate(${x},${y})`);
                tooltip.select("text").text(d);
            });

        // Crear el tooltip
        const tooltip = svg.append("g")
            .attr("class", "tooltip")
            .style("display", "none");

        tooltip.append("rect")
            .attr("width", 30)
            .attr("height", 20)
            .attr("fill", "white")
            .style("opacity", 0.5);

        tooltip.append("text")
            .attr("x", 15)
            .attr("dy", "1.2em")
            .style("text-anchor", "middle")
            .attr("font-size", "12px")
            .attr("font-family", "sans-serif");
    </script>
</body>
</html>

Ejercicio Práctico

Ejercicio 1: Añadir Interactividad a un Gráfico de Líneas

  1. Crea un gráfico de líneas básico.
  2. Añade interactividad para que la línea cambie de color cuando el usuario pase el ratón sobre ella.
  3. Muestra un tooltip con el valor de y en el punto donde el usuario pasa el ratón.

Solución

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Gráfico de Líneas Interactivo</title>
    <script src="https://d3js.org/d3.v6.min.js"></script>
    <style>
        .line {
            fill: none;
            stroke: steelblue;
            stroke-width: 2px;
        }
        .line:hover {
            stroke: orange;
        }
    </style>
</head>
<body>
    <svg width="600" height="400"></svg>
    <script>
        const data = [30, 86, 168, 281, 303, 365];

        const svg = d3.select("svg");
        const width = +svg.attr("width");
        const height = +svg.attr("height");

        const x = d3.scaleLinear()
            .domain([0, data.length - 1])
            .range([0, width]);

        const y = d3.scaleLinear()
            .domain([0, d3.max(data)])
            .nice()
            .range([height, 0]);

        const line = d3.line()
            .x((d, i) => x(i))
            .y(d => y(d));

        svg.append("path")
            .datum(data)
            .attr("class", "line")
            .attr("d", line)
            .on("mouseover", function(event, d) {
                d3.select(this).attr("stroke", "orange");
                tooltip.style("display", null);
            })
            .on("mouseout", function(event, d) {
                d3.select(this).attr("stroke", "steelblue");
                tooltip.style("display", "none");
            })
            .on("mousemove", function(event, d) {
                const [xPos, yPos] = d3.pointer(event);
                const index = Math.round(x.invert(xPos));
                const value = data[index];
                tooltip.attr("transform", `translate(${xPos},${yPos})`);
                tooltip.select("text").text(value);
            });

        // Crear el tooltip
        const tooltip = svg.append("g")
            .attr("class", "tooltip")
            .style("display", "none");

        tooltip.append("rect")
            .attr("width", 30)
            .attr("height", 20)
            .attr("fill", "white")
            .style("opacity", 0.5);

        tooltip.append("text")
            .attr("x", 15)
            .attr("dy", "1.2em")
            .style("text-anchor", "middle")
            .attr("font-size", "12px")
            .attr("font-family", "sans-serif");
    </script>
</body>
</html>

Conclusión

En esta sección, hemos aprendido cómo añadir interactividad a nuestras visualizaciones de D3.js utilizando eventos del DOM y manejadores de eventos. Hemos visto cómo cambiar el color de los elementos y mostrar tooltips en respuesta a eventos del usuario. La interactividad mejora significativamente la experiencia del usuario y hace que las visualizaciones sean más atractivas y útiles.

En la siguiente sección, profundizaremos en cómo manejar eventos de manera más avanzada y cómo crear transiciones y animaciones para nuestras visualizaciones.

D3.js: De Principiante a Avanzado

Módulo 1: Introducción a D3.js

Módulo 2: Trabajando con Selecciones

Módulo 3: Datos y Escalas

Módulo 4: Creando Visualizaciones Básicas

Módulo 5: Visualizaciones Avanzadas

Módulo 6: Interactividad y Animación

Módulo 7: Trabajando con Datos Reales

Módulo 8: Rendimiento y Optimización

Módulo 9: Mejores Prácticas y Técnicas Avanzadas

Módulo 10: Proyecto Final

© Copyright 2024. Todos los derechos reservados