Public
Edited
Apr 21, 2023
Insert cell
Insert cell
Insert cell
viewof selection = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width + margin.left + margin.right, height + margin.top + margin.bottom]);

svg.append("g")
.attr("transform", `translate(${width/2},${height+margin.bottom})`)
.append('text')
.attr("font-family", "var(--sans-serif)")
.attr("text-anchor", "middle")
.attr("font-size", "6px")
.attr("fill", "grey")
.text("Log2(CPM+1)")
const selectCount = svg.append("g")
.attr("transform", `translate(0,${margin.top})`)
.append('text')
.attr("font-family", "var(--sans-serif)")
.attr("text-anchor", "middle")
.attr("font-size", "6px")
.attr("fill", "#212121")
.attr("opacity", 0)
.text('poo')
const brush = d3.brushX()
.on("start", startBrush)
.on('brush end',brushing);

const bar = svg.append("g")
.selectAll("rect")
.data(data)
.join("rect")
.attr("fill", (d,i) => color(i))
.attr("x", (d,i) => barScale(i.toString()))
.attr("y", d => y(d.count))
.attr("height", d => y(0) - y(d.count))
.attr("width", barScale.bandwidth())

const mainAxis = svg.append("g")
.attr("class", "x-axis")
.call(xAxis)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line")
.attr("stroke", "grey")
.attr("stroke-width",".5"))
.call(g => g.selectAll(".tick text")
.attr("font-size", "6px")
.attr("fill", "grey"))
const selectionAxis = svg.append("g")
.attr("class", "selection-axis")
.call(selectAxis)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick")
.attr("opacity", 0))
.call(g => g.selectAll(".tick line")
.attr("stroke", "grey")
.attr("stroke-width",".5"))
.call(g => g.selectAll(".tick text")
.attr("font-size", "6px")
.attr("fill", "#212121"))

svg.append("g")
.call(brush);

function clearSelection(){
bar.attr("opacity", 1);
mainAxis.selectAll(".tick")
.attr("opacity", 1);
selectionAxis.selectAll(".tick")
.attr("opacity", 0);
selectCount.attr("opacity", 0)
svg.property("value", []).dispatch("input");
}

function startBrush({selection, sourceEvent}) {
if (!selection || !sourceEvent) return;
if (selection[0]==selection[1]) clearSelection();
}
function brushing({type, selection, sourceEvent}) {
// based on https://observablehq.com/@maritrinez/d3-brushable-timeline
if (!selection && !sourceEvent) return;
if(selection){
const d0 = filteredDomain(...selection);
if (d0.length==0) return;

const min = d0[0], max = d0[d0.length-1];

if(sourceEvent && type=='end'){
const snappedSelection = [barScale(min), barScale(max) + barScale.bandwidth()];
d3.select(this).transition().call(brush.move, snappedSelection);
}

bar.attr("opacity", (d,i) => d0.includes(i.toString()) ? 1 : .25);
mainAxis.selectAll(".tick")
.attr("opacity", 0);
selectionAxis.selectAll(".tick")
.attr("opacity", (d,i) => i==min || (i-1)==max ? 1 : 0);

let count = data.slice(+min,+max+1).reduce((acc,obj) => acc + obj.count, 0);

selectCount.text(count == 0 ? "0" : d3.format(".3s")(count))
.attr("opacity", 1)
.attr("dx", selection[0]+((selection[1]-selection[0])/2));
}
}

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
valuesTick = function(){
const ticks = axisScale.domain();
const filteredTicks = ticks.filter(function(d,i){ return !(i%2) });
return filteredTicks[filteredTicks.length-1]==ticks[ticks.length-1] ? filteredTicks : [...filteredTicks, ticks[ticks.length-1]];
}
Insert cell
valuesTick()
Insert cell
formatTick = function(i){
return d3.format(".1f")(i==data.length ? data[i-1].bin[1] : data[i].bin[0]);
}
Insert cell
Insert cell
Insert cell
minVal = 0
Insert cell
maxVal = 8.309866
Insert cell
colorInterpolator = d3.scaleLinear()
.domain([0, 1])
.range([minColor, maxColor])
.clamp(true)
Insert cell
Insert cell
minColor = '#f5f5f5' // pale
Insert cell
maxColor = '#a70000' // red
Insert cell
margin = ({ top: 5, right: 5, bottom: 15, left: 5 })
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