Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add middle scroll option; direction;fix sticky top
  • Loading branch information
mhkeller committed Feb 19, 2016
commit 92bf66bdce1d4cc83135c6422f0047b2e588058a
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@ Simple scrolling events for [d3](https://github.com/mbostock/d3) graphs. Based o

### [Demo/Documentation](http://1wheel.github.io/graph-scroll/)

`graphScroll` takes a selection of explanatory text sections and dispatches `active` events as different sections are scrolled into to view. These `active` events can be used to update a chart's state.
`graphScroll` takes a selection of explanatory text sections and dispatches `active` events as different sections are scrolled into to view. These `active` events can be used to update a chart's state.

A `direction` is also passed on active. It is either `up`, `down` or `jump` (fired when you load a page from not at the time, like when you refresh).

Set an `offset` to determine how far from the top the next section will be before it becomes active.

```js
graphScroll()
.sections(d3.selectAll('#sections > div'))
.on('active', function(i){ console.log(i + 'th section active') })
.offset(180)
.on('active', function(i, direction){ console.log(i + 'th section active', 'Moving ' + direction) })
```

The top most element scrolled fully into view is classed `graph-scroll-active`. This makes it easy to highlight the active section with css:
You can also set `.triggerAt('middle')` to activate the next section when it reaches the middle of the viewport. The top most element scrolled fully into view is classed `graph-scroll-active`. This makes it easy to highlight the active section with css:

```css
#sections > div{
Expand Down Expand Up @@ -47,7 +52,7 @@ graphScroll()
.graph(d3.selectAll('#graph'))
.container(d3.select('#container'))
.sections(d3.selectAll('#sections > div'))
.on('active', function(i){ console.log(i + 'th section active') })
.on('active', function(i, direction){ console.log(i + 'th section active', 'Moving ' + direction) })

```

Expand Down
60 changes: 54 additions & 6 deletions graph-scroll.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
(function(){
var d3 = this.d3 || undefined
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
d3 = require('d3')
exports = module.exports = graphScroll;
}
exports.graphScroll = graphScroll;
Expand All @@ -22,38 +24,70 @@
containerStart = 0,
belowStart,
eventId = Math.random(),
stickyTop
stickyTop,
lastPageY = -Infinity,
triggerAt = 'top',
offset = 0;

function reposition(){
var i1 = 0
var viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0)

// If our lastPageY variable is our default but we're farther than the scroll top, then we are entering the page from somewhere not the top
if (lastPageY == -Infinity && pageYOffset > 0) {
direction = 'jump'
} else if (pageYOffset > lastPageY) {
direction = 'down'
} else {
direction = 'up'
}

sectionPos.forEach(function(d, i){
if (d < pageYOffset - containerStart + 180) i1 = i
// Trigger active section when it gets to the middle of the viewport
if (triggerAt == 'middle' && d < (pageYOffset - containerStart + viewportHeight / 2 + offset) ) {
i1 = i
// Or at the top of the viewport
} else if (triggerAt == 'top' && d < pageYOffset - containerStart + offset) {
i1 = i
}
})

i1 = Math.min(n - 1, i1)
if (i != i1){
sections.classed('graph-scroll-active', function(d, i){ return i === i1 })

dispatch.active.call(sections[0][i1], i1, i)
dispatch.active.call(sections[0][i1], i1, direction)

i = i1
}
var yStickyOffset = stickyTop || 0

var isBelow1 = pageYOffset > belowStart - 120
var isBelow1 = pageYOffset + yStickyOffset > belowStart
if (isBelow != isBelow1){
isBelow = isBelow1
graph.classed('graph-scroll-below', isBelow)
}

var isFixed1 = !isBelow && pageYOffset > containerStart - 120
var isFixed1 = !isBelow && pageYOffset > containerStart - yStickyOffset
if (isFixed != isFixed1){
isFixed = isFixed1
graph
.classed('graph-scroll-fixed', isFixed)
}

var top
if (stickyTop){
graph.style('padding-top', (isBelow || isFixed ? stickyTop : 0)+ 'px')
if (isBelow) {
top = 'auto'
} else if (isFixed) {
top = stickyTop + 'px'
} else {
top = '0px'
}
graph.style('top', top)
}

lastPageY = pageYOffset
}

function resize(){
Expand Down Expand Up @@ -128,6 +162,13 @@
return rv
}

rv.triggerAt = function(_x){
if (!_x) return triggerAt

triggerAt = _x
return rv
}

rv.eventId = function(_x){
if (!_x) return eventId

Expand All @@ -142,6 +183,13 @@
return rv
}

rv.offset = function(_x){
if (!_x) return offset

offset = _x
return rv
}

rv.sections = function (_x){
if (!_x) return sections

Expand Down
16 changes: 10 additions & 6 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,21 @@ <h3>Simple scrolling events for d3 graphics.</h3>
<div>
<h3>Connect text and graphics</h3>
<span class='mono'>graph-scroll</span>
takes a selection of explanatory text sections and dispatches <span class='mono'>active</span> events as different sections are scrolled into to view. These active events are used to update a graph's state.
takes a selection of explanatory text sections and dispatches <span class='mono'>active</span> events as different sections are scrolled into to view. These active events are used to update a graph's state.<br/><br/>A <span class='mono'>direction</span> is also passed on active. It is either <span class='mono'>up</span>, <span class='mono'>down</span> or <span class='mono'>jump</span> (fired when you load a page from not at the time, like when you refresh).<br/><br/>Set an <span class="mono">offset</span> to determine how far from the top the next section will be before it becomes active.
<pre>
graphScroll()
.sections(d3.selectAll('#sections > div'))
.on('active', function(i){
console.log(i + 'th section active') })
.offset(180)
.on('active', function(i, direction){
console.log(i + 'th section active')
console.log('Moving ' + direction)
</pre>

</div>

<div>
<h3>Highlight active text</h3>
The top most text section scrolled into view is classed <span class='mono'>graph-scroll-active</span>. This makes it easy to highlight the active section with css:
You can also set <span class="mono">.triggerAt('middle')</span> to activate the next section when it reaches the middle of the viewport. The top most text section scrolled into view is classed <span class='mono'>graph-scroll-active</span>. This makes it easy to highlight the active section with css:
<pre>
#sections > div{
opacity: .3
Expand Down Expand Up @@ -234,7 +236,9 @@ <h3 id='source'><a href='https://github.com/1wheel/graph-scroll'>contribute/view
.container(d3.select('#container'))
.graph(d3.selectAll('#graph'))
.sections(d3.selectAll('#sections > div'))
.on('active', function(i){
.offset(180)
.triggerAt('top')
.on('active', function(i, direction){
var pos = [ {cx: width - r, cy: r},
{cx: r, cy: r},
{cx: width - r, cy: height - r},
Expand All @@ -257,7 +261,7 @@ <h3 id='source'><a href='https://github.com/1wheel/graph-scroll'>contribute/view
.container(d3.select('#container2'))
.graph(d3.selectAll('#graph2'))
.sections(d3.selectAll('#sections2 > div'))
.on('active', function(i){
.on('active', function(i, direction){
var h = height
var w = width
var dArray = [
Expand Down