var container = d3.select('body'), article = d3.select('article'), previous; var localScrolls = d3.local(), localScrollSpeed = d3.local(); article .on('scroll.getspeed', setScrollSpeed) .on('scroll.readspeed', function() { if(localScrollSpeed.get(this) > 2 && container.select('.previous').empty()) { previous = container.node().appendChild(article.node().cloneNode(true)); previous.scrollTop = this.scrollTop; d3.select(previous).classed('previous', true); } else if (previous && previous.scrollTop > article.node().scrollTop) { d3.select(previous).remove(); } }) // get scroll speed function setScrollSpeed() { var scrolls = localScrolls.get(this) || []; scrolls.push({t: Date.now(), y: this.scrollTop}); if(scrolls.length > 100) scrolls.shift(); localScrolls.set(this, scrolls); localScrollSpeed.set(this, calcSpeed(scrolls)); function calcSpeed(scrolls) { var now = Date.now(); var scrollSamples = scrolls.filter(function(d) { return now - d.t < 400 }); if(scrollSamples.length > 1) { var s0 = scrollSamples[0]; var s1 = scrollSamples[scrollSamples.length-1]; scrollSpeed = (s1.y - s0.y) / (s1.t - s0.t); } else { scrollSpeed = 0; } // in pixels per millisecond return scrollSpeed; } }