Skip to content

Instantly share code, notes, and snippets.

@lmatteis
Last active August 23, 2019 23:29
Scrollable bar charts with nested scales and fixed x axis
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.bar--positive {
fill: #9BCCF5;
}
.bar--negative {
fill: pink;
}
text {
font: 10px sans-serif;
}
.tick text {
fill: #000;
}
.axis path,
.axis line {
fill: none;
stroke: #909090;
shape-rendering: crispEdges;
}
text.link {
fill: #4B4BCE;
cursor:pointer;
text-decoration: underline;
}
.title {
font-size: 13px;
font-weight:bold;
}
#chart {
width: 960px;
height: 470px;
overflow-y: scroll;
}
</style>
<body>
<div id="chart"></div>
<div id="xaxis"></div>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src='http://crossfilter.github.io/crossfilter/crossfilter.v1.min.js'></script>
<script>
var data = [{"key":"http://viralfeeds.biz/url2/v10","interactions":276200,"unique_authors":141400,"topic":"BMW"},{"key":"http://www.dat.de/angebote/verlagsprodukte/leitfaden-kraftstoffverbrauch.html","interactions":28000,"unique_authors":25400,"topic":"BMW"},{"key":"http://insider.foxnews.com/2016/03/20/florida-man-steals-bmw-after-trying-buy-it-ebt-card-food-stamps","interactions":27300,"unique_authors":26100,"topic":"BMW"},{"key":"http://bit.ly/1pQ4wmf","interactions":26500,"unique_authors":26500,"topic":"BMW"},{"key":"http://bit.ly/22DMFjE","interactions":13800,"unique_authors":13800,"topic":"BMW"},{"key":"http://blog.dupontregistry.com/bmw/bmw-3-0-csl-hommage-rs-booming-engine/","interactions":10900,"unique_authors":10500,"topic":"BMW"},{"key":"http://bit.ly/1MsBH98","interactions":10800,"unique_authors":10300,"topic":"BMW"},{"key":"http://www.topgear.com/car-news/classic/icymi-bmws-m4-gts-and-predecessors","interactions":9600,"unique_authors":9200,"topic":"BMW"},{"key":"http://bit.ly/1SD75yD","interactions":9000,"unique_authors":9000,"topic":"BMW"},{"key":"https://www.g-power.com/onlineshop-de/","interactions":8300,"unique_authors":5600,"topic":"BMW"},{"key":"http://www.dat.de/angebote/verlagsprodukte/leitfaden-kraftstoffverbrauch.html","interactions":27900,"unique_authors":25400,"topic":"Cars"},{"key":"http://blog.dupontregistry.com/bmw/bmw-3-0-csl-hommage-rs-booming-engine/","interactions":10900,"unique_authors":10500,"topic":"Cars"},{"key":"http://www.msn.com/en-us/autos/autos-sports/ford-mustang-outsold-audi-tt-and-porsche-911-in-germany/ar-BBrwGGa?li=BBnb4R5","interactions":4500,"unique_authors":4300,"topic":"Cars"},{"key":"http://fastmusclecar.com/supercharged-cars/1966-ford-mustang-sema-show-car-custom-500hp/","interactions":4300,"unique_authors":3900,"topic":"Cars"},{"key":"http://fastmusclecar.com/muscle-cars/1968-ford-mustang-gt-cobrajet-fastback/","interactions":4300,"unique_authors":3500,"topic":"Cars"},{"key":"http://fastmusclecar.com/readers-rides/1967-ford-mustang-351c-prostreet-show-car/","interactions":4100,"unique_authors":3300,"topic":"Cars"},{"key":"http://fastmusclecar.com/muscle-cars/1965-ford-mustang-302-pro-touring/","interactions":3900,"unique_authors":3600,"topic":"Cars"},{"key":"http://bit.ly/1Mnhl18","interactions":3700,"unique_authors":2500,"topic":"Cars"},{"key":"http://fastmusclecar.com/best-muscle-cars/1965-ford-mustang-gt-restomod-347/","interactions":2900,"unique_authors":2700,"topic":"Cars"},{"key":"http://fastmusclecar.com/best-muscle-cars/1970-ford-mustang-g-code-boss-302/","interactions":2900,"unique_authors":2400,"topic":"Cars"},{"key":"http://www.roadandtrack.com/car-culture/news/a28751/lamborghini-countach-amphibious-replica/","interactions":7000,"unique_authors":6700,"topic":"Honda Civic"},{"key":"http://paultan.org/2016/04/07/iims-2016-new-honda-civic-launched-1-5l-turbo-only/","interactions":6600,"unique_authors":6100,"topic":"Honda Civic"},{"key":"http://carros.mercadolivre.com.br/honda/civic","interactions":4100,"unique_authors":3900,"topic":"Honda Civic"},{"key":"https://tw.autos.yahoo.com/news/rs%E9%A0%82%E7%B4%9A%E8%BB%8A%E5%9E%8B%E5%9…D%A3%E5%BC%8F%E7%99%BC%E8%A1%A8-%E4%B8%AD%E5%9C%8B%E7%89%88-043500327.html","interactions":3300,"unique_authors":3100,"topic":"Honda Civic"},{"key":"http://www.autoguide.com/auto-news/2016/03/honda-makes-it-official-all-turbo-civics-to-get-six-speed-manual.html","interactions":2800,"unique_authors":2600,"topic":"Honda Civic"},{"key":"http://paultan.org/2016/04/18/2016-honda-civic-spore-gets-1-6-only-from-rm318k/","interactions":2600,"unique_authors":2600,"topic":"Honda Civic"},{"key":"http://revistaautoesporte.globo.com/Noticias/noticia/2016/03/toyota-corolla-tambem-e-atualizado-nos-estados-unidos.html","interactions":2200,"unique_authors":2100,"topic":"Honda Civic"},{"key":"http://www.fastcar.co.uk/2016/03/31/stanced-honda-civic-ek-coupe/","interactions":2100,"unique_authors":2100,"topic":"Honda Civic"},{"key":"http://www.carbuzz.com/news/2016/3/24/Honda-Confirms-Civic-Hatchback-Will-Be-Fun-And-Talks-Type-R-And-Si-Release-Dates-7732651/","interactions":1800,"unique_authors":1800,"topic":"Honda Civic"},{"key":"http://bit.ly/_Fa%C3%A7aUmTestDrive","interactions":1700,"unique_authors":1600,"topic":"Honda Civic"},{"key":"http://oak.ctx.ly/r/4g9r7","interactions":13600,"unique_authors":13600,"topic":"Ford Mustang"},{"key":"http://oak.ctx.ly/r/4g9rm","interactions":12600,"unique_authors":11200,"topic":"Ford Mustang"},{"key":"http://www.carbuzz.com/news/2016/4/9/The-Ford-Mustang-Just-Outsold-Two-Of-Germany-s-Top-Sports-Cars-In-Germany-7732965/","interactions":8800,"unique_authors":8700,"topic":"Ford Mustang"},{"key":"http://bit.ly/1o46dL2","interactions":7200,"unique_authors":7200,"topic":"Ford Mustang"},{"key":"http://mensclubmagazine.info/top-10-best-mustangs/","interactions":7100,"unique_authors":6500,"topic":"Ford Mustang"},{"key":"http://www.roadandtrack.com/car-shows/new-york-auto-show/news/a28539/the-legendary-shelby-gt-h-is-back","interactions":6100,"unique_authors":5800,"topic":"Ford Mustang"},{"key":"http://racing.ford.com/enthusiasts/media-room/2016/03/shelby-american--hert…nive/ford-shelby-gt350r-mustang-names-sports-car-of-the-year-by-popul.html","interactions":4900,"unique_authors":4500,"topic":"Ford Mustang"},{"key":"http://www.msn.com/en-us/autos/autos-sports/ford-mustang-outsold-audi-tt-and-porsche-911-in-germany/ar-BBrwGGa?li=BBnb4R5","interactions":4500,"unique_authors":4300,"topic":"Ford Mustang"},{"key":"http://fastmusclecar.com/supercharged-cars/1966-ford-mustang-sema-show-car-custom-500hp/","interactions":4300,"unique_authors":3900,"topic":"Ford Mustang"},{"key":"http://fastmusclecar.com/muscle-cars/1968-ford-mustang-gt-cobrajet-fastback/","interactions":4300,"unique_authors":3500,"topic":"Ford Mustang"},{"key":"http://www.carbuzz.com/news/2016/4/7/Ford-Just-Made-The-Already-Epic-Shelby-GT350-Mustang-Better-But-At-What-Cost-7732922/","interactions":7400,"unique_authors":7300,"topic":"Ford Motor Company"},{"key":"http://ford.to/1Rk6KRp","interactions":7200,"unique_authors":7100,"topic":"Ford Motor Company"},{"key":"http://bit.ly/1o46dL2","interactions":7200,"unique_authors":7200,"topic":"Ford Motor Company"},{"key":"http://bit.ly/1RA30jl","interactions":3400,"unique_authors":3000,"topic":"Ford Motor Company"},{"key":"http://www.1320video.com/differential-explodes-at-drag-strip/","interactions":3000,"unique_authors":2900,"topic":"Ford Motor Company"},{"key":"http://tn.com.ar/autos/lo-ultimo/muy-especial-el-ford-mustang-del-que-se-haran-solo-140-unidades_661123","interactions":2800,"unique_authors":2700,"topic":"Ford Motor Company"},{"key":"http://www.ford-trucks.com/articles/ford-mustang-best-selling-car-in-germany/","interactions":2800,"unique_authors":2700,"topic":"Ford Motor Company"},{"key":"http://oak.ctx.ly/r/4i08j","interactions":2700,"unique_authors":2700,"topic":"Ford Motor Company"},{"key":"https://www.instagram.com/p/BCYFVkXpCSB/?taken-by=ford","interactions":2700,"unique_authors":2700,"topic":"Ford Motor Company"},{"key":"http://www.caradvice.com.au/419671/2019-ford-bronco-rendered-get-a-load-of-this/","interactions":2600,"unique_authors":2500,"topic":"Ford Motor Company"}];
var xf = crossfilter(data);
var topic = xf.dimension(function (d) { return d.topic; }),
topics = topic.group().reduce(
function (p, v) { if (!p[v.key]) p[v.key] = 0; p[v.key] += v.interactions; return p; },
function (p, v) { if (!p[v.key]) p[v.key] = 0; p[v.key] -= v.interactions; return p; },
function () { return {}; }
)
var dispatch = d3.dispatch('redraw');
drawHorizontalBars('#chart', dispatch, topic, topics)
dispatch.redraw();
function drawHorizontalBars (selector, dispatch, dimension, group) {
var margin = {top: 20, right: 20, bottom: 0, left: 100},
width = 940 - margin.left - margin.right,
height = 900 - margin.top - margin.bottom;
var leftSpacing = 200;
var color = d3.scale.category20();
var t = d3.transition()
.duration(750);
var x = d3.scale.linear()
.range([0, width - leftSpacing]);
var y = d3.scale.ordinal()
.rangeRoundBands([0, height], 0.1);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(7)
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickSize(0)
var svg = d3.select(selector).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var xAxisSvg = d3.select('#xaxis').append('svg')
.attr("width", width + margin.left + margin.right)
.attr("height", 20)
.append("g")
// .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
dispatch.on('redraw.' + selector, function () {
var data = group.all()
var arr = []
data.forEach(function(d) {
d.arr = []
var obj = d.value;
for (var i in obj) {
arr.push(obj[i])
d.arr.push({
topic: d.key,
link: i,
interactions: obj[i]
})
}
})
var domain = [0, d3.max(arr)]
x.domain(domain).nice();
y.domain(data.map(function(d) { return d.key; }));
var cont = svg.append('g').attr('style', 'overflow:auto;')
var g = cont.selectAll("g.topic")
.data(data).enter().append('g')
.attr('class', 'topic')
.attr("transform", function (d) { return "translate(0," + y(d.key) + ")" })
var bars = g.selectAll('.bar')
.data(function (d) { return d.arr })
.enter().append('rect')
.attr('class', 'bar')
var y1 = d3.scale.ordinal()
.rangeRoundBands([0, y.rangeBand()], 0.1)
.domain([0,1,2,3,4,5,6,7,8,9]);
bars
.attr('fill', function (d) { return color(d.topic)})
.attr("x", function(d) { return leftSpacing; })
.attr("y", function(d, i) { return y1(i); })
.attr("height", y1.rangeBand())
.attr("width", function(d) { return Math.abs(x(d.interactions)) - x(leftSpacing); })
var texts = g.selectAll('text.link')
.data(function (d) { return d.arr })
.enter().append('text')
.attr('class', 'link')
texts
.attr("x", function (d, i) { return 10 })
.attr("y", function (d, i) { return y1(i) + (y1.rangeBand() / 2) })
.attr('dy', '.35em')
.text(function (d) { return d.link.substring(0, (leftSpacing / 5.3)) })
.on('click', function (d) { window.open(d.link, '_blank'); })
var xAxisDom = xAxisSvg.selectAll('.x.axis')
if (xAxisDom.empty()) {
xAxisDom = xAxisSvg.append("g")
.attr("class", "x axis")
}
xAxisDom
.attr("transform", "translate("+ (leftSpacing + margin.left) +"," + 1 + ")")
.call(xAxis);
xAxisDom
.selectAll('.tick text')
.text(function (d) { if (d < 0) return -d; else return d; })
var yAxisDom = svg.selectAll('.y.axis')
if (yAxisDom.empty()) {
yAxisDom = svg.append("g")
.attr("class", "y axis")
}
yAxisDom
.transition(t)
.attr("transform", "translate(" + x(0) + ",0)")
.call(yAxis);
});
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment