Published
Edited
Oct 3, 2020
Fork of 3.2 Tooltips
1 star
Insert cell
Insert cell
{
// 1. Creación de un área de dibujo
const svg = d3.create("svg")
.attr("width",width)
.attr("height",height);
// 2. Ejes
svg.append("g").call(xAxis);
svg.append("g").call(yAxis);
// 3. Asociamos los datos: Usamos datum (y no data) cuando queremos asociar
// un único elemento gráfico a los datos, en este caso, un solo path está asociado a toda la linea
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "#ff006e")
.attr("stroke-width", 1.5)
.attr("d", function(d) { return line(d) }); // El dato es la linea (ver abajo)
// 4. Retornamos el canvas
return svg.node();
}
Insert cell
Insert cell
data = d3.csvParse(await FileAttachment("aapl-bollinger.csv").text(), d3.autoType)
Insert cell
Insert cell
polyline = d3.line()([[10, 60], [40, 90], [60, 40], [90, 50]])
Insert cell
Insert cell
// Prueben modificar los puntos de la polyline en la celda de arriba para ver modificaciones
svg`<svg width=200 height=100 viewBox="0 0 200 100">
<path d="${polyline}" stroke="black" fill="none" />
</svg>`
Insert cell
Insert cell
line = d3.line()
.x(d => x(d.date)) // x corresponde al campo fecha
.y(d => y(d.close)) // y corresponde al campo close
Insert cell
Insert cell
html`<div>
Soy un poco de texto dentro de un componente div
</div>`
Insert cell
Insert cell
html`<div>
<div>
<img width="215" src="https://i.pinimg.com/736x/3e/84/09/3e8409dcdd012b4bcda84a710f2d1052.jpg">
</div>
<div>
El tutorial no termina más.
</div>
</div>`
Insert cell
Insert cell
{
// 1. Creación de un área de dibujo
const svg = d3.create("svg")
.attr("width",width/4)
.attr("height",height);
// 2. Componente del tooltip, texto dentro de un div.
var tooltip = d3.select("body").append("div")
.style("position", "absolute")
.style("visibility", "hidden") // Al principio está oculto
.text("Soy un círculo 😊");
const margen_tooltip = 10 // Pequeño desplazamiento para que el tooltip no se muestre sobre el cursor
// 3. Agrego un solo círculo a mi canvas
const circle = svg.append("circle")
.attr("cx", width/8)
.attr("cy", height/2)
.attr("r", 40)
.attr("fill", "#ff006e")
// a. Utilizo los eventos del mouse para volverlo visible si el mouse pasa sobre el círculo
.on("mouseover", function(){
// Al entrar el mouse, se vuelve visible
tooltip.style("visibility", "visible");
})
.on("mousemove", function(){
// b. Mientras estamos dentro, actualizamos la posición del tooltip
tooltip.style("top", (d3.event.pageY-margen_tooltip)+"px")
.style("left",(d3.event.pageX+margen_tooltip)+"px");
})
.on("mouseout", function(){
// c. Al salir del círculo, ocultamos el tooltip
tooltip.style("visibility", "hidden");
});

// 4. Retorno el canvas
return svg.node();
}
Insert cell
Insert cell
{

// 1. Creación de un área de dibujo
const svg = d3.create("svg")
.attr("width",width/4)
.attr("height",height);
// 2. Componente del tooltip, texto dentro de un div.
var tooltip = d3.select("body").append("div")
.style("position", "absolute")
.style("visibility", "hidden") // Al principio está oculto
.text("");
const margen_tooltip = 10 // Pequeño desplazamiento para que el tooltip no se muestre sobre el cursor
// 3. Agrego un solo círculo a mi canvas
const circle = svg.append("circle")
.attr("cx", width/8)
.attr("cy", height/2)
.attr("r", 40)
.attr("fill", "#ff006e")
// a. Utilizo los eventos del mouse para volverlo visible si el mouse pasa sobre el círculo
.on("mouseover", function(){
// Al entrar el mouse, se vuelve visible
tooltip.style("visibility", "visible");
})
.on("mousemove", function(){
// b. Mientras estamos dentro, actualizamos la posición del tooltip
tooltip.style("top", (d3.event.pageY-margen_tooltip)+"px")
.style("left",(d3.event.pageX+margen_tooltip)+"px");
tooltip.text("(x="+ d3.event.pageX.toString()+ ",y=" +d3.event.pageY.toString()+")")
})
.on("mouseout", function(){
// c. Al salir del círculo, ocultamos el tooltip
tooltip.style("visibility", "hidden");
});

// 4. Retorno el canvas
return svg.node();
}
Insert cell
Insert cell
{
// 1. Creación de un área de dibujo
const svg = d3.create("svg")
.attr("width",width)
.attr("height",height);
// 2. Ejes:
svg.append("g").call(xAxis);
svg.append("g").call(yAxis);
// 3. Asociamos los datos: Usamos datum (y no data) cuando queremos asociar
// un único elemento gráfico a los datos, en este caso, un solo path está asociado a toda la linea
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "#ff006e")
.attr("stroke-width", 1.5)
.attr("d", function(d) { return line(d) });
// 4. Componente del tooltip. Esta vez, en vez de un div, utilizaremos un elemento de texto dentro de un
// componente g de svg (grupo)
var tooltip_g = svg.append("g")
.style("visibility", "hide") // Al principio está oculto
// Podemos "colgar" cosas de ese grupo, en este caso agregaremos dos líneas de texto,
// una para la fecha y otra para el valor del campo close. Noten que tenemos que desplazarlos
// ligeramente para que no se superpongan
var tooltip_txt_date = tooltip_g.append("text")
.attr("y", -32) // Prueben modificando estos valores para ver el efecto
.text("texto...");
var tooltip_txt_close = tooltip_g.append("text")
.attr("y", -12) // Prueben modificando estos valores para ver el efecto
.attr("x", 12) // Prueben modificando estos valores para ver el efecto
.text("texto..");
// 5. Agregamos un componente que se encarge de atender los eventos del mouse y mostrar el tooltip.
// El gráfico de línea requiere una estrategia diferente a la hora de visualizar tooltips.
// En el ejemplo del círculo, simplemente bastaba con asociar la aparición y desaparición del
// tooltip a los eventos del mouse de ese círculo. En este caso, no tenemos componentes individuales
// para cada dato, solo una larga y única linea. Por eso, una alternativa que es crear componentes,
// en este caso, rectángulos invisibles, que abarcan todo el alto del gráfico, pero que de ancho solo
// abarcan pares de puntos contiguos. Luego, asociamos a cada rectángulos los eventos de aparición y
// desaparición del tooltip. Además, lo desplazamos hasta la posición correspondiente.
svg.append("g")
.attr("fill", "none")
.attr("pointer-events", "all")
.selectAll("rect")
.data(d3.pairs(data)) // Retorna pares de elementos sucesivos: https://observablehq.com/@d3/d3-pairs
.join("rect") // Creamos rectángulos invisibles por los que pase el mouse para detectar el evento
.attr("x", function([a]) { return x(a.date); })
.attr("height", height)
.attr("width", function([a, b]) { return x(b.date) - x(a.date); })
.on("mouseover", function([a]) {
tooltip_g.style("visibility", "visible"); // Visibilidad del tooltip
tooltip_g.attr("transform", `translate(${x(a.date)},${y(a.close)})`); // Desplazo
tooltip_txt_date.text(formatDate(a.date)); // Le seteamos el texto correcto
tooltip_txt_close.text(formatClose(a.close)); // Le seteamos el texto correcto
})
.on("mouseout", function() { tooltip_g.style("visibility", "hide"); });

// 6. Retornamos el canvas
return svg.node();
}
Insert cell
Insert cell
{
// 1. Creación de un área de dibujo
const svg = d3.create("svg")
.attr("width",width)
.attr("height",height);
// 2. Ejes:
svg.append("g").call(xAxis);
svg.append("g").call(yAxis);
// 3. Asociamos los datos: Usamos datum (y no data) cuando queremos asociar
// un único elemento gráfico a los datos, en este caso, un solo path está asociado a toda la linea
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "#ff006e")
.attr("stroke-width", 1.5)
.attr("d", function(d) { return line(d) });
// 4. Componente del tooltip. Esta vez, en vez de un div, utilizaremos un elemento de texto dentro de un
// componente g de svg (grupo)
var tooltip_g = svg.append("g")
.style("visibility", "hide") // Al principio está oculto
// Podemos "colgar" cosas de ese grupo, en este caso agregaremos dos líneas de texto,
// una para la fecha y otra para el valor del campo close. Noten que tenemos que desplazarlos
// ligeramente para que no se superpongan
var tooltip_txt_date = tooltip_g.append("text")
.attr("y", -32) // Prueben modificando estos valores para ver el efecto
.text("texto...");
var tooltip_txt_close = tooltip_g.append("text")
.attr("y", -12) // Prueben modificando estos valores para ver el efecto
.attr("x", 12) // Prueben modificando estos valores para ver el efecto
.text("texto..");
// 5. Agregamos un componente que se encarge de atender los eventos del mouse y mostrar el tooltip.
// El gráfico de línea requiere una estrategia diferente a la hora de visualizar tooltips.
// En el ejemplo del círculo, simplemente bastaba con asociar la aparición y desaparición del
// tooltip a los eventos del mouse de ese círculo. En este caso, no tenemos componentes individuales
// para cada dato, solo una larga y única linea. Por eso, una alternativa que es crear componentes,
// en este caso, rectángulos invisibles, que abarcan todo el alto del gráfico, pero que de ancho solo
// abarcan pares de puntos contiguos. Luego, asociamos a cada rectángulos los eventos de aparición y
// desaparición del tooltip. Además, lo desplazamos hasta la posición correspondiente.
svg.append("g")
.attr("fill", "none")
.attr("pointer-events", "all")
.selectAll("rect")
.data(d3.pairs(data)) // Retorna pares de elementos sucesivos: https://observablehq.com/@d3/d3-pairs
.join("rect") // Creamos rectángulos invisibles por los que pase el mouse para detectar el evento
.attr("x", function([a]) { return x(a.date); })
.attr("height", height)
.attr("width", function([a, b]) { return x(b.date) - x(a.date); })
.on("mouseover", function([a]) {
tooltip_g.style("visibility", "visible"); // Visibilidad del tooltip
tooltip_g.attr("transform", `translate(${x(a.date)},${y(a.close)})`); // Desplazo
tooltip_txt_date.text(formatDate(a.date)); // Le seteamos el texto correcto
tooltip_txt_close.text(formatClose(a.close)); // Le seteamos el texto correcto
d3.select(this).style("fill","red").style("opacity",0.5)
})
.on("mouseout", function() {
tooltip_g.style("visibility", "hide");
d3.select(this).style("fill","none")
});

// 6. Retornamos el canvas
return svg.node();
}
Insert cell
Insert cell
{
// 1. Creación de un área de dibujo
const svg = d3.create("svg")
.attr("width",width)
.attr("height",height);
// 2. Ejes:
svg.append("g").call(xAxis);
svg.append("g").call(yAxis);
// 3. Asociamos los datos: Usamos datum (y no data) cuando queremos asociar
// un único elemento gráfico a los datos, en este caso, un solo path está asociado a toda la linea
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "#ff006e")
.attr("stroke-width", 1.5)
.attr("d", function(d) { return line(d) });
// 4. Componente del tooltip. Esta vez, en vez de un div, utilizaremos un elemento de texto dentro de un
// componente g de svg (grupo)
var tooltip_g = svg.append("g")
.style("visibility", "hide") // Al principio está oculto
// Podemos "colgar" cosas de ese grupo, en este caso agregaremos dos líneas de texto,
// una para la fecha y otra para el valor del campo close. Noten que tenemos que desplazarlos
// ligeramente para que no se superpongan
var tooltip_txt_date = tooltip_g.append("text")
.attr("y", -32) // Prueben modificando estos valores para ver el efecto
.attr("x", -32)
.text("texto...");
var tooltip_txt_close = tooltip_g.append("text")
.attr("y", -12) // Prueben modificando estos valores para ver el efecto
.attr("x", -22) // Prueben modificando estos valores para ver el efecto
.text("texto..");
// Círculo para el tooltip
var tooltip_circle = tooltip_g.append("circle")
.attr("r", 2.5);
// 5. Agregamos un componente que se encarge de atender los eventos del mouse y mostrar el tooltip.
// El gráfico de línea requiere una estrategia diferente a la hora de visualizar tooltips.
// En el ejemplo del círculo, simplemente bastaba con asociar la aparición y desaparición del
// tooltip a los eventos del mouse de ese círculo. En este caso, no tenemos componentes individuales
// para cada dato, solo una larga y única linea. Por eso, una alternativa que es crear componentes,
// en este caso, rectángulos invisibles, que abarcan todo el alto del gráfico, pero que de ancho solo
// abarcan pares de puntos contiguos. Luego, asociamos a cada rectángulos los eventos de aparición y
// desaparición del tooltip. Además, lo desplazamos hasta la posición correspondiente.
svg.append("g")
.attr("fill", "none")
.attr("pointer-events", "all")
.selectAll("rect")
.data(d3.pairs(data)) // Retorna pares de elementos sucesivos: https://observablehq.com/@d3/d3-pairs
.join("rect") // Creamos rectángulos invisibles por los que pase el mouse para detectar el evento
.attr("x", function([a]) { return x(a.date); })
.attr("height", height)
.attr("width", function([a, b]) { return x(b.date) - x(a.date); })
.on("mouseover", function([a]) {
tooltip_g.style("visibility", "visible"); // Visibilidad del tooltip
tooltip_g.attr("transform", `translate(${x(a.date)},${y(a.close)})`); // Desplazo
tooltip_txt_date.text(formatDate(a.date)); // Le seteamos el texto correcto
tooltip_txt_close.text(formatClose(a.close)); // Le seteamos el texto correcto
})
.on("mouseout", function() { tooltip_g.style("visibility", "hide"); });

// 6. Retornamos el canvas
return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
formatClose = d3.format("$.2f")
Insert cell
formatDate = d3.utcFormat("%b %-d, ’%y")
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