Published
Edited
Aug 15, 2019
1 star
Insert cell
md`# Interactions with Bars from Fullstack DataViz`
Insert cell
d3 = require("d3@5")
Insert cell
{
yield html`
<div id="wrapper" class="wrapper">
<div id="tooltip" class="tooltip">
<div class="tooltip-range">
Humidity: <span id="range"></span>
</div>
<div class="tooltip-value">
<span id="count"></span> days
</div>
</div>
</div>`;
drawBars();
}
Insert cell
async function drawBars() {
// Data
const dataset = await d3.json("https://gist.githubusercontent.com/chekos/7ee802ef53ba4bbd10a3b8161116d638/raw/e0d655473a57fae5ba54e648429bfd01ca698e12/tijuana_weather_data.json")
// dimensiones
let dimensions = {
width: width,
height: width * 0.6,
margin: {
top: 35,
right: 50,
bottom: 50,
left: 50,
},
}
dimensions.boundedWidth = dimensions.width - dimensions.margin.left - dimensions.margin.right
dimensions.boundedHeight = dimensions.height - dimensions.margin.top - dimensions.margin.bottom
// Lienzo pa dibujar todo
const wrapper = d3.select("#wrapper")
.append("svg")
.attr("width", dimensions.width)
.attr("height", dimensions.height)
// margenes / limites
const bounds = wrapper.append("g")
.style("transform", `translate(${dimensions.margin.left}px, ${dimensions.margin.top}px)`)
// inicializamos elementos estaticos
bounds.append("g")
.attr("class", "bins")
bounds.append("line")
.attr("class", "mean")
bounds.append("g")
.attr("class", "x-axis")
.style("transform", `translateY(${dimensions.boundedHeight}px)`)
.append("text")
.attr("class", "x-axis-label")
const metricAccessor = d => d.humidity
const yAccessor = d => d.length
// escalas
const xScale = d3.scaleLinear()
.domain(d3.extent(dataset, metricAccessor))
.range([0, dimensions.boundedWidth])
.nice()
const binsGenerator = d3.histogram()
.domain(xScale.domain())
.value(metricAccessor)
.thresholds(12)
const bins = binsGenerator(dataset)
const yScale = d3.scaleLinear()
.domain([0, d3.max(bins, yAccessor)])
.range([dimensions.boundedHeight, 0])
.nice()
// dibuja datos
const barPadding = 1
let binGroups = bounds.select(".bins")
.selectAll(".bin")
.data(bins)
binGroups.exit()
.remove()
const newBinGroups = binGroups.enter().append("g")
.attr("class", "bin")
newBinGroups.append("rect")
newBinGroups.append("text")
// actualiza binGroups para incluir nueevos puntos
binGroups = newBinGroups.merge(binGroups)
const barRects = binGroups.select("rect")
.attr("x", d => xScale(d.x0) + barPadding)
.attr("y", d => yScale(yAccessor(d)))
.attr("height", d => dimensions.boundedHeight - yScale(yAccessor(d)))
.attr("width", d => d3.max([0, xScale(d.x1) - xScale(d.x0) - barPadding]))
const mean = d3.mean(dataset, metricAccessor)
const meanLine = bounds.selectAll(".mean")
.attr("x1", xScale(mean))
.attr("x2", xScale(mean))
.attr("y1", -20)
.attr("y2", dimensions.boundedHeight)
// ejes
const xAxisGenerator = d3.axisBottom()
.scale(xScale)
const xAxis = bounds.select(".x-axis")
.call(xAxisGenerator)
const xAxisLabel = xAxis.select(".x-axis-label")
.attr("x", dimensions.boundedWidth / 2)
.attr("y", dimensions.margin.bottom - 10)
.text("Humidity")
// interacciones
binGroups.select("rect")
.on("mouseenter", onMouseEnter)
.on("mouseleave", onMouseLeave)
const tooltip = d3.select("#tooltip")
const formatHumidity = d3.format(".2f")
function onMouseEnter(datum) {
tooltip.select("#count")
.text(yAccessor(datum))
tooltip.select("#range")
.text([formatHumidity(datum.x0), formatHumidity(datum.x1)].join(" - "))
const x = xScale(datum.x0) + (xScale(datum.x1) - xScale(datum.x0)) / 2 + dimensions.margin.left
const y = yScale(yAccessor(datum)) + dimensions.margin.top

tooltip.style("transform", `translate(calc( -50% + ${x}px), calc( -100% + ${y}px))`)
tooltip.style("opacity", 1)
}
function onMouseLeave(datum) {
tooltip.style("opacity", 0)
}
}
Insert cell
dataset.Race
Insert cell
html`<style>
.wrapper {
position: relative;
}

.bin rect {
fill: #19267C;
}

.bin rect:hover {
fill: #DC0D7A;
}

.bin text {
text-anchor: middle;
fill: darkgrey;
font-size: 12px;
font-family: sans-serif;
}

.mean {
stroke: maroon;
stroke-dasharray: 2px 4px;
}

.x-axis-label {
fill: black;
font-size: 1.4em;
text-transform: capitalize;
}

.tooltip {
opacity: 0;
position: absolute;
top: -12px;
left: 0;
padding: 0.6em 1em;
background: #fff;
text-align: center;
border: 1px solid #ddd;
z-index: 10;
transition: all 0.2s ease-out;
pointer-events: none;
}

.tooltip:before {
content: '';
position: absolute;
bottom: 0;
left: 50%;
width: 12px;
height: 12px;
background: white;
border: 1px solid #ddd;
border-top-color: transparent;
border-left-color: transparent;
transform: translate(-50%, 50%) rotate(45deg);
transform-origin: center center;
z-index: 10;
}

.tooltip-range {
margin-bottom: 0.2em;
font-weight: 600;
}
</style>`
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