UNPKG

parallaxis

Version:

A tiny parallax library that updates styles on scroll

338 lines (277 loc) 9.38 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.parallaxis = factory()); }(this, (function () { 'use strict'; var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var performanceNow = createCommonjsModule(function (module) { // Generated by CoffeeScript 1.7.1 (function() { var getNanoSeconds, hrtime, loadTime; if ((typeof performance !== "undefined" && performance !== null) && performance.now) { module.exports = function() { return performance.now(); }; } else if ((typeof process !== "undefined" && process !== null) && process.hrtime) { module.exports = function() { return (getNanoSeconds() - loadTime) / 1e6; }; hrtime = process.hrtime; getNanoSeconds = function() { var hr; hr = hrtime(); return hr[0] * 1e9 + hr[1]; }; loadTime = getNanoSeconds(); } else if (Date.now) { module.exports = function() { return Date.now() - loadTime; }; loadTime = Date.now(); } else { module.exports = function() { return new Date().getTime() - loadTime; }; loadTime = new Date().getTime(); } }).call(commonjsGlobal); }); var root = typeof window === 'undefined' ? commonjsGlobal : window; var vendors = ['moz', 'webkit']; var suffix = 'AnimationFrame'; var raf = root['request' + suffix]; var caf = root['cancel' + suffix] || root['cancelRequest' + suffix]; for(var i = 0; !raf && i < vendors.length; i++) { raf = root[vendors[i] + 'Request' + suffix]; caf = root[vendors[i] + 'Cancel' + suffix] || root[vendors[i] + 'CancelRequest' + suffix]; } // Some versions of FF have rAF but not cAF if(!raf || !caf) { var last = 0 , id = 0 , queue = [] , frameDuration = 1000 / 60; raf = function(callback) { if(queue.length === 0) { var _now = performanceNow() , next = Math.max(0, frameDuration - (_now - last)); last = next + _now; setTimeout(function() { var cp = queue.slice(0); // Clear queue here to prevent // callbacks from appending listeners // to the current frame's queue queue.length = 0; for(var i = 0; i < cp.length; i++) { if(!cp[i].cancelled) { try{ cp[i].callback(last); } catch(e) { setTimeout(function() { throw e }, 0); } } } }, Math.round(next)); } queue.push({ handle: ++id, callback: callback, cancelled: false }); return id }; caf = function(handle) { for(var i = 0; i < queue.length; i++) { if(queue[i].handle === handle) { queue[i].cancelled = true; } } }; } var index = function(fn) { // Wrap in a new function to prevent // `cancel` potentially being assigned // to the native rAF function return raf.call(root, fn) }; var cancel = function() { caf.apply(root, arguments); }; var polyfill = function() { root.requestAnimationFrame = raf; root.cancelAnimationFrame = caf; }; index.cancel = cancel; index.polyfill = polyfill; function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } var cache = new WeakMap(); var difference = function difference(a, b) { return Math.abs(a - b); }; var elements = function elements(className) { var els = [].concat(_toConsumableArray(document.querySelectorAll('.' + className))); return els.map(function (el) { var relative = el.dataset.relative === 'true'; var offset = relative ? elY(el) : 0; var end = parseInt(el.dataset.end, 10); var start = parseInt(el.dataset.start, 10); var opacityStart = parseFloat(el.dataset.opacityStart); var opacityEnd = parseFloat(el.dataset.opacityEnd); var translateXStart = parseInt(el.dataset.translatexStart, 10); var translateXEnd = parseInt(el.dataset.translatexEnd, 10); var translateYStart = parseInt(el.dataset.translateyStart, 10); var translateYEnd = parseInt(el.dataset.translateyEnd, 10); var scaleStart = parseFloat(el.dataset.scaleStart); var scaleEnd = parseFloat(el.dataset.scaleEnd); var updates = {}; if (!isNaN(opacityStart) && !isNaN(opacityEnd)) { updates.opacity = { end: opacityEnd, start: opacityStart }; } if (!isNaN(translateXStart) && !isNaN(translateXEnd)) { updates.translateX = { end: translateXEnd, start: translateXStart }; } if (!isNaN(translateYStart) && !isNaN(translateYEnd)) { updates.translateY = { end: translateYEnd, start: translateYStart }; } if (!isNaN(scaleStart) && !isNaN(scaleEnd)) { updates.scale = { end: scaleEnd, start: scaleStart }; } if (typeof end === 'undefined' || typeof start === 'undefined' || Object.keys(updates) === 0) { return null; } return { el: el, end: end, offset: offset, relative: relative, start: start, updates: updates }; }).filter(function (x) { return x; }); }; var elY = function elY(el) { return scrollY() + el.getBoundingClientRect().top; }; var init = function init() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$className = _ref.className, className = _ref$className === undefined ? 'js-parallaxis' : _ref$className; var els = elements(className); if (els.length) { var updateFunc = update(els); updateOffsetsOnResize(els); updateFunc(); window.addEventListener('scroll', function () { return index(updateFunc); }); } }; var interpolate = function interpolate(start, end, progress) { var p = difference(start, end) * progress; return start > end ? start - p : start + p; }; var interval = function interval(start, end, current) { return difference(start, current) / difference(start, end); }; var limit = function limit(min, max, value) { return Math.max(Math.min(value, max), min); }; var prefixedTransformProp = function prefixedTransformProp() { var el = document.createElement('div'); var vendors = ['Webkit', 'webkit', 'Moz', 'moz', 'ms', 'o']; if (el.style.transform != null) { return 'transform'; } for (var v in vendors) { var prop = vendors[v] + 'Transform'; if (typeof el.style[prop] !== 'undefined') { return prop; } } }; var scrollY = function scrollY() { return parseInt(window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0, 10); }; var update = function update(els) { var transformProp = prefixedTransformProp(); return function () { var y = scrollY(); els.map(function (_ref2) { var el = _ref2.el, end = _ref2.end, offset = _ref2.offset, start = _ref2.start, updates = _ref2.updates; var s = offset + start; var e = offset + end; var state = cache.get(el); if (y >= s && y <= e || state !== 'before' && y < s || state !== 'after' && y > e) { var translateX = 0; var translateY = 0; var scale = 1; var current = limit(s, e, y); var i = interval(s, e, current); if (updates.opacity) { var _updates$opacity = updates.opacity, _end = _updates$opacity.end, _start = _updates$opacity.start; var opacity = interpolate(_start, _end, i).toFixed(2); el.style.opacity = opacity; } if (updates.translateX) { var _updates$translateX = updates.translateX, _end2 = _updates$translateX.end, _start2 = _updates$translateX.start; translateX = parseInt(interpolate(_start2, _end2, i), 10); } if (updates.translateY) { var _updates$translateY = updates.translateY, _end3 = _updates$translateY.end, _start3 = _updates$translateY.start; translateY = parseInt(interpolate(_start3, _end3, i), 10); } if (updates.scale) { var _updates$scale = updates.scale, _end4 = _updates$scale.end, _start4 = _updates$scale.start; scale = interpolate(_start4, _end4, i).toFixed(2); } el.style[transformProp] = 'translate3d(' + translateX + 'px, ' + translateY + 'px, 0) scale(' + scale + ')'; if (y < s) { cache.set(el, 'before'); } else if (y > e) { cache.set(el, 'after'); } else { cache.set(el, 'during'); } } }); }; }; var updateOffsetsOnResize = function updateOffsetsOnResize(els) { var updateOffsets = function updateOffsets() { return els.map(function (x) { if (x.relative) { x.offset = elY(x.el); } }); }; var d = void 0; window.addEventListener('resize', function () { window.clearTimeout(d); d = window.setTimeout(updateOffsets, 50); }); }; return init; })));