Public
Edited
May 3
Insert cell
Type Markdown, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const width = 600;
const height = 500;
const margin = { top: 50, right: 20, bottom: 40, left: 50 };
const data = [
{ pais: "Brasil", valor: 50 },
{ pais: "Uruguay", valor: 40 },
{ pais: "Argentina", valor: 35 },
{ pais: "Chile", valor: 28 },
{ pais: "Paraguay", valor: 22 }
];
// Crear el SVG
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height);
const x = d3.scaleBand()
.domain(data.map(d => d.pais))
.range([margin.left, width - margin.right])
.padding(0.1);
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.valor)])
.nice()
.range([height - margin.bottom, margin.top]);
// Crear los ejes
svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x));
svg.append("g")
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y));
// Crear grupos que contendrán barra + etiqueta para cada elemento
const barGroups = svg.selectAll(".bar-group")
.data(data)
.enter()
.append("g")
.attr("class", "bar-group");
// Añadir las barras dentro de los grupos
barGroups.append("rect")
.attr("class", "barra")
.attr("x", d => x(d.pais))
.attr("y", d => y(d.valor))
.attr("width", x.bandwidth())
.attr("height", d => y(0) - y(d.valor))
.attr("fill", "steelblue");
// Añadir las etiquetas dentro de los grupos con color blanco por defecto
barGroups.append("text")
.attr("class", "etiqueta")
.attr("x", d => x(d.pais) + x.bandwidth() / 2)
.attr("y", d => y(d.valor) - 5)
.attr("text-anchor", "middle")
.style("font-family", "sans-serif")
.style("font-size", "12px")
.style("font-weight", "bold")
.style("fill", "white") // Color blanco por defecto
.text(d => `${d.pais}: ${d.valor}`);
// Añadir interactividad a los grupos completos
barGroups
.on("mouseover", function() {
// Cambiar el color de la barra a naranja
d3.select(this).select("rect")
.attr("fill", "orange");
// Cambiar el color del texto a naranja
d3.select(this).select("text")
.style("fill", "orange");
})
.on("mouseout", function() {
// Restaurar el color de la barra a azul
d3.select(this).select("rect")
.attr("fill", "steelblue");
// Restaurar el color del texto a blanco
d3.select(this).select("text")
.style("fill", "white");
});
return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
{
// Dimensiones del gráfico y márgenes
const width = 600; // Ancho total del SVG
const height = 400; // Alto total del SVG
const margin = { top: 20, right: 20, bottom: 40, left: 50 }; // Márgenes internos

// Datos para la gráfica
const data = [ // Datos a visualizar
{ pais: "Brasil", valor: 50 },
{ pais: "Uruguay", valor: 40 },
{ pais: "Argentina", valor: 35 },
{ pais: "Chile", valor: 28 },
{ pais: "Paraguay", valor: 22 }
];

// Creamos un área de dibujo (SVG)
const svg = d3.create("svg")
.attr("width", width) // Asigna ancho al SVG
.attr("height", height); // Asigna alto al SVG
// Escala horizontal (eje X) tipo categórica
const x = d3.scaleBand()
.domain(data.map(d => d.pais)) // Mapea los países a rangos en eje X
.range([margin.left, width - margin.right]) // Rango: de margen izquierdo a derecho
.padding(0.1); // Espaciado entre barras

// Escala vertical (eje Y) lineal
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.valor)]) // Dominio: de 0 al máximo valor
.range([height - margin.bottom, margin.top]); // Rango: de abajo hacia arriba

// Eje X (abajo)
svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`) // Posiciona el eje abajo
.call(d3.axisBottom(x)); // Crea y agrega el eje X

// Eje Y (izquierda)
svg.append("g")
.attr("transform", `translate(${margin.left},0)`) // Posiciona el eje a la izquierda
.call(d3.axisLeft(y)); // Crea y agrega el eje Y

// Tooltip (cuadro de texto flotante)
var tooltip = d3.select("body").append("div")
.style("position", "absolute") // Posicionamiento flotante
.attr("text-anchor", "middle") // Centrado del texto
.style("visibility", "hidden") // Inicialmente oculto
.style("font-family", '-apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif')
.style("font-size", "10px") // Tamaño de letra
.style("font-weight", "bold") // Texto en negrita
.style("color", "#3d3d3d") // Color de texto
.text(""); // Texto inicial vacío

const margen_tooltip = 10 // Desplazamiento del tooltip respecto al cursor

// Dibujamos las barras
const barras = svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", d => x(d.pais))
.attr("y", d => y(d.valor))
.attr("width", x.bandwidth())
.attr("height", d => y(0) - y(d.valor))
.attr("fill", "steelblue")

// Interacción: mouseover
.on("mouseover", function(d) {
d3.select(this)
.attr("fill", "orange"); // Cambia el color al pasar el mouse
tooltip
.style("visibility", "visible")
.text(`${d.pais}: ${d.valor}`);
})

// Interacción: movimiento dentro de la barra
.on("mousemove", function() {
tooltip
.style("top", (d3.event.pageY + margen_tooltip) + "px")
.style("left", (d3.event.pageX + margen_tooltip) + "px");
})

// Interacción: mouseout
.on("mouseout", function() {
d3.select(this)
.attr("fill", "steelblue"); // Restaura el color original
tooltip
.style("visibility", "hidden");
});

return svg.node(); // Devuelve el nodo SVG para ser insertado en el DOM
}

Insert cell
Insert cell
Insert cell
Insert cell
{
// Dimensiones del gráfico y márgenes
const width = 600; // Ancho total del SVG
const height = 400; // Alto total del SVG
const margin = { top: 20, right: 20, bottom: 40, left: 50 }; // Márgenes internos

// Datos para la gráfica
const data = [ // Lista de países y sus valores asociados
{ pais: "Brasil", valor: 50 },
{ pais: "Uruguay", valor: 40 },
{ pais: "Argentina", valor: 35 },
{ pais: "Chile", valor: 28 },
{ pais: "Paraguay", valor: 22 }
];

// Creamos un área de dibujo SVG
const svg = d3.create("svg") // Crea un nuevo elemento SVG
.attr("width", width) // Define ancho del SVG
.attr("height", height); // Define alto del SVG

// Escala categórica para el eje X
const x = d3.scaleBand()
.domain(data.map(d => d.pais)) // Mapea los países a posiciones
.range([margin.left, width - margin.right]) // Rango horizontal dentro del SVG
.padding(0.1); // Espacio entre barras

// Escala lineal para el eje Y
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.valor)]) // Dominio de 0 al máximo valor
.range([height - margin.bottom, margin.top]); // Rango invertido: mayor valor más arriba

// Eje X (inferior)
svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`) // Posiciona el eje X en la parte inferior
.call(d3.axisBottom(x)); // Dibuja los ticks y etiquetas

// Eje Y (izquierdo)
svg.append("g")
.attr("transform", `translate(${margin.left},0)`) // Posiciona el eje Y a la izquierda
.call(d3.axisLeft(y)); // Dibuja los ticks y etiquetas

// Grupo SVG que contiene el tooltip (texto) y puede ser movido con transform
const tooltip_group = svg.append("g")
.style("visibility", "hidden"); // Oculto por defecto

const tooltip_text = tooltip_group.append("text") // Texto dentro del grupo
.attr("text-anchor", "middle")// Centrado horizontal
.style("font-family", '-apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif')
.style("font-size", "10px") // Tamaño de fuente
.style("fill", "orange") // Color del texto
.style("font-weight", "bold") // Negrita
.text(""); // Texto inicial vacío

const margen_tooltip = 10; // Desplazamiento del tooltip sobre la barra

var seleccionada = null; // Variable que guarda qué país está seleccionado (o null)

// Dibujamos las barras del gráfico
const barras = svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", d => x(d.pais))
.attr("y", d => y(d.valor))
.attr("width", x.bandwidth())
.attr("height", d => y(0) - y(d.valor))
.attr("fill", "steelblue")

// Interacción: al pasar el mouse sobre la barra
.on("mouseover", function(d) {
// Siempre mostrar el tooltip, independientemente de la selección
tooltip_group
.style("visibility", "visible")
.attr("transform", `translate(${x(d.pais) + x.bandwidth()/2}, ${y(d.valor) - margen_tooltip})`);
tooltip_text.text(`${d.pais}: ${d.valor}`);
// Solo cambiar el color si no hay selección
if (seleccionada === null) {
d3.select(this).attr("fill", "orange");
}
})

// Interacción: al sacar el mouse de la barra
.on("mouseout", function(d) {
// Siempre ocultar el tooltip
tooltip_group.style("visibility", "hidden");
// Solo restaurar el color si no está seleccionada
if (seleccionada === null) {
d3.select(this).attr("fill", "steelblue");
}
})

// Interacción: al hacer clic en una barra
.on("click", function(d) {
if (seleccionada === d.pais) {
// Deseleccionar
seleccionada = null;
d3.select(this).attr("fill", "steelblue");
} else {
// Restaurar color anterior
if (seleccionada !== null) {
svg.selectAll("rect")
.filter(b => b.pais === seleccionada)
.attr("fill", "steelblue");
}
// Seleccionar nueva barra
seleccionada = d.pais;
d3.select(this).attr("fill", "#C71585");
}
});

return svg.node(); // Devuelve el nodo SVG para insertar en el DOM
}
Insert cell
Insert cell
{
// Dimensiones y márgenes del SVG
const width = 600;
const height = 400;
const margin = { top: 20, right: 20, bottom: 40, left: 50 };

// Datos por país con valor total y desglose en hombres y mujeres
const data = [
{ pais: "Brasil", valor: 50, hombres: 35, mujeres: 15 },
{ pais: "Uruguay", valor: 40, hombres: 5, mujeres: 35 },
{ pais: "Argentina", valor: 35, hombres: 15, mujeres: 20 },
{ pais: "Chile", valor: 28, hombres: 22, mujeres: 6 },
{ pais: "Paraguay", valor: 22, hombres: 20, mujeres: 2 }
];

// Crear el SVG donde se dibujará todo
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height);

// Escala horizontal (X): países → posición
const x = d3.scaleBand()
.domain(data.map(d => d.pais)) // Nombres de países
.range([margin.left, width - margin.right]) // Espacio disponible
.padding(0.1); // Separación entre barras

// Escala vertical (Y): valores → altura
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.valor)]) // De 0 al máximo valor total
.range([height - margin.bottom, margin.top]); // Desde abajo hacia arriba

// Agregar eje X (inferior)
svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x));

// Agregar eje Y (izquierdo)
svg.append("g")
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y));

// Variable que indica qué país está seleccionado actualmente (o null)
let seleccionada = null;

// Función principal que renderiza el gráfico en función de los datos y la selección
function render(data, seleccionada) {
// Unimos los datos a grupos SVG, uno por país
const groups = svg.selectAll(".barra-grupo")
.data(data, d => d.pais) // Usamos el nombre del país como clave
.join("g") // Maneja automáticamente enter/update/exit: crea nuevos <g> si es necesario, actualiza los existentes, y elimina los que ya no están
.attr("class", "barra-grupo")
.attr("transform", d => `translate(${x(d.pais)},0)`); // Posicionamos el grupo

// Limpiamos el contenido previo de cada grupo antes de redibujar
groups.selectAll("*").remove();

// Para cada grupo (país), dibujamos la barra simple o la barra apilada
groups.each(function(d) {
const g = d3.select(this); // Seleccionamos el grupo actual
const barWidth = x.bandwidth(); // Ancho de cada barra

// Si el país está seleccionado → mostrar como barra apilada
if (d.pais === seleccionada) {
const total = d.valor; // Valor total
const h = d.hombres;
const m = d.mujeres;

const yH = y(h); // Y del tope del segmento hombres
const yM = y(h + m); // Y del tope del segmento mujeres
const heightH = y(0) - yH; // Altura de hombres
const heightM = y(0) - y(m); // Altura de mujeres

// Rectángulo inferior: hombres
g.append("rect")
.attr("class", "apilada")
.attr("y", yH)
.attr("width", barWidth)
.attr("height", heightH)
.attr("fill", "#f1a1bc") // Rosa suave
.on("click", () => manejarClick(d)); // Permite deselección con clic

// Porcentaje centrado para hombres
g.append("text")
.attr("x", barWidth / 2)
.attr("y", yH + heightH / 2)
.attr("text-anchor", "middle")
.attr("dominant-baseline", "middle")
.style("font-size", "12px")
.style("fill", "black")
.style("font-family", '-apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif')
.style("font-weight", "bold") // Negrita
.text(Math.round((h / total) * 100) + "%");

// Rectángulo superior: mujeres
g.append("rect")
.attr("class", "apilada")
.attr("y", yM)
.attr("width", barWidth)
.attr("height", heightM)
.attr("fill", "#7bbfa7") // Verde azulado
.on("click", () => manejarClick(d));

// Porcentaje centrado para mujeres
g.append("text")
.attr("x", barWidth / 2)
.attr("y", yM + heightM / 2)
.attr("text-anchor", "middle")
.attr("dominant-baseline", "middle")
.style("font-size", "12px")
.style("fill", "black")
.style("font-family", '-apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif')
.style("font-weight", "bold") // Negrita
.text(Math.round((m / total) * 100) + "%");

// Si el país no está seleccionado → mostrar barra simple
} else {
g.append("rect")
.attr("class", "barra")
.attr("y", y(d.valor))
.attr("width", barWidth)
.attr("height", y(0) - y(d.valor))
.attr("fill", "steelblue")
// Hover interacciones (solo si no está seleccionada)
.on("mouseover", function() {
if (seleccionada !== d.pais)
d3.select(this).attr("fill", "orange");
})
.on("mouseout", function() {
if (seleccionada !== d.pais)
d3.select(this).attr("fill", "steelblue");
})
.on("click", () => manejarClick(d)); // Clic para seleccionar
}
});
}

// Función que gestiona el clic en una barra (selección/deselección)
function manejarClick(d) {
if (seleccionada === d.pais) {
seleccionada = null; // Si estaba seleccionada → deseleccionamos
} else {
seleccionada = d.pais; // Si no → seleccionamos
}
render(data, seleccionada); // Siempre redibujamos el gráfico luego de un click
}

// Primer renderizado
render(data, seleccionada);

// Devolvemos el nodo SVG para visualizar
return svg.node();
}

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

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.
Learn more