|
import scroll from '../lib/scrollListener' |
|
|
|
const Velocity = require('velocity-animate') |
|
|
|
const fetchAnchors = el => { |
|
let anchors = [].slice.call( el.querySelectorAll('[href]') ) |
|
return anchors.filter( restrictToHash ).map( fetchDestinations ) |
|
} |
|
|
|
const restrictToHash = el => /#/.test( el.anchor = el.getAttribute('href') ) |
|
|
|
const fetchDestinations = el => ( |
|
{ |
|
anchor: el, |
|
dest: document.getElementById( /.*#(.*)/.exec(el.anchor).pop() ) |
|
} |
|
) |
|
|
|
const reduceToClosest = scrollTop => (prev, curr) => { |
|
//Create a new object, with the key being the offset |
|
let obj = [prev,curr].reduce( (a,b) => (a[ Math.abs( b.dest.offsetY - scrollTop) ] = b, a), {}) |
|
let closest = Math.min( ...Object.keys(obj) ) |
|
return obj[closest] |
|
} |
|
|
|
const getOffset = (el, win=window, docElem=document.documentElement, box=false) => ( |
|
box = el.getBoundingClientRect(), |
|
box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0) |
|
) |
|
|
|
const cacheOffsets = el => el.offsetY = getOffset(el) |
|
|
|
export default function(el) { |
|
const waypoints = fetchAnchors(el) |
|
const sticky = el.querySelector('.js-inner') |
|
|
|
let offset; |
|
let getAllOffsets; |
|
(getAllOffsets = function(){ |
|
waypoints.map(el => el.dest).forEach(cacheOffsets) |
|
offset = getOffset(el) |
|
})(); |
|
|
|
scroll( (scrollTop) => { |
|
if ( scrollTop >= offset) { |
|
sticky.classList.add('is-fixed') |
|
} else { |
|
sticky.classList.remove('is-fixed') |
|
} |
|
|
|
waypoints.forEach( el => el.anchor.classList.remove('is-active')) |
|
waypoints.reduce( reduceToClosest(scrollTop) ).anchor.classList.add('is-active') |
|
}) |
|
|
|
waypoints.forEach( waypoint=> { |
|
waypoint.anchor.addEventListener('click', e => { |
|
e.preventDefault() |
|
e.returnValue = false |
|
Velocity(document.body, 'scroll', {duration: 1000, offset: getOffset(waypoint.dest) - 100 }) |
|
}) |
|
}) |
|
|
|
window.addEventListener('resize', getAllOffsets) |
|
} |
A super duper simple waypoints library to handle the simple challenge of having a submenu of anchor links with ID-based href's (i.e. #Intro) that need to initiate a scroll animation to the corresponding DOM Element. See the submenu on Wanderlust 108s for an example of what I am talking about.
Dependencies
This example uses the RAFScroll library to replace window.addEventListener('scroll', function(e) {.. native usage. Replace if you want a simple but less performant option. We also use the Velocity animation library to fade in the video. Again, replace this with another form of animation if you need!
Notes
is-fixed
class to the submenu when it has reached the top of the page.is-active
class to an anchor element when the user has scrolled to it's corresponding DOM NodeUsage
InitScripts initialization pattern
Vanilla Javascript initialization