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();
}