spiritjs
Version:
The animation toolkit for the web
234 lines (223 loc) • 9.53 kB
JavaScript
;
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);
}