/*! Shifty 2.9.1 - https://github.com/jeremyckahn/shifty */
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define("shifty", [], factory);
else if(typeof exports === 'object')
exports["shifty"] = factory();
else
root["shifty"] = factory();
})(global, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
var easing_functions_namespaceObject = {};
__webpack_require__.r(easing_functions_namespaceObject);
__webpack_require__.d(easing_functions_namespaceObject, "linear", function() { return linear; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInQuad", function() { return easeInQuad; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutQuad", function() { return easeOutQuad; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutQuad", function() { return easeInOutQuad; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInCubic", function() { return easeInCubic; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutCubic", function() { return easeOutCubic; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutCubic", function() { return easeInOutCubic; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInQuart", function() { return easeInQuart; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutQuart", function() { return easeOutQuart; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutQuart", function() { return easeInOutQuart; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInQuint", function() { return easeInQuint; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutQuint", function() { return easeOutQuint; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutQuint", function() { return easeInOutQuint; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInSine", function() { return easeInSine; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutSine", function() { return easeOutSine; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutSine", function() { return easeInOutSine; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInExpo", function() { return easeInExpo; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutExpo", function() { return easeOutExpo; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutExpo", function() { return easeInOutExpo; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInCirc", function() { return easeInCirc; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutCirc", function() { return easeOutCirc; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutCirc", function() { return easeInOutCirc; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutBounce", function() { return easeOutBounce; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInBack", function() { return easeInBack; });
__webpack_require__.d(easing_functions_namespaceObject, "easeOutBack", function() { return easeOutBack; });
__webpack_require__.d(easing_functions_namespaceObject, "easeInOutBack", function() { return easeInOutBack; });
__webpack_require__.d(easing_functions_namespaceObject, "elastic", function() { return elastic; });
__webpack_require__.d(easing_functions_namespaceObject, "swingFromTo", function() { return swingFromTo; });
__webpack_require__.d(easing_functions_namespaceObject, "swingFrom", function() { return swingFrom; });
__webpack_require__.d(easing_functions_namespaceObject, "swingTo", function() { return swingTo; });
__webpack_require__.d(easing_functions_namespaceObject, "bounce", function() { return bounce; });
__webpack_require__.d(easing_functions_namespaceObject, "bouncePast", function() { return bouncePast; });
__webpack_require__.d(easing_functions_namespaceObject, "easeFromTo", function() { return easeFromTo; });
__webpack_require__.d(easing_functions_namespaceObject, "easeFrom", function() { return easeFrom; });
__webpack_require__.d(easing_functions_namespaceObject, "easeTo", function() { return easeTo; });
var token_namespaceObject = {};
__webpack_require__.r(token_namespaceObject);
__webpack_require__.d(token_namespaceObject, "doesApply", function() { return doesApply; });
__webpack_require__.d(token_namespaceObject, "tweenCreated", function() { return tweenCreated; });
__webpack_require__.d(token_namespaceObject, "beforeTween", function() { return beforeTween; });
__webpack_require__.d(token_namespaceObject, "afterTween", function() { return afterTween; });
// CONCATENATED MODULE: ./src/easing-functions.js
/*!
* All equations are adapted from Thomas Fuchs'
* [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js).
*
* Based on Easing Equations (c) 2003 [Robert
* Penner](http://www.robertpenner.com/), all rights reserved. This work is
* [subject to terms](http://www.robertpenner.com/easing_terms_of_use.html).
*/
/*!
* TERMS OF USE - EASING EQUATIONS
* Open source under the BSD License.
* Easing Equations (c) 2003 Robert Penner, all rights reserved.
*/
/**
* @member shifty.Tweenable.formulas
* @description A static Object of {@link shifty.easingFunction}s that can by
* used by Shifty. The default values are defined in
* [`easing-functions.js`](easing-functions.js.html), but you can add your own
* {@link shifty.easingFunction}s by defining them as keys to this Object.
*
* Shifty ships with an implementation of [Robert Penner's easing
* equations](http://robertpenner.com/easing/), as adapted from
* [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js)'s
* implementation.
*
See the Pen Shifty - Easing formula
* names by Jeremy Kahn (@jeremyckahn) on CodePen.
*
* @type {Object.}
* @static
*/
var linear = function linear(pos) {
return pos;
};
var easeInQuad = function easeInQuad(pos) {
return Math.pow(pos, 2);
};
var easeOutQuad = function easeOutQuad(pos) {
return -(Math.pow(pos - 1, 2) - 1);
};
var easeInOutQuad = function easeInOutQuad(pos) {
return (pos /= 0.5) < 1 ? 0.5 * Math.pow(pos, 2) : -0.5 * ((pos -= 2) * pos - 2);
};
var easeInCubic = function easeInCubic(pos) {
return Math.pow(pos, 3);
};
var easeOutCubic = function easeOutCubic(pos) {
return Math.pow(pos - 1, 3) + 1;
};
var easeInOutCubic = function easeInOutCubic(pos) {
return (pos /= 0.5) < 1 ? 0.5 * Math.pow(pos, 3) : 0.5 * (Math.pow(pos - 2, 3) + 2);
};
var easeInQuart = function easeInQuart(pos) {
return Math.pow(pos, 4);
};
var easeOutQuart = function easeOutQuart(pos) {
return -(Math.pow(pos - 1, 4) - 1);
};
var easeInOutQuart = function easeInOutQuart(pos) {
return (pos /= 0.5) < 1 ? 0.5 * Math.pow(pos, 4) : -0.5 * ((pos -= 2) * Math.pow(pos, 3) - 2);
};
var easeInQuint = function easeInQuint(pos) {
return Math.pow(pos, 5);
};
var easeOutQuint = function easeOutQuint(pos) {
return Math.pow(pos - 1, 5) + 1;
};
var easeInOutQuint = function easeInOutQuint(pos) {
return (pos /= 0.5) < 1 ? 0.5 * Math.pow(pos, 5) : 0.5 * (Math.pow(pos - 2, 5) + 2);
};
var easeInSine = function easeInSine(pos) {
return -Math.cos(pos * (Math.PI / 2)) + 1;
};
var easeOutSine = function easeOutSine(pos) {
return Math.sin(pos * (Math.PI / 2));
};
var easeInOutSine = function easeInOutSine(pos) {
return -0.5 * (Math.cos(Math.PI * pos) - 1);
};
var easeInExpo = function easeInExpo(pos) {
return pos === 0 ? 0 : Math.pow(2, 10 * (pos - 1));
};
var easeOutExpo = function easeOutExpo(pos) {
return pos === 1 ? 1 : -Math.pow(2, -10 * pos) + 1;
};
var easeInOutExpo = function easeInOutExpo(pos) {
if (pos === 0) {
return 0;
}
if (pos === 1) {
return 1;
}
if ((pos /= 0.5) < 1) {
return 0.5 * Math.pow(2, 10 * (pos - 1));
}
return 0.5 * (-Math.pow(2, -10 * --pos) + 2);
};
var easeInCirc = function easeInCirc(pos) {
return -(Math.sqrt(1 - pos * pos) - 1);
};
var easeOutCirc = function easeOutCirc(pos) {
return Math.sqrt(1 - Math.pow(pos - 1, 2));
};
var easeInOutCirc = function easeInOutCirc(pos) {
return (pos /= 0.5) < 1 ? -0.5 * (Math.sqrt(1 - pos * pos) - 1) : 0.5 * (Math.sqrt(1 - (pos -= 2) * pos) + 1);
};
var easeOutBounce = function easeOutBounce(pos) {
if (pos < 1 / 2.75) {
return 7.5625 * pos * pos;
} else if (pos < 2 / 2.75) {
return 7.5625 * (pos -= 1.5 / 2.75) * pos + 0.75;
} else if (pos < 2.5 / 2.75) {
return 7.5625 * (pos -= 2.25 / 2.75) * pos + 0.9375;
} else {
return 7.5625 * (pos -= 2.625 / 2.75) * pos + 0.984375;
}
};
var easeInBack = function easeInBack(pos) {
var s = 1.70158;
return pos * pos * ((s + 1) * pos - s);
};
var easeOutBack = function easeOutBack(pos) {
var s = 1.70158;
return (pos = pos - 1) * pos * ((s + 1) * pos + s) + 1;
};
var easeInOutBack = function easeInOutBack(pos) {
var s = 1.70158;
if ((pos /= 0.5) < 1) {
return 0.5 * (pos * pos * (((s *= 1.525) + 1) * pos - s));
}
return 0.5 * ((pos -= 2) * pos * (((s *= 1.525) + 1) * pos + s) + 2);
};
var elastic = function elastic(pos) {
return -1 * Math.pow(4, -8 * pos) * Math.sin((pos * 6 - 1) * (2 * Math.PI) / 2) + 1;
};
var swingFromTo = function swingFromTo(pos) {
var s = 1.70158;
return (pos /= 0.5) < 1 ? 0.5 * (pos * pos * (((s *= 1.525) + 1) * pos - s)) : 0.5 * ((pos -= 2) * pos * (((s *= 1.525) + 1) * pos + s) + 2);
};
var swingFrom = function swingFrom(pos) {
var s = 1.70158;
return pos * pos * ((s + 1) * pos - s);
};
var swingTo = function swingTo(pos) {
var s = 1.70158;
return (pos -= 1) * pos * ((s + 1) * pos + s) + 1;
};
var bounce = function bounce(pos) {
if (pos < 1 / 2.75) {
return 7.5625 * pos * pos;
} else if (pos < 2 / 2.75) {
return 7.5625 * (pos -= 1.5 / 2.75) * pos + 0.75;
} else if (pos < 2.5 / 2.75) {
return 7.5625 * (pos -= 2.25 / 2.75) * pos + 0.9375;
} else {
return 7.5625 * (pos -= 2.625 / 2.75) * pos + 0.984375;
}
};
var bouncePast = function bouncePast(pos) {
if (pos < 1 / 2.75) {
return 7.5625 * pos * pos;
} else if (pos < 2 / 2.75) {
return 2 - (7.5625 * (pos -= 1.5 / 2.75) * pos + 0.75);
} else if (pos < 2.5 / 2.75) {
return 2 - (7.5625 * (pos -= 2.25 / 2.75) * pos + 0.9375);
} else {
return 2 - (7.5625 * (pos -= 2.625 / 2.75) * pos + 0.984375);
}
};
var easeFromTo = function easeFromTo(pos) {
return (pos /= 0.5) < 1 ? 0.5 * Math.pow(pos, 4) : -0.5 * ((pos -= 2) * Math.pow(pos, 3) - 2);
};
var easeFrom = function easeFrom(pos) {
return Math.pow(pos, 4);
};
var easeTo = function easeTo(pos) {
return Math.pow(pos, 0.25);
};
// CONCATENATED MODULE: ./src/tweenable.js
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
// CONSTANTS
var DEFAULT_EASING = 'linear';
var DEFAULT_DURATION = 500;
var UPDATE_TIME = 1000 / 60;
var root = typeof window !== 'undefined' ? window : global;
var AFTER_TWEEN = 'afterTween';
var AFTER_TWEEN_END = 'afterTweenEnd';
var BEFORE_TWEEN = 'beforeTween';
var TWEEN_CREATED = 'tweenCreated';
var TYPE_FUNCTION = 'function';
var TYPE_STRING = 'string'; // requestAnimationFrame() shim by Paul Irish (modified for Shifty)
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
var scheduleFunction = root.requestAnimationFrame || root.webkitRequestAnimationFrame || root.oRequestAnimationFrame || root.msRequestAnimationFrame || root.mozCancelRequestAnimationFrame && root.mozRequestAnimationFrame || setTimeout;
var noop = function noop() {};
var listHead = null;
var listTail = null; // Strictly used for testing
var resetList = function resetList() {
return listHead = listTail = null;
};
var getListHead = function getListHead() {
return listHead;
};
var getListTail = function getListTail() {
return listTail;
};
var formulas = _objectSpread({}, easing_functions_namespaceObject);
/**
* Calculates the interpolated tween values of an Object for a given
* timestamp.
* @param {number} forPosition The position to compute the state for.
* @param {Object} currentState Current state properties.
* @param {Object} originalState: The original state properties the Object is
* tweening from.
* @param {Object} targetState: The destination state properties the Object
* is tweening to.
* @param {number} duration: The length of the tween in milliseconds.
* @param {number} timestamp: The UNIX epoch time at which the tween began.
* @param {Object} easing: This Object's keys must correspond
* to the keys in targetState.
* @returns {Object}
* @private
*/
var tweenProps = function tweenProps(forPosition, currentState, originalState, targetState, duration, timestamp, easing) {
var normalizedPosition = forPosition < timestamp ? 0 : (forPosition - timestamp) / duration;
for (var key in currentState) {
var easingObjectProp = easing[key];
var easingFn = easingObjectProp.call ? easingObjectProp : formulas[easingObjectProp];
var start = originalState[key];
currentState[key] = start + (targetState[key] - start) * easingFn(normalizedPosition);
}
return currentState;
};
var processTween = function processTween(tween, currentTime) {
var _attachment = tween._attachment,
_currentState = tween._currentState,
_delay = tween._delay,
_easing = tween._easing,
_originalState = tween._originalState;
var _duration = tween._duration,
_step = tween._step,
_targetState = tween._targetState,
_timestamp = tween._timestamp;
var endTime = _timestamp + _delay + _duration;
var timeToCompute = currentTime > endTime ? endTime : currentTime;
var hasEnded = timeToCompute >= endTime;
var offset = _duration - (endTime - timeToCompute);
if (hasEnded) {
_step(_targetState, _attachment, offset);
tween.stop(true);
} else {
tween._applyFilter(BEFORE_TWEEN); // If the animation has not yet reached the start point (e.g., there was
// delay that has not yet completed), just interpolate the starting
// position of the tween.
if (timeToCompute < _timestamp + _delay) {
timeToCompute = 1;
_duration = 1;
_timestamp = 1;
} else {
_timestamp += _delay;
}
tweenProps(timeToCompute, _currentState, _originalState, _targetState, _duration, _timestamp, _easing);
tween._applyFilter(AFTER_TWEEN);
_step(_currentState, _attachment, offset);
}
};
/**
* Process all tweens currently managed by Shifty for the current tick. This
* does not perform any timing or update scheduling; it is the logic that is
* run *by* the scheduling functionality. Specifically, it computes the state
* and calls all of the relevant {@link shifty.tweenConfig} functions supplied
* to each of the tweens for the current point in time (as determined by {@link
* shifty.Tweenable.now}.
*
* This is a low-level API that won't be needed in the majority of situations.
* It is primarily useful as a hook for higher-level animation systems that are
* built on top of Shifty. If you need this function, it is likely you need to
* pass something like `() => {}` to {@link
* shifty.Tweenable.setScheduleFunction}, override {@link shifty.Tweenable.now}
* and manage the scheduling logic yourself.
*
* @method shifty.processTweens
* @see https://github.com/jeremyckahn/shifty/issues/109
*/
var processTweens = function processTweens() {
var currentTime = Tweenable.now();
var tween = listHead;
while (tween) {
var nextTween = tween._next;
processTween(tween, currentTime);
tween = nextTween;
}
};
/**
* Handles the update logic for one step of a tween.
* @param {number} [currentTimeOverride] Needed for accurate timestamp in
* shifty.Tweenable#seek.
* @private
*/
var scheduleUpdate = function scheduleUpdate() {
if (!listHead) {
return;
}
scheduleFunction.call(root, scheduleUpdate, UPDATE_TIME);
processTweens();
};
/**
* Creates a usable easing Object from a string, a function or another easing
* Object. If `easing` is an Object, then this function clones it and fills
* in the missing properties with `"linear"`.
* @param {Object.} fromTweenParams
* @param {Object|string|Function} easing
* @return {Object.}
* @private
*/
var composeEasingObject = function composeEasingObject(fromTweenParams) {
var easing = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_EASING;
var composedEasing = {};
var typeofEasing = _typeof(easing);
if (typeofEasing === TYPE_STRING || typeofEasing === TYPE_FUNCTION) {
for (var prop in fromTweenParams) {
composedEasing[prop] = easing;
}
} else {
for (var _prop in fromTweenParams) {
composedEasing[_prop] = easing[_prop] || DEFAULT_EASING;
}
}
return composedEasing;
};
var remove = function remove(tween) {
// Adapted from:
// https://github.com/trekhleb/javascript-algorithms/blob/7c9601df3e8ca4206d419ce50b88bd13ff39deb6/src/data-structures/doubly-linked-list/DoublyLinkedList.js#L73-L121
if (tween === listHead) {
listHead = tween._next;
if (listHead) {
listHead._previous = null;
} else {
listTail = null;
}
} else if (tween === listTail) {
listTail = tween._previous;
if (listTail) {
listTail._next = null;
} else {
listHead = null;
}
} else {
var previousTween = tween._previous;
var nextTween = tween._next;
previousTween._next = nextTween;
nextTween._previous = previousTween;
} // Clean up any references in case the tween is restarted later.
tween._previous = tween._next = null;
};
var Tweenable =
/*#__PURE__*/
function () {
/**
* @param {Object} [initialState={}] The values that the initial tween should
* start at if a `from` value is not provided to {@link
* shifty.Tweenable#tween} or {@link shifty.Tweenable#setConfig}.
* @param {shifty.tweenConfig} [config] Configuration object to be passed to
* {@link shifty.Tweenable#setConfig}.
* @constructs shifty.Tweenable
*/
function Tweenable() {
var initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
_classCallCheck(this, Tweenable);
this._currentState = initialState;
this._configured = false;
this._filters = [];
this._timestamp = null;
this._next = null;
this._previous = null; // To prevent unnecessary calls to setConfig do not set default
// configuration here. Only set default configuration immediately before
// tweening if none has been set.
if (config) {
this.setConfig(config);
}
}
/**
* Applies a filter to Tweenable instance.
* @param {string} filterName The name of the filter to apply.
* @private
*/
_createClass(Tweenable, [{
key: "_applyFilter",
value: function _applyFilter(filterName) {
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = this._filters[Symbol.iterator](), _step2; !(_iteratorNormalCompletion = (_step2 = _iterator.next()).done); _iteratorNormalCompletion = true) {
var filterType = _step2.value;
var filter = filterType[filterName];
if (filter) {
filter(this);
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator["return"] != null) {
_iterator["return"]();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
/**
* Configure and start a tween. If the tween already playing then the
* previous tween will stop and throw an error.
* @method shifty.Tweenable#tween
* @param {shifty.tweenConfig} [config] Gets passed to {@link
* shifty.Tweenable#setConfig}.
* @return {external:Promise}
*/
}, {
key: "tween",
value: function tween() {
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
var _attachment = this._attachment,
_configured = this._configured; // Only set default config if no configuration has been set previously and
// none is provided now.
if (config || !_configured) {
this.setConfig(config);
}
this._pausedAtTime = null;
this._timestamp = Tweenable.now();
this._start(this.get(), _attachment);
return this.resume();
}
/**
* Configure a tween that will start at some point in the future.
* @method shifty.Tweenable#setConfig
* @param {shifty.tweenConfig} [config={}]
* @return {shifty.Tweenable}
*/
}, {
key: "setConfig",
value: function setConfig() {
var _this = this;
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
attachment = _ref.attachment,
_ref$delay = _ref.delay,
delay = _ref$delay === void 0 ? 0 : _ref$delay,
_ref$duration = _ref.duration,
duration = _ref$duration === void 0 ? DEFAULT_DURATION : _ref$duration,
easing = _ref.easing,
from = _ref.from,
_ref$promise = _ref.promise,
promise = _ref$promise === void 0 ? Promise : _ref$promise,
_ref$start = _ref.start,
start = _ref$start === void 0 ? noop : _ref$start,
_ref$step = _ref.step,
step = _ref$step === void 0 ? noop : _ref$step,
to = _ref.to;
this._configured = true; // Attach something to this Tweenable instance (e.g.: a DOM element, an
// object, a string, etc.);
this._attachment = attachment; // Init the internal state
this._isPlaying = false;
this._pausedAtTime = null;
this._scheduleId = null;
this._delay = delay;
this._start = start;
this._step = step;
this._duration = duration;
this._currentState = _objectSpread({}, from || this.get());
this._originalState = this.get();
this._targetState = _objectSpread({}, to || this.get());
var _currentState = this._currentState; // Ensure that there is always something to tween to.
this._targetState = _objectSpread({}, _currentState, {}, this._targetState);
this._easing = composeEasingObject(_currentState, easing);
var filters = Tweenable.filters;
this._filters.length = 0;
for (var name in filters) {
if (filters[name].doesApply(this)) {
this._filters.push(filters[name]);
}
}
this._applyFilter(TWEEN_CREATED);
this._promise = new promise(function (resolve, reject) {
_this._resolve = resolve;
_this._reject = reject;
}); // Needed to silence (harmless) logged errors when a .catch handler is not
// added by downstream code
this._promise["catch"](noop);
return this;
}
/**
* @method shifty.Tweenable#get
* @return {Object} The current state.
*/
}, {
key: "get",
value: function get() {
return _objectSpread({}, this._currentState);
}
/**
* Set the current state.
* @method shifty.Tweenable#set
* @param {Object} state The state to set.
*/
}, {
key: "set",
value: function set(state) {
this._currentState = state;
}
/**
* Pause a tween. Paused tweens can be resumed from the point at which they
* were paused. If a tween is not running, this is a no-op.
* @method shifty.Tweenable#pause
* @return {shifty.Tweenable}
*/
}, {
key: "pause",
value: function pause() {
if (!this._isPlaying) {
return;
}
this._pausedAtTime = Tweenable.now();
this._isPlaying = false;
remove(this);
return this;
}
/**
* Resume a paused tween.
* @method shifty.Tweenable#resume
* @return {external:Promise}
*/
}, {
key: "resume",
value: function resume() {
if (this._timestamp === null) {
return this.tween();
}
if (this._isPlaying) {
return this._promise;
}
var currentTime = Tweenable.now();
if (this._pausedAtTime) {
this._timestamp += currentTime - this._pausedAtTime;
this._pausedAtTime = null;
}
this._isPlaying = true;
if (listHead === null) {
listHead = this;
listTail = this;
scheduleUpdate();
} else {
this._previous = listTail;
listTail._next = this;
listTail = this;
}
return this._promise;
}
/**
* Move the state of the animation to a specific point in the tween's
* timeline. If the animation is not running, this will cause {@link
* shifty.stepFunction} handlers to be called.
* @method shifty.Tweenable#seek
* @param {millisecond} millisecond The millisecond of the animation to seek
* to. This must not be less than `0`.
* @return {shifty.Tweenable}
*/
}, {
key: "seek",
value: function seek(millisecond) {
millisecond = Math.max(millisecond, 0);
var currentTime = Tweenable.now();
if (this._timestamp + millisecond === 0) {
return this;
}
this._timestamp = currentTime - millisecond;
if (!this._isPlaying) {
// If the animation is not running, call processTween to make sure that
// any step handlers are run.
processTween(this, currentTime);
}
return this;
}
/**
* Stops and cancels a tween. If a tween is not running, this is a no-op.
* @param {boolean} [gotoEnd] If `false`, the tween just stops at its current
* state, and the tween promise is not resolved. If `true`, the tweened
* object's values are instantly set to the target values, and the promise is
* resolved.
* @method shifty.Tweenable#stop
* @return {shifty.Tweenable}
*/
}, {
key: "stop",
value: function stop() {
var gotoEnd = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var _attachment = this._attachment,
_currentState = this._currentState,
_easing = this._easing,
_originalState = this._originalState,
_targetState = this._targetState;
if (!this._isPlaying) {
return;
}
this._isPlaying = false;
remove(this);
if (gotoEnd) {
this._applyFilter(BEFORE_TWEEN);
tweenProps(1, _currentState, _originalState, _targetState, 1, 0, _easing);
this._applyFilter(AFTER_TWEEN);
this._applyFilter(AFTER_TWEEN_END);
this._resolve(_currentState, _attachment);
} else {
this._reject({
error: 'stop() executed while tween isPlaying.',
currentState: _currentState,
attachment: _attachment
});
}
return this;
}
/**
* Whether or not a tween is running.
* @method shifty.Tweenable#isPlaying
* @return {boolean}
*/
}, {
key: "isPlaying",
value: function isPlaying() {
return this._isPlaying;
}
/**
* @method shifty.Tweenable#setScheduleFunction
* @param {shifty.scheduleFunction} scheduleFunction
* @deprecated Will be removed in favor of {@link shifty.Tweenable.setScheduleFunction} in 3.0.
*/
}, {
key: "setScheduleFunction",
value: function setScheduleFunction(scheduleFunction) {
Tweenable.setScheduleFunction(scheduleFunction);
}
/**
* `delete` all "own" properties. Call this when the {@link
* shifty.Tweenable} instance is no longer needed to free memory.
* @method shifty.Tweenable#dispose
*/
}, {
key: "dispose",
value: function dispose() {
for (var prop in this) {
delete this[prop];
}
}
}]);
return Tweenable;
}();
/**
* Set a custom schedule function.
*
* By default,
* [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame)
* is used if available, otherwise
* [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/Window.setTimeout)
* is used.
* @method shifty.Tweenable.setScheduleFunction
* @param {shifty.scheduleFunction} fn The function to be
* used to schedule the next frame to be rendered.
* @return {shifty.scheduleFunction} The function that was set.
*/
Tweenable.setScheduleFunction = function (fn) {
return scheduleFunction = fn;
};
Tweenable.formulas = formulas;
/**
* The {@link shifty.filter}s available for use. These filters are
* automatically applied at tween-time by Shifty. You can define your own
* {@link shifty.filter}s and attach them to this object.
* @member shifty.Tweenable.filters
* @type {Object.}
*/
Tweenable.filters = {};
/**
* @method shifty.Tweenable.now
* @static
* @returns {number} The current timestamp.
*/
Tweenable.now = Date.now || function () {
return +new Date();
};
/**
* @method shifty.tween
* @param {shifty.tweenConfig} [config={}]
* @description Standalone convenience method that functions identically to
* {@link shifty.Tweenable#tween}. You can use this to create tweens without
* needing to set up a {@link shifty.Tweenable} instance.
*
* import { tween } from 'shifty';
*
* tween({ from: { x: 0 }, to: { x: 10 } }).then(
* () => console.log('All done!')
* );
*
* @returns {external:Promise}
*/
function tween() {
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var tweenable = new Tweenable();
var promise = tweenable.tween(config);
promise.tweenable = tweenable;
return promise;
}
// CONCATENATED MODULE: ./src/token.js
var R_NUMBER_COMPONENT = /(\d|-|\.)/;
var R_FORMAT_CHUNKS = /([^\-0-9.]+)/g;
var R_UNFORMATTED_VALUES = /[0-9.-]+/g;
var R_RGB = function () {
var number = R_UNFORMATTED_VALUES.source;
var comma = /,\s*/.source;
return new RegExp("rgb\\(".concat(number).concat(comma).concat(number).concat(comma).concat(number, "\\)"), 'g');
}();
var R_RGB_PREFIX = /^.*\(/;
var R_HEX = /#([0-9]|[a-f]){3,6}/gi;
var VALUE_PLACEHOLDER = 'VAL'; // HELPERS
/**
* @param {Array.number} rawValues
* @param {string} prefix
*
* @return {Array.}
* @private
*/
var getFormatChunksFrom = function getFormatChunksFrom(rawValues, prefix) {
return rawValues.map(function (val, i) {
return "_".concat(prefix, "_").concat(i);
});
};
/**
* @param {string} formattedString
*
* @return {string}
* @private
*/
var getFormatStringFrom = function getFormatStringFrom(formattedString) {
var chunks = formattedString.match(R_FORMAT_CHUNKS);
if (!chunks) {
// chunks will be null if there were no tokens to parse in
// formattedString (for example, if formattedString is '2'). Coerce
// chunks to be useful here.
chunks = ['', '']; // If there is only one chunk, assume that the string is a number
// followed by a token...
// NOTE: This may be an unwise assumption.
} else if (chunks.length === 1 || // ...or if the string starts with a number component (".", "-", or a
// digit)...
formattedString.charAt(0).match(R_NUMBER_COMPONENT)) {
// ...prepend an empty string here to make sure that the formatted number
// is properly replaced by VALUE_PLACEHOLDER
chunks.unshift('');
}
return chunks.join(VALUE_PLACEHOLDER);
};
/**
* Convert a base-16 number to base-10.
*
* @param {number|string} hex The value to convert.
*
* @returns {number} The base-10 equivalent of `hex`.
* @private
*/
function hexToDec(hex) {
return parseInt(hex, 16);
}
/**
* Convert a hexadecimal string to an array with three items, one each for
* the red, blue, and green decimal values.
*
* @param {string} hex A hexadecimal string.
*
* @returns {Array.} The converted Array of RGB values if `hex` is a
* valid string, or an Array of three 0's.
* @private
*/
var hexToRGBArray = function hexToRGBArray(hex) {
hex = hex.replace(/#/, ''); // If the string is a shorthand three digit hex notation, normalize it to
// the standard six digit notation
if (hex.length === 3) {
hex = hex.split('');
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
}
return [hexToDec(hex.substr(0, 2)), hexToDec(hex.substr(2, 2)), hexToDec(hex.substr(4, 2))];
};
/**
* @param {string} hexString
*
* @return {string}
* @private
*/
var convertHexToRGB = function convertHexToRGB(hexString) {
return "rgb(".concat(hexToRGBArray(hexString).join(','), ")");
};
/**
* TODO: Can this be rewritten to leverage String#replace more efficiently?
* Runs a filter operation on all chunks of a string that match a RegExp.
*
* @param {RegExp} pattern
* @param {string} unfilteredString
* @param {function(string)} filter
*
* @return {string}
* @private
*/
var filterStringChunks = function filterStringChunks(pattern, unfilteredString, filter) {
var patternMatches = unfilteredString.match(pattern);
var filteredString = unfilteredString.replace(pattern, VALUE_PLACEHOLDER);
if (patternMatches) {
patternMatches.forEach(function (match) {
return filteredString = filteredString.replace(VALUE_PLACEHOLDER, filter(match));
});
}
return filteredString;
};
/**
* @param {string} str
*
* @return {string}
* @private
*/
var sanitizeHexChunksToRGB = function sanitizeHexChunksToRGB(str) {
return filterStringChunks(R_HEX, str, convertHexToRGB);
};
/**
* Convert all hex color values within a string to an rgb string.
*
* @param {Object} stateObject
* @private
*/
var sanitizeObjectForHexProps = function sanitizeObjectForHexProps(stateObject) {
for (var prop in stateObject) {
var currentProp = stateObject[prop];
if (typeof currentProp === 'string' && currentProp.match(R_HEX)) {
stateObject[prop] = sanitizeHexChunksToRGB(currentProp);
}
}
};
/**
* @param {string} rgbChunk
*
* @return {string}
* @private
*/
var sanitizeRGBChunk = function sanitizeRGBChunk(rgbChunk) {
var numbers = rgbChunk.match(R_UNFORMATTED_VALUES).map(Math.floor);
var prefix = rgbChunk.match(R_RGB_PREFIX)[0];
return "".concat(prefix).concat(numbers.join(','), ")");
};
/**
* Check for floating point values within rgb strings and round them.
*
* @param {string} formattedString
*
* @return {string}
* @private
*/
var sanitizeRGBChunks = function sanitizeRGBChunks(formattedString) {
return filterStringChunks(R_RGB, formattedString, sanitizeRGBChunk);
};
/**
* Note: It's the duty of the caller to convert the Array elements of the
* return value into numbers. This is a performance optimization.
*
* @param {string} formattedString
*
* @return {Array.|null}
* @private
*/
var getValuesFrom = function getValuesFrom(formattedString) {
return formattedString.match(R_UNFORMATTED_VALUES);
};
/**
* @param {Object} stateObject
*
* @return {Object} An Object of formatSignatures that correspond to
* the string properties of stateObject.
* @private
*/
var getFormatSignatures = function getFormatSignatures(stateObject) {
var signatures = {};
for (var propertyName in stateObject) {
var property = stateObject[propertyName];
if (typeof property === 'string') {
signatures[propertyName] = {
formatString: getFormatStringFrom(property),
chunkNames: getFormatChunksFrom(getValuesFrom(property), propertyName)
};
}
}
return signatures;
};
/**
* @param {Object} stateObject
* @param {Object} formatSignatures
* @private
*/
var expandFormattedProperties = function expandFormattedProperties(stateObject, formatSignatures) {
var _loop = function _loop(propertyName) {
getValuesFrom(stateObject[propertyName]).forEach(function (number, i) {
return stateObject[formatSignatures[propertyName].chunkNames[i]] = +number;
});
delete stateObject[propertyName];
};
for (var propertyName in formatSignatures) {
_loop(propertyName);
}
};
/**
* @param {Object} stateObject
* @param {Array.} chunkNames
*
* @return {Object} The extracted value chunks.
* @private
*/
var extractPropertyChunks = function extractPropertyChunks(stateObject, chunkNames) {
var extractedValues = {};
chunkNames.forEach(function (chunkName) {
extractedValues[chunkName] = stateObject[chunkName];
delete stateObject[chunkName];
});
return extractedValues;
};
/**
* @param {Object} stateObject
* @param {Array.} chunkNames
*
* @return {Array.}
* @private
*/
var getValuesList = function getValuesList(stateObject, chunkNames) {
return chunkNames.map(function (chunkName) {
return stateObject[chunkName];
});
};
/**
* @param {string} formatString
* @param {Array.} rawValues
*
* @return {string}
* @private
*/
var getFormattedValues = function getFormattedValues(formatString, rawValues) {
rawValues.forEach(function (rawValue) {
return formatString = formatString.replace(VALUE_PLACEHOLDER, +rawValue.toFixed(4));
});
return formatString;
};
/**
* @param {Object} stateObject
* @param {Object} formatSignatures
* @private
*/
var collapseFormattedProperties = function collapseFormattedProperties(stateObject, formatSignatures) {
for (var prop in formatSignatures) {
var _formatSignatures$pro = formatSignatures[prop],
chunkNames = _formatSignatures$pro.chunkNames,
formatString = _formatSignatures$pro.formatString;
var currentProp = getFormattedValues(formatString, getValuesList(extractPropertyChunks(stateObject, chunkNames), chunkNames));
stateObject[prop] = sanitizeRGBChunks(currentProp);
}
};
/**
* @param {Object} easingObject
* @param {Object} tokenData
* @private
*/
var expandEasingObject = function expandEasingObject(easingObject, tokenData) {
var _loop2 = function _loop2(prop) {
var chunkNames = tokenData[prop].chunkNames;
var easing = easingObject[prop];
if (typeof easing === 'string') {
var easingNames = easing.split(' ');
var defaultEasing = easingNames[easingNames.length - 1];
chunkNames.forEach(function (chunkName, i) {
return easingObject[chunkName] = easingNames[i] || defaultEasing;
});
} else {
// easing is a function
chunkNames.forEach(function (chunkName) {
return easingObject[chunkName] = easing;
});
}
delete easingObject[prop];
};
for (var prop in tokenData) {
_loop2(prop);
}
};
/**
* @param {Object} easingObject
* @param {Object} tokenData
* @private
*/
var collapseEasingObject = function collapseEasingObject(easingObject, tokenData) {
for (var prop in tokenData) {
var chunkNames = tokenData[prop].chunkNames;
var firstEasing = easingObject[chunkNames[0]];
if (typeof firstEasing === 'string') {
easingObject[prop] = chunkNames.map(function (chunkName) {
var easingName = easingObject[chunkName];
delete easingObject[chunkName];
return easingName;
}).join(' ');
} else {
// firstEasing is a function
easingObject[prop] = firstEasing;
}
}
};
var doesApply = function doesApply(_ref) {
var _currentState = _ref._currentState;
return Object.keys(_currentState).some(function (key) {
return typeof _currentState[key] === 'string';
});
};
function tweenCreated(tweenable) {
var _currentState = tweenable._currentState,
_originalState = tweenable._originalState,
_targetState = tweenable._targetState;
[_currentState, _originalState, _targetState].forEach(sanitizeObjectForHexProps);
tweenable._tokenData = getFormatSignatures(_currentState);
}
function beforeTween(tweenable) {
var _currentState = tweenable._currentState,
_originalState = tweenable._originalState,
_targetState = tweenable._targetState,
_easing = tweenable._easing,
_tokenData = tweenable._tokenData;
expandEasingObject(_easing, _tokenData);
[_currentState, _originalState, _targetState].forEach(function (state) {
return expandFormattedProperties(state, _tokenData);
});
}
function afterTween(tweenable) {
var _currentState = tweenable._currentState,
_originalState = tweenable._originalState,
_targetState = tweenable._targetState,
_easing = tweenable._easing,
_tokenData = tweenable._tokenData;
[_currentState, _originalState, _targetState].forEach(function (state) {
return collapseFormattedProperties(state, _tokenData);
});
collapseEasingObject(_easing, _tokenData);
}
// CONCATENATED MODULE: ./src/interpolate.js
function interpolate_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function interpolate_objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { interpolate_ownKeys(Object(source), true).forEach(function (key) { interpolate_defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { interpolate_ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function interpolate_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
// Fake a Tweenable and patch some internals. This approach allows us to
// skip uneccessary processing and object recreation, cutting down on garbage
// collection pauses.
var mockTweenable = new Tweenable();
var filters = Tweenable.filters;
/**
* Compute the midpoint of two Objects. This method effectively calculates a
* specific frame of animation that {@link shifty.Tweenable#tween} does many times
* over the course of a full tween.
*
* import { interpolate } from 'shifty';
*
* const interpolatedValues = interpolate({
* width: '100px',
* opacity: 0,
* color: '#fff'
* }, {
* width: '200px',
* opacity: 1,
* color: '#000'
* },
* 0.5
* );
*
* console.log(interpolatedValues); // Logs: {opacity: 0.5, width: "150px", color: "rgb(127,127,127)"}
*
* @method shifty.interpolate
* @param {Object} from The starting values to tween from.
* @param {Object} to The ending values to tween to.
* @param {number} position The normalized position value (between `0.0` and
* `1.0`) to interpolate the values between `from` and `to` for. `from`
* represents `0` and `to` represents `1`.
* @param {Object.|string|shifty.easingFunction}
* easing The easing curve(s) to calculate the midpoint against. You can
* reference any easing function attached to {@link shifty.Tweenable.formulas},
* or provide the {@link shifty.easingFunction}(s) directly. If omitted, this
* defaults to "linear".
* @param {number} [delay=0] Optional delay to pad the beginning of the
* interpolated tween with. This increases the range of `position` from (`0`
* through `1`) to (`0` through `1 + delay`). So, a delay of `0.5` would
* increase all valid values of `position` to numbers between `0` and `1.5`.
* @return {Object}
*/
var interpolate_interpolate = function interpolate(from, to, position, easing) {
var delay = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
var current = interpolate_objectSpread({}, from);
var easingObject = composeEasingObject(from, easing);
mockTweenable._filters.length = 0;
mockTweenable.set({});
mockTweenable._currentState = current;
mockTweenable._originalState = from;
mockTweenable._targetState = to;
mockTweenable._easing = easingObject;
for (var name in filters) {
if (filters[name].doesApply(mockTweenable)) {
mockTweenable._filters.push(filters[name]);
}
} // Any defined value transformation must be applied
mockTweenable._applyFilter('tweenCreated');
mockTweenable._applyFilter('beforeTween');
var interpolatedValues = tweenProps(position, current, from, to, 1, delay, easingObject); // Transform data in interpolatedValues back into its original format
mockTweenable._applyFilter('afterTween');
return interpolatedValues;
};
// CONCATENATED MODULE: ./src/scene.js
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
function scene_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function scene_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function scene_createClass(Constructor, protoProps, staticProps) { if (protoProps) scene_defineProperties(Constructor.prototype, protoProps); if (staticProps) scene_defineProperties(Constructor, staticProps); return Constructor; }
function _classPrivateFieldGet(receiver, privateMap) { var descriptor = privateMap.get(receiver); if (!descriptor) { throw new TypeError("attempted to get private field on non-instance"); } if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
var Scene =
/*#__PURE__*/
function () {
/**
* The {@link shifty.Scene} class provides a way to control groups of {@link
* shifty.Tweenable}s. It is lightweight, minimalistic, and meant to provide
* performant {@link shifty.Tweenable} batch control that users of Shifty
* might otherwise have to implement themselves. It is **not** a robust
* timeline solution, and it does **not** provide utilities for sophisticated
* animation sequencing or orchestration. If that is what you need for your
* project, consider using a more robust tool such as
* [Rekapi](http://jeremyckahn.github.io/rekapi/doc/) (a timeline layer built
* on top of Shifty).
*
* Please be aware that {@link shifty.Scene} does **not** perform any
* automatic cleanup. If you want to remove a {@link shifty.Tweenable} from a
* {@link shifty.Scene}, you must do so explicitly with either {@link
* shifty.Scene#remove} or {@link shifty.Scene#empty}.
*
*
* See the Pen
* Shifty Scene Demo by Jeremy Kahn (@jeremyckahn)
* on CodePen.
*
*
* @param {...shifty.Tweenable} tweenables
* @see https://codepen.io/jeremyckahn/pen/qvZKbe
* @constructs shifty.Scene
*/
function Scene() {
scene_classCallCheck(this, Scene);
_tweenables.set(this, {
writable: true,
value: []
});
for (var _len = arguments.length, tweenables = new Array(_len), _key = 0; _key < _len; _key++) {
tweenables[_key] = arguments[_key];
}
tweenables.forEach(this.add.bind(this));
}
/**
* A copy of the internal {@link shifty.Tweenable}s array.
* @member shifty.Scene#tweenables
* @type {Array.}
* @readonly
*/
scene_createClass(Scene, [{
key: "add",
/**
* Add a {@link shifty.Tweenable} to be controlled by this {@link
* shifty.Scene}.
* @method shifty.Scene#add
* @param {shifty.Tweenable} tweenable
* @return {shifty.Tweenable} The {@link shifty.Tweenable} that was added.
*/
value: function add(tweenable) {
_classPrivateFieldGet(this, _tweenables).push(tweenable);
return tweenable;
}
/**
* Remove a {@link shifty.Tweenable} that is controlled by this {@link
* shifty.Scene}.
* @method shifty.Scene#remove
* @param {shifty.Tweenable} tweenable
* @return {shifty.Tweenable} The {@link shifty.Tweenable} that was removed.
*/
}, {
key: "remove",
value: function remove(tweenable) {
var index = _classPrivateFieldGet(this, _tweenables).indexOf(tweenable);
if (~index) {
_classPrivateFieldGet(this, _tweenables).splice(index, 1);
}
return tweenable;
}
/**
* [Remove]{@link shifty.Scene#remove} all {@link shifty.Tweenable}s in this {@link
* shifty.Scene}.
* @method shifty.Scene#empty
* @return {Array.} The {@link shifty.Tweenable}s that were
* removed.
*/
}, {
key: "empty",
value: function empty() {
// Deliberate of the tweenables getter here to create a temporary array
return this.tweenables.map(this.remove.bind(this));
}
/**
* Is `true` if any {@link shifty.Tweenable} in this {@link shifty.Scene} is
* playing.
* @method shifty.Scene#isPlaying
* @return {boolean}
*/
}, {
key: "isPlaying",
value: function isPlaying() {
return _classPrivateFieldGet(this, _tweenables).some(function (tweenable) {
return tweenable.isPlaying();
});
}
/**
* Play all {@link shifty.Tweenable}s from their beginning.
* @method shifty.Scene#play
* @return {shifty.Scene}
*/
}, {
key: "play",
value: function play() {
_classPrivateFieldGet(this, _tweenables).forEach(function (tweenable) {
return tweenable.tween();
});
return this;
}
/**
* {@link shifty.Tweenable#pause} all {@link shifty.Tweenable}s in this
* {@link shifty.Scene}.
* @method shifty.Scene#pause
* @return {shifty.Scene}
*/
}, {
key: "pause",
value: function pause() {
_classPrivateFieldGet(this, _tweenables).forEach(function (tweenable) {
return tweenable.pause();
});
return this;
}
/**
* {@link shifty.Tweenable#resume} all paused {@link shifty.Tweenable}s.
* @method shifty.Scene#resume
* @return {shifty.Scene}
*/
}, {
key: "resume",
value: function resume() {
_classPrivateFieldGet(this, _tweenables).forEach(function (tweenable) {
return tweenable.resume();
});
return this;
}
/**
* {@link shifty.Tweenable#stop} all {@link shifty.Tweenable}s in this {@link
* shifty.Scene}.
* @method shifty.Scene#stop
* @param {boolean} [gotoEnd]
* @return {shifty.Scene}
*/
}, {
key: "stop",
value: function stop(gotoEnd) {
_classPrivateFieldGet(this, _tweenables).forEach(function (tweenable) {
return tweenable.stop(gotoEnd);
});
return this;
}
}, {
key: "tweenables",
get: function get() {
return _toConsumableArray(_classPrivateFieldGet(this, _tweenables));
}
/**
* The {@link external:Promise}s for all {@link shifty.Tweenable}s in this
* {@link shifty.Scene} that have been configured with {@link
* shifty.Tweenable#setConfig}. Note that each call of {@link
* shifty.Scene#play} or {@link shifty.Scene#pause} creates new {@link
* external:Promise}s:
*
* const scene = new Scene(new Tweenable());
* scene.play();
*
* Promise.all(scene.promises).then(() =>
* // Plays the scene again upon completion, but a new promise is
* // created so this line only runs once.
* scene.play()
* );
*
* @member shifty.Scene#promises
* @type {Array.}
* @readonly
*/
}, {
key: "promises",
get: function get() {
return _classPrivateFieldGet(this, _tweenables).map(function (_ref) {
var _promise = _ref._promise;
return _promise;
});
}
}]);
return Scene;
}();
var _tweenables = new WeakMap();
// CONCATENATED MODULE: ./src/bezier.js
/**
* The Bezier magic in this file is adapted/copied almost wholesale from
* [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/cubic-bezier.js),
* which was adapted from Apple code (which probably came from
* [here](http://opensource.apple.com/source/WebCore/WebCore-955.66/platform/graphics/UnitBezier.h)).
* Special thanks to Apple and Thomas Fuchs for much of this code.
*/
/**
* Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder(s) nor the names of any
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
// port of webkit cubic bezier handling by http://www.netzgesta.de/dev/
/**
* @param {number} t
* @param {number} p1x
* @param {number} p1y
* @param {number} p2x
* @param {number} p2y
* @param {number} duration
* @returns {Function}
* @private
*/
function cubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {
var ax = 0,
bx = 0,
cx = 0,
ay = 0,
by = 0,
cy = 0;
var sampleCurveX = function sampleCurveX(t) {
return ((ax * t + bx) * t + cx) * t;
};
var sampleCurveY = function sampleCurveY(t) {
return ((ay * t + by) * t + cy) * t;
};
var sampleCurveDerivativeX = function sampleCurveDerivativeX(t) {
return (3 * ax * t + 2 * bx) * t + cx;
};
var solveEpsilon = function solveEpsilon(duration) {
return 1 / (200 * duration);
};
var fabs = function fabs(n) {
return n >= 0 ? n : 0 - n;
};
var solveCurveX = function solveCurveX(x, epsilon) {
var t0, t1, t2, x2, d2, i;
for (t2 = x, i = 0; i < 8; i++) {
x2 = sampleCurveX(t2) - x;
if (fabs(x2) < epsilon) {
return t2;
}
d2 = sampleCurveDerivativeX(t2);
if (fabs(d2) < 1e-6) {
break;
}
t2 = t2 - x2 / d2;
}
t0 = 0;
t1 = 1;
t2 = x;
if (t2 < t0) {
return t0;
}
if (t2 > t1) {
return t1;
}
while (t0 < t1) {
x2 = sampleCurveX(t2);
if (fabs(x2 - x) < epsilon) {
return t2;
}
if (x > x2) {
t0 = t2;
} else {
t1 = t2;
}
t2 = (t1 - t0) * 0.5 + t0;
}
return t2; // Failure.
};
var solve = function solve(x, epsilon) {
return sampleCurveY(solveCurveX(x, epsilon));
};
cx = 3 * p1x;
bx = 3 * (p2x - p1x) - cx;
ax = 1 - cx - bx;
cy = 3 * p1y;
by = 3 * (p2y - p1y) - cy;
ay = 1 - cy - by;
return solve(t, solveEpsilon(duration));
} // End ported code
/**
* GetCubicBezierTransition(x1, y1, x2, y2) -> Function.
*
* Generates a transition easing function that is compatible
* with WebKit's CSS transitions `-webkit-transition-timing-function`
* CSS property.
*
* The W3C has more information about CSS3 transition timing functions:
* http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag
*
* @param {number} x1
* @param {number} y1
* @param {number} x2
* @param {number} y2
* @return {Function}
* @private
*/
var getCubicBezierTransition = function getCubicBezierTransition(x1, y1, x2, y2) {
return function (pos) {
return cubicBezierAtTime(pos, x1, y1, x2, y2, 1);
};
};
/**
* Create a Bezier easing function and attach it to {@link
* shifty.Tweenable.formulas}. This function gives you total control over the
* easing curve. Matthew Lein's [Ceaser](http://matthewlein.com/ceaser/) is a
* useful tool for visualizing the curves you can make with this function.
* @method shifty.setBezierFunction
* @param {string} name The name of the easing curve. Overwrites the old
* easing function on {@link shifty.Tweenable.formulas} if it exists.
* @param {number} x1
* @param {number} y1
* @param {number} x2
* @param {number} y2
* @return {shifty.easingFunction} The {@link shifty.easingFunction} that was
* attached to {@link shifty.Tweenable.formulas}.
*/
var bezier_setBezierFunction = function setBezierFunction(name, x1, y1, x2, y2) {
var cubicBezierTransition = getCubicBezierTransition(x1, y1, x2, y2);
cubicBezierTransition.displayName = name;
cubicBezierTransition.x1 = x1;
cubicBezierTransition.y1 = y1;
cubicBezierTransition.x2 = x2;
cubicBezierTransition.y2 = y2;
return Tweenable.formulas[name] = cubicBezierTransition;
};
/**
* `delete` an easing function from {@link shifty.Tweenable.formulas}. Be
* careful with this method, as it `delete`s whatever easing formula matches
* `name` (which means you can delete standard Shifty easing functions).
* @method shifty.unsetBezierFunction
* @param {string} name The name of the easing function to delete.
* @return {boolean} Whether or not the functions was `delete`d.
*/
var bezier_unsetBezierFunction = function unsetBezierFunction(name) {
return delete Tweenable.formulas[name];
};
// CONCATENATED MODULE: ./src/index.js
/* concated harmony reexport processTweens */__webpack_require__.d(__webpack_exports__, "processTweens", function() { return processTweens; });
/* concated harmony reexport Tweenable */__webpack_require__.d(__webpack_exports__, "Tweenable", function() { return Tweenable; });
/* concated harmony reexport tween */__webpack_require__.d(__webpack_exports__, "tween", function() { return tween; });
/* concated harmony reexport interpolate */__webpack_require__.d(__webpack_exports__, "interpolate", function() { return interpolate_interpolate; });
/* concated harmony reexport Scene */__webpack_require__.d(__webpack_exports__, "Scene", function() { return Scene; });
/* concated harmony reexport setBezierFunction */__webpack_require__.d(__webpack_exports__, "setBezierFunction", function() { return bezier_setBezierFunction; });
/* concated harmony reexport unsetBezierFunction */__webpack_require__.d(__webpack_exports__, "unsetBezierFunction", function() { return bezier_unsetBezierFunction; });
/**
* @namespace shifty
*/
Tweenable.filters.token = token_namespaceObject;
/**
* @external Promise
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise}
*/
/**
* @callback {Function} shifty.easingFunction
* @param {number} position The normalized (0-1) position of the tween.
* @return {number} The curve-adjusted value.
*/
/**
* @callback {Function} shifty.startFunction
* @param {Object} state The current state of the tween.
* @param {Object} [attachment] Cached data provided from a {@link
* shifty.tweenConfig}.
*/
/**
* Gets called for every tick of the tween. This function is not called on the
* final step of the animation.
* @callback {Function} shifty.stepFunction
* @param {Object} state The current state of the tween.
* @param {Object|undefined} attachment Cached data provided from a {@link
* shifty.tweenConfig}.
* @param {number} timeElapsed The time elapsed since the start of the tween.
*/
/**
* @callback shifty.scheduleFunction
* @param {Function} callback
* @param {number} timeout
*/
/**
* @typedef {Object} shifty.tweenConfig
* @property {Object} [from] Starting position. If omitted, {@link
* shifty.Tweenable#get} is used.
* @property {Object} [to] Ending position. The keys of this Object should
* match those of `to`.
* @property {number} [duration] How many milliseconds to animate for.
* @property {number} [delay] How many milliseconds to wait before starting the
* tween.
* @property {shifty.startFunction} [start] Executes when the tween begins.
* @property {shifty.stepFunction} [step] Executes on every tick.
* @property
* {Object.|string|shifty.easingFunction}
* [easing] Easing curve name(s) or {@link shifty.easingFunction}(s) to apply
* to the properties of the tween. If this is an Object, the keys should
* correspond to `to`/`from`. You can learn more about this in the {@tutorial
* easing-function-in-depth} tutorial.
* @property {Object} [attachment] Cached value that is passed to {@link
* shifty.startFunction}/{@link shifty.stepFunction}.
* @property {Function} [promise] Promise constructor for when you want
* to use Promise library or polyfill Promises in unsupported environments.
*/
/**
* Is called when a tween is created to determine if a filter is needed.
* Filters are only added to a tween when it is created so that they are not
* unnecessarily processed if they don't apply during an update tick.
* @callback {Function} shifty.doesApplyFilter
* @param {shifty.Tweenable} tweenable The {@link shifty.Tweenable} instance.
* @return {boolean}
*/
/**
* Is called when a tween is created. This should perform any setup needed by
* subsequent per-tick calls to {@link shifty.beforeTween} and {@link
* shifty.afterTween}.
* @callback {Function} shifty.tweenCreatedFilter
* @param {shifty.Tweenable} tweenable The {@link shifty.Tweenable} instance.
*/
/**
* Is called right before a tween is processed in a tick.
* @callback {Function} shifty.beforeTweenFilter
* @param {shifty.Tweenable} tweenable The {@link shifty.Tweenable} instance.
*/
/**
* Is called right after a tween is processed in a tick.
* @callback {Function} shifty.afterTweenFilter
* @param {shifty.Tweenable} tweenable The {@link shifty.Tweenable} instance.
*/
/**
* An Object that contains functions that are called at key points in a tween's
* lifecycle. Shifty can only process `Number`s internally, but filters can
* expand support for any type of data. This is the mechanism that powers
* [string interpolation]{@tutorial string-interpolation}.
* @typedef {Object} shifty.filter
* @property {shifty.doesApplyFilter} doesApply Is called when a tween is
* created.
* @property {shifty.tweenCreatedFilter} tweenCreated Is called when a tween is
* created.
* @property {shifty.beforeTweenFilter} beforeTween Is called right before a
* tween starts.
* @property {shifty.afterTweenFilter} afterTween Is called right after a tween
* ends.
*/
/***/ })
/******/ ]);
});
//# sourceMappingURL=shifty.node.js.map