UNPKG

spiritjs

Version:

The animation toolkit for the web

234 lines (223 loc) 9.53 kB
"use strict"; exports.__esModule = true; exports.ensure = ensure; exports.generateTimeline = generateTimeline; exports.has = has; exports.isGSAPInstance = isGSAPInstance; exports.isGSAPTimeline = isGSAPTimeline; exports.killTimeline = killTimeline; exports.loadFromCDN = loadFromCDN; exports.transformOrigins = transformOrigins; var _config = _interopRequireDefault(require("../config/config")); var _loadscript = _interopRequireDefault(require("./loadscript")); var _timeline = _interopRequireDefault(require("../group/timeline")); var _debug = _interopRequireDefault(require("./debug")); var _is = require("./is"); var _context = require("./context"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; } function _createForOfIteratorHelperLoose(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (t) return (t = t.call(r)).next.bind(t); if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var o = 0; return function () { return o >= r.length ? { done: !0 } : { done: !1, value: r[o++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /** * Check on GSAP presence * * @returns {boolean} */ function has() { return isGSAPInstance(_config["default"].gsap.instance); } /** * Ensure GSAP is loaded * Auto inject * * @returns {Promise<void>} */ function ensure() { if (has()) { return Promise.resolve(); } if ((0, _context.isBrowser)() && isGSAPInstance(window.gsap)) { _config["default"].gsap.instance = window.gsap; return Promise.resolve(); } // load from cdn if (!_config["default"].gsap.autoInject) { if ((0, _debug["default"])()) { console.warn("\n\n It seems that you've disabled autoInject. GSAP cannot be found or loaded by Spirit.\n Please make sure you provide the tween and timeline to Spirit:\n\n spirit.setup({\n tween: TweenMax,\n timeline: TimelineMax\n })\n\n Or enable the autoInject \"spirit.config.gsap.autoInject = true\".\n\n "); } return Promise.reject(new Error('GSAP not found.')); } if ((0, _debug["default"])()) { console.warn("\n\n GSAP is being fetched from CDN: " + _config["default"].gsap.autoInjectUrl + ".\n If you already have GSAP installed, please provide it to Spirit:\n\n spirit.setup(gsap)\n\n You want to use another cdn? Change it here:\n\n spirit.config.gsap.autoInjectUrl = 'https://cdn.xxx'\n\n "); } return this.loadFromCDN(); } /** * Load GSAP from CDN based on autoInjectUrl * * @return {Promise<void>} */ function loadFromCDN() { return (0, _loadscript["default"])(_config["default"].gsap.autoInjectUrl).then(function () { if (!isGSAPInstance(window.gsap)) { return Promise.reject(new Error('GSAP could not be loaded from CDN: ' + _config["default"].gsap.autoInjectUrl)); } _config["default"].gsap.instance = window.gsap; return Promise.resolve(); })["catch"](function (err) { return Promise.reject(err); }); } /** * Get transform origins for timeline * * @param {Timeline} timeline * @return {Function} */ function transformOrigins(timeline) { var prop = timeline.props.get('transformOrigin'); var origins = prop && prop.keyframes.list.map(function (k) { return { time: k.time, value: k.value }; }) || []; // add start 50% 50% ? if (origins.length > 0 && origins[0].time !== 0 || origins.length === 0) { origins.unshift({ time: 0, value: '50% 50%' }); } var current = origins.shift(); var next, getVal; getVal = function getVal() { return { current: current, next: next }; }; next = function next() { current = origins && origins.length > 0 && origins.shift() || null; return getVal(); }; return getVal(); } /** * Generate timeline from data * * @param {Timeline} timeline * @returns {TimelineMax|TimelineLite} */ function generateTimeline(timeline) { if (!timeline || !(timeline instanceof _timeline["default"])) { throw new Error('Need valid timeline data to generate GSAP timeline from'); } if (timeline.type !== 'dom') { throw new Error('Timeline invalid. Needs a timeline with type of dom.'); } if (!has()) { throw new Error('GSAP not set. Please make sure GSAP is available.'); } // create new timeline var tl = _config["default"].gsap.instance.timeline({ paused: true }); // eslint-disable-line new-cap var origins = transformOrigins(timeline); var origin = origins.current; timeline.props.each(function (prop) { if (prop.keyframes.length === 0 || prop.name === 'transformOrigin' || prop.name === 'svgOrigin') { return; } var keyframe = prop.keyframes.at(0); while (keyframe) { var _property; var _keyframe = keyframe, value = _keyframe.value, ease = _keyframe.ease, time = _keyframe.time; var prev = keyframe.prev(); var start = prev ? prev.time : 0; var duration = prev ? time - prev.time : time; var props = { ease: ease || 'none' }; var property = (_property = {}, _property[prop.name] = value, _property); // parse dots into recursive object if (/\./.test(prop.name)) { var segments = prop.name.split('.'); var last = segments.pop(); var obj = {}; var o = obj; while (segments.length > 0) { var segment = segments.shift(); obj[segment] = {}; obj = obj[segment]; } obj[last] = value; property = o; } props = _objectSpread(_objectSpread(_objectSpread({}, props), property), {}, { duration: duration }); if (time === 0) { props.immediateRender = true; } if (prop.isCSSTransform() && origin && time >= origin.time) { props.transformOrigin = origin.value; origin = origins.next().current; } tl.to(timeline.transformObject, props, start); keyframe = keyframe.next(); } }); return tl; } /** * Recursively kill timeline * Reset props on targets * * @param {TimelineMax|TimelineLite} gsapTimeline */ function killTimeline(gsapTimeline) { if (isGSAPTimeline(gsapTimeline)) { if (gsapTimeline.eventCallback) { gsapTimeline.eventCallback('onComplete', null); gsapTimeline.eventCallback('onUpdate', null); gsapTimeline.eventCallback('onStart', null); gsapTimeline.eventCallback('onReverseComplete', null); gsapTimeline.eventCallback('onRepeat', null); } var targets = gsapTimeline.getChildren ? gsapTimeline.getChildren() : []; gsapTimeline.kill(); for (var i = 0; i < targets.length; i++) { if (targets[i]._targets) { for (var _iterator = _createForOfIteratorHelperLoose(targets[i]._targets), _step; !(_step = _iterator()).done;) { var el = _step.value; _config["default"].gsap.instance.set(el, { clearProps: 'all' }); delete el._gsap; } } if (isGSAPTimeline(targets[i])) { killTimeline(targets[i]); } } if (gsapTimeline.clear) { gsapTimeline.clear(); } } return gsapTimeline; } function isGSAPTimeline(timeline) { return timeline && _config["default"].gsap.instance && timeline instanceof _config["default"].gsap.instance.core.Animation; } function isGSAPInstance(n) { return (0, _is.isObject)(n) && (0, _is.isFunction)(n.to) && (0, _is.isFunction)(n.timeline); }