var container = d3.select("article"); // Set up columns var columnWidth = 400; var gutter = 20; // Defined and used later for offsets when things loop around var x = d3.scale.threshold(); var y = d3.scale.threshold(); var opacity = d3.scale.threshold(); // Load sections Promise.all( ["solon.html", "poplicola.html", "comparison.html"].map(d => fetch(d).then(resp => resp.text()) ) ).then(render); function render(data) { data = data.map(function(html) { return {html}; }); container.style('width', columnWidth + 'px'); // Load sections into html var section = container.selectAll("section") .data(data) .enter() .append("section") .html(d => d.html); // Save initial computed layout as bound data section .each(function(d) { d.height = this.getBoundingClientRect().height; d.top = this.offsetTop; }) .style('height', function(d) { return d.height + 'px'; }); // Compound breakpoints (for when things should loop around) var thresholds = section.data().map(function(d,i) { return [d.top, -i*(columnWidth + gutter), 1/Math.pow(2,i)]; }); x.domain(thresholds.map(d => d[0])) .range(thresholds.map(d => d[1])); y.domain(thresholds.map(d => d[0])) .range(thresholds.map(d => d[0])); opacity.domain(thresholds.map(d => d[0])) .range(thresholds.map(d => d[2])); // Position everything absolutely var block = section.selectAll('h2,h3,p') .datum(function(d) { return { 'top': this.offsetTop, 'height': this.offsetHeight } }) .style('position', 'absolute') .style('width', columnWidth + 'px'); d3.select(window).on("scroll", recompute); recompute(); // Recompute layout on scroll function recompute() { var containerTop = container.node().getBoundingClientRect().top; block .style('left', function(d) { return x(-(containerTop + d.top + d.height)) + 'px'; }) .style('top', function(d) { return d.top + y(-(containerTop + d.top + d.height)) + 'px'; }) .style('opacity', function(d) { return opacity(-(containerTop + d.top + d.height)); }); } } // This isn't actually used but I'm leaving it here as a reminder // that there must be better ways to do this than d3 threshold scales, // like just floors and modulos or uh whatever I'm an idiot. // http://javascript.about.com/od/problemsolving/a/modulobug.htm Number.prototype.mod = function(n) { return ((this%n)+n)%n; }