vendor/assets/javascripts/greensock/TweenMax.js in greensock-rails-1.20.2.0 vs vendor/assets/javascripts/greensock/TweenMax.js in greensock-rails-1.20.3.0
- old
+ new
@@ -1,8 +1,8 @@
/*!
- * VERSION: 1.20.2
- * DATE: 2017-06-30
+ * VERSION: 1.20.3
+ * DATE: 2017-10-02
* UPDATES AND DOCS AT: http://greensock.com
*
* Includes all of the following: TweenLite, TweenMax, TimelineLite, TimelineMax, EasePack, CSSPlugin, RoundPropsPlugin, BezierPlugin, AttrPlugin, DirectionalRotationPlugin
*
* @license Copyright (c) 2008-2017, GreenSock. All rights reserved.
@@ -38,21 +38,23 @@
TweenLite.call(this, target, duration, vars);
this._cycle = 0;
this._yoyo = (this.vars.yoyo === true || !!this.vars.yoyoEase);
this._repeat = this.vars.repeat || 0;
this._repeatDelay = this.vars.repeatDelay || 0;
- this._dirty = true; //ensures that if there is any repeat, the totalDuration will get recalculated to accurately report it.
+ if (this._repeat) {
+ this._uncache(true); //ensures that if there is any repeat, the totalDuration will get recalculated to accurately report it.
+ }
this.render = TweenMax.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method)
},
_tinyNum = 0.0000000001,
TweenLiteInternals = TweenLite._internals,
_isSelector = TweenLiteInternals.isSelector,
_isArray = TweenLiteInternals.isArray,
p = TweenMax.prototype = TweenLite.to({}, 0.1, {}),
_blankArray = [];
- TweenMax.version = "1.20.2";
+ TweenMax.version = "1.20.3";
p.constructor = TweenMax;
p.kill()._gc = false;
TweenMax.killTweensOf = TweenMax.killDelayedCallsTo = TweenLite.killTweensOf;
TweenMax.getTweensOf = TweenLite.getTweensOf;
TweenMax.lagSmoothing = TweenLite.lagSmoothing;
@@ -283,11 +285,11 @@
//this.invalidate();
this._init(); //will just apply overwriting since _initted of (2) means it was a from() tween that had immediateRender:true
}
if (this._startAt) {
if (time >= 0) {
- this._startAt.render(time, suppressEvents, force);
+ this._startAt.render(time, true, force);
} else if (!callback) {
callback = "_dummyGS"; //if no callback is defined, use a dummy value just so that the condition at the end evaluates as true because _startAt should render AFTER the normal render loop when the time is negative. We could handle this in a more intuitive way, of course, but the render loop is the MOST important thing to optimize, so this technique allows us to avoid adding extra conditional logic in a high-frequency area.
}
}
if (this.vars.onStart) if (this._totalTime !== 0 || duration === 0) if (!suppressEvents) {
@@ -305,22 +307,22 @@
pt = pt._next;
}
if (this._onUpdate) {
if (time < 0) if (this._startAt && this._startTime) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
- this._startAt.render(time, suppressEvents, force); //note: for performance reasons, we tuck this conditional logic inside less traveled areas (most tweens don't have an onUpdate). We'd just have it at the end before the onComplete, but the values should be updated before any onUpdate is called, so we ALSO put it here and then if it's not called, we do so later near the onComplete.
+ this._startAt.render(time, true, force); //note: for performance reasons, we tuck this conditional logic inside less traveled areas (most tweens don't have an onUpdate). We'd just have it at the end before the onComplete, but the values should be updated before any onUpdate is called, so we ALSO put it here and then if it's not called, we do so later near the onComplete.
}
if (!suppressEvents) if (this._totalTime !== prevTotalTime || callback) {
this._callback("onUpdate");
}
}
if (this._cycle !== prevCycle) if (!suppressEvents) if (!this._gc) if (this.vars.onRepeat) {
this._callback("onRepeat");
}
if (callback) if (!this._gc || force) { //check gc because there's a chance that kill() could be called in an onUpdate
if (time < 0 && this._startAt && !this._onUpdate && this._startTime) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
- this._startAt.render(time, suppressEvents, force);
+ this._startAt.render(time, true, force);
}
if (isComplete) {
if (this._timeline.autoRemoveChildren) {
this._enabled(false, false);
}
@@ -698,11 +700,11 @@
for (i = 0; i !== l; b.push(a[i++]));
return b;
},
p = TimelineLite.prototype = new SimpleTimeline();
- TimelineLite.version = "1.20.2";
+ TimelineLite.version = "1.20.3";
p.constructor = TimelineLite;
p.kill()._gc = p._forcingPlayhead = p._hasPause = false;
/* might use later...
//translates a local time inside an animation to the corresponding time on the root/global timeline, factoring in all nesting and timeScales.
@@ -806,26 +808,33 @@
if (vars.smoothChildTiming == null) {
vars.smoothChildTiming = true;
}
var tl = new TimelineLite(vars),
root = tl._timeline,
- tween, next;
+ hasNegativeStart, time, tween, next;
if (ignoreDelayedCalls == null) {
ignoreDelayedCalls = true;
}
root._remove(tl, true);
tl._startTime = 0;
tl._rawPrevTime = tl._time = tl._totalTime = root._time;
tween = root._first;
while (tween) {
next = tween._next;
if (!ignoreDelayedCalls || !(tween instanceof TweenLite && tween.target === tween.vars.onComplete)) {
- tl.add(tween, tween._startTime - tween._delay);
+ time = tween._startTime - tween._delay;
+ if (time < 0) {
+ hasNegativeStart = 1;
+ }
+ tl.add(tween, time);
}
tween = next;
}
root.add(tl, 0);
+ if (hasNegativeStart) { //calling totalDuration() will force the adjustment necessary to shift the children forward so none of them start before zero, and moves the timeline backwards the same amount, so the playhead is still aligned where it should be globally, but the timeline doesn't have illegal children that start before zero.
+ tl.totalDuration();
+ }
return tl;
};
p.add = function(value, position, align, stagger) {
var curTime, l, i, child, tl, beforeRawTime;
@@ -961,11 +970,11 @@
if (ignore[i] instanceof Animation && ignore[i].timeline === this) {
this.remove(ignore[i]);
}
}
}
- clippedDuration = (this.duration() > 99999999999) ? this.recent().endTime(false) : this._duration; //in case there's a child that infinitely repeats, users almost never intend for the insertion point of a new child to be based on a SUPER long value like that so we clip it and assume the most recently-added child's endTime should be used instead.
+ clippedDuration = (typeof(timeOrLabel) === "number" && !offsetOrLabel) ? 0 : (this.duration() > 99999999999) ? this.recent().endTime(false) : this._duration; //in case there's a child that infinitely repeats, users almost never intend for the insertion point of a new child to be based on a SUPER long value like that so we clip it and assume the most recently-added child's endTime should be used instead.
if (typeof(offsetOrLabel) === "string") {
return this._parseTimeOrLabel(offsetOrLabel, (appendIfAbsent && typeof(timeOrLabel) === "number" && this._labels[offsetOrLabel] == null) ? timeOrLabel - clippedDuration : 0, appendIfAbsent);
}
offsetOrLabel = offsetOrLabel || 0;
if (typeof(timeOrLabel) === "string" && (isNaN(timeOrLabel) || this._labels[timeOrLabel] != null)) { //if the string is a number like "1", check to see if there's a label with that name, otherwise interpret it as a number (absolute value).
@@ -1002,16 +1011,19 @@
p.render = function(time, suppressEvents, force) {
if (this._gc) {
this._enabled(true, false);
}
- var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
- prevTime = this._time,
+ var prevTime = this._time,
+ totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
prevStart = this._startTime,
prevTimeScale = this._timeScale,
prevPaused = this._paused,
tween, isComplete, next, callback, internalForce, pauseTween, curTime;
+ if (prevTime !== this._time) { //if totalDuration() finds a child with a negative startTime and smoothChildTiming is true, things get shifted around internally so we need to adjust the time accordingly. For example, if a tween starts at -30 we must shift EVERYTHING forward 30 seconds and move this timeline's startTime backward by 30 seconds so that things align with the playhead (no jump).
+ time += this._time - prevTime;
+ }
if (time >= totalDur - 0.0000001 && time >= 0) { //to work around occasional floating point math artifacts.
this._totalTime = this._time = totalDur;
if (!this._reversed) if (!this._hasPausedChild()) {
isComplete = true;
callback = "onComplete";
@@ -1340,19 +1352,24 @@
while (tween) {
prev = tween._prev; //record it here in case the tween changes position in the sequence...
if (tween._dirty) {
tween.totalDuration(); //could change the tween._startTime, so make sure the tween's cache is clean before analyzing it.
}
- if (tween._startTime > prevStart && this._sortChildren && !tween._paused) { //in case one of the tweens shifted out of order, it needs to be re-inserted into the correct position in the sequence
+ if (tween._startTime > prevStart && this._sortChildren && !tween._paused && !this._calculatingDuration) { //in case one of the tweens shifted out of order, it needs to be re-inserted into the correct position in the sequence
+ this._calculatingDuration = 1; //prevent endless recursive calls - there are methods that get triggered that check duration/totalDuration when we add(), like _parseTimeOrLabel().
this.add(tween, tween._startTime - tween._delay);
+ this._calculatingDuration = 0;
} else {
prevStart = tween._startTime;
}
if (tween._startTime < 0 && !tween._paused) { //children aren't allowed to have negative startTimes unless smoothChildTiming is true, so adjust here if one is found.
max -= tween._startTime;
if (this._timeline.smoothChildTiming) {
this._startTime += tween._startTime / this._timeScale;
+ this._time -= tween._startTime;
+ this._totalTime -= tween._startTime;
+ this._rawPrevTime -= tween._startTime;
}
this.shiftChildren(-tween._startTime, false, -9999999999);
prevStart = 0;
}
end = tween._startTime + (tween._totalDuration / tween._timeScale);
@@ -1434,11 +1451,11 @@
_easeNone = new Ease(null, null, 1, 0),
p = TimelineMax.prototype = new TimelineLite();
p.constructor = TimelineMax;
p.kill()._gc = false;
- TimelineMax.version = "1.20.2";
+ TimelineMax.version = "1.20.3";
p.invalidate = function() {
this._yoyo = (this.vars.yoyo === true);
this._repeat = this.vars.repeat || 0;
this._repeatDelay = this.vars.repeatDelay || 0;
@@ -1506,20 +1523,23 @@
p.render = function(time, suppressEvents, force) {
if (this._gc) {
this._enabled(true, false);
}
- var totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
+ var prevTime = this._time,
+ totalDur = (!this._dirty) ? this._totalDuration : this.totalDuration(),
dur = this._duration,
- prevTime = this._time,
prevTotalTime = this._totalTime,
prevStart = this._startTime,
prevTimeScale = this._timeScale,
prevRawPrevTime = this._rawPrevTime,
prevPaused = this._paused,
prevCycle = this._cycle,
tween, isComplete, next, callback, internalForce, cycleDuration, pauseTween, curTime;
+ if (prevTime !== this._time) { //if totalDuration() finds a child with a negative startTime and smoothChildTiming is true, things get shifted around internally so we need to adjust the time accordingly. For example, if a tween starts at -30 we must shift EVERYTHING forward 30 seconds and move this timeline's startTime backward by 30 seconds so that things align with the playhead (no jump).
+ time += this._time - prevTime;
+ }
if (time >= totalDur - 0.0000001 && time >= 0) { //to work around occasional floating point math artifacts.
if (!this._locked) {
this._totalTime = totalDur;
this._cycle = this._repeat;
}
@@ -2561,11 +2581,11 @@
_overwriteProps, //alias to the currently instantiating CSSPlugin's _overwriteProps array. We use this closure in order to avoid having to pass a reference around from method to method and aid in minification.
_specialProps = {},
p = CSSPlugin.prototype = new TweenPlugin("css");
p.constructor = CSSPlugin;
- CSSPlugin.version = "1.20.0";
+ CSSPlugin.version = "1.20.3";
CSSPlugin.API = 2;
CSSPlugin.defaultTransformPerspective = 0;
CSSPlugin.defaultSkewType = "compensated";
CSSPlugin.defaultSmoothOrigin = true;
p = "px"; //we'll reuse the "p" variable to keep file size down
@@ -3028,11 +3048,11 @@
s = Number(a[1]) / 100;
l = Number(a[2]) / 100;
g = (l <= 0.5) ? l * (s + 1) : l + s - l * s;
r = l * 2 - g;
if (a.length > 3) {
- a[3] = Number(v[3]);
+ a[3] = Number(a[3]);
}
a[0] = _hue(h + 1 / 3, r, g);
a[1] = _hue(h, r, g);
a[2] = _hue(h - 1 / 3, r, g);
} else if (v.indexOf("=") !== -1) { //if relative values are found, just return the raw strings with the relative prefixes in place.
@@ -3410,12 +3430,17 @@
ea = e.split(", ").join(",").split(" "), //ending array
l = ba.length,
autoRound = (_autoRound !== false),
i, xi, ni, bv, ev, bnums, enums, bn, hasAlpha, temp, cv, str, useHSL;
if (e.indexOf(",") !== -1 || b.indexOf(",") !== -1) {
- ba = ba.join(" ").replace(_commasOutsideParenExp, ", ").split(" ");
- ea = ea.join(" ").replace(_commasOutsideParenExp, ", ").split(" ");
+ if ((e + b).indexOf("rgb") !== -1 || (e + b).indexOf("hsl") !== -1) { //keep rgb(), rgba(), hsl(), and hsla() values together! (remember, we're splitting on spaces)
+ ba = ba.join(" ").replace(_commasOutsideParenExp, ", ").split(" ");
+ ea = ea.join(" ").replace(_commasOutsideParenExp, ", ").split(" ");
+ } else {
+ ba = ba.join(" ").split(",").join(", ").split(" ");
+ ea = ea.join(" ").split(",").join(", ").split(" ");
+ }
l = ba.length;
}
if (l !== ea.length) {
//DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")");
ba = (dflt || "").split(" ");
@@ -3819,11 +3844,11 @@
if (!skipRecord) {
e.setAttribute("data-svg-origin", v.join(" "));
}
},
_getBBoxHack = function(swapIfPossible) { //works around issues in some browsers (like Firefox) that don't correctly report getBBox() on SVG elements inside a <defs> element and/or <mask>. We try creating an SVG, adding it to the documentElement and toss the element in there so that it's definitely part of the rendering tree, then grab the bbox and if it works, we actually swap out the original getBBox() method for our own that does these extra steps whenever getBBox is needed. This helps ensure that performance is optimal (only do all these extra steps when absolutely necessary...most elements don't need it).
- var svg = _createElement("svg", this.ownerSVGElement.getAttribute("xmlns") || "http://www.w3.org/2000/svg"),
+ var svg = _createElement("svg", (this.ownerSVGElement && this.ownerSVGElement.getAttribute("xmlns")) || "http://www.w3.org/2000/svg"),
oldParent = this.parentNode,
oldSibling = this.nextSibling,
oldCSS = this.style.cssText,
bbox;
_docElement.appendChild(svg);
@@ -3853,11 +3878,11 @@
} catch (error) {
return _getBBoxHack.call(e, true);
}
},
_isSVG = function(e) { //reports if the element is an SVG on which getBBox() actually works
- return !!(_SVGElement && e.getCTM && _getBBox(e) && (!e.parentNode || e.ownerSVGElement));
+ return !!(_SVGElement && e.getCTM && (!e.parentNode || e.ownerSVGElement) && _getBBox(e));
},
_identity2DMatrix = [1,0,0,1,0,0],
_getMatrix = function(e, force2D) {
var tm = e._gsTransform || new Transform(),
rnd = 100000,
@@ -3869,11 +3894,11 @@
//for older versions of IE, we need to interpret the filter portion that is in the format: progid:DXImageTransform.Microsoft.Matrix(M11=6.123233995736766e-17, M12=-1, M21=1, M22=6.123233995736766e-17, sizingMethod='auto expand') Notice that we need to swap b and c compared to a normal matrix.
s = e.currentStyle.filter.match(_ieGetMatrixExp);
s = (s && s.length === 4) ? [s[0].substr(4), Number(s[2].substr(4)), Number(s[1].substr(4)), s[3].substr(4), (tm.x || 0), (tm.y || 0)].join(",") : "";
}
isDefault = (!s || s === "none" || s === "matrix(1, 0, 0, 1, 0, 0)");
- if (_transformProp && ((none = (_getComputedStyle(e).display === "none")) || !e.parentNode)) {
+ if (_transformProp && ((none = (!_getComputedStyle(e) || _getComputedStyle(e).display === "none")) || !e.parentNode)) { //note: Firefox returns null for getComputedStyle() if the element is in an iframe that has display:none. https://bugzilla.mozilla.org/show_bug.cgi?id=548397
if (none) { //browsers don't report transforms accurately unless the element is in the DOM and has a display value that's not "none". Firefox and Microsoft browsers have a partial bug where they'll report transforms even if display:none BUT not any percentage-based values like translate(-50%, 8px) will be reported as if it's translate(0, 8px).
n = style.display;
style.display = "block";
}
if (!e.parentNode) {
@@ -5739,11 +5764,11 @@
p.getRatio = function(p) {
var r = p + (0.5 - p) * this._p;
if (p < this._p1) {
return this._calcEnd ? 1 - ((p = 1 - (p / this._p1)) * p) : r - ((p = 1 - (p / this._p1)) * p * p * p * r);
} else if (p > this._p3) {
- return this._calcEnd ? 1 - (p = (p - this._p3) / this._p1) * p : r + ((p - r) * (p = (p - this._p3) / this._p1) * p * p * p);
+ return this._calcEnd ? (p === 1 ? 0 : 1 - (p = (p - this._p3) / this._p1) * p) : r + ((p - r) * (p = (p - this._p3) / this._p1) * p * p * p); //added p === 1 ? 0 to avoid floating point rounding errors from affecting the final value, like 1 - 0.7 = 0.30000000000000004 instead of 0.3
}
return this._calcEnd ? 1 : r;
};
SlowMo.ease = new SlowMo(0.7, 0.7);
@@ -6324,10 +6349,13 @@
_self.tick = function() {
_tick(true);
};
_self.lagSmoothing = function(threshold, adjustedLag) {
+ if (!arguments.length) { //if lagSmoothing() is called with no arguments, treat it like a getter that returns a boolean indicating if it's enabled or not. This is purposely undocumented and is for internal use.
+ return (_lagThreshold < 1 / _tinyNum);
+ }
_lagThreshold = threshold || (1 / _tinyNum); //zero should be interpreted as basically unlimited
_adjustedLag = Math.min(adjustedLag, _lagThreshold, 0);
};
_self.sleep = function() {
@@ -6431,11 +6459,11 @@
p._paused = false;
//some browsers (like iOS) occasionally drop the requestAnimationFrame event when the user switches to a different tab and then comes back again, so we use a 2-second setTimeout() to sense if/when that condition occurs and then wake() the ticker.
var _checkTimeout = function() {
- if (_tickerActive && _getTime() - _lastUpdate > 2000 && _doc.visibilityState !== "hidden") {
+ if (_tickerActive && _getTime() - _lastUpdate > 2000 && (_doc.visibilityState !== "hidden" || !_ticker.lagSmoothing())) { //note: if the tab is hidden, we should still wake if lagSmoothing has been disabled.
_ticker.wake();
}
var t = setTimeout(_checkTimeout, 2000);
if (t.unref) {
// allows a node process to exit even if the timeout’s callback hasn't been invoked. Without it, the node process could hang as this function is called every two seconds.
@@ -6697,18 +6725,25 @@
p.timeScale = function(value) {
if (!arguments.length) {
return this._timeScale;
}
+ var pauseTime, t;
value = value || _tinyNum; //can't allow zero because it'll throw the math off
if (this._timeline && this._timeline.smoothChildTiming) {
- var pauseTime = this._pauseTime,
- t = (pauseTime || pauseTime === 0) ? pauseTime : this._timeline.totalTime();
+ pauseTime = this._pauseTime;
+ t = (pauseTime || pauseTime === 0) ? pauseTime : this._timeline.totalTime();
this._startTime = t - ((t - this._startTime) * this._timeScale / value);
}
this._timeScale = value;
- return this._uncache(false);
+ t = this.timeline;
+ while (t && t.timeline) { //must update the duration/totalDuration of all ancestor timelines immediately in case in the middle of a render loop, one tween alters another tween's timeScale which shoves its startTime before 0, forcing the parent timeline to shift around and shiftChildren() which could affect that next tween's render (startTime). Doesn't matter for the root timeline though.
+ t._dirty = true;
+ t.totalDuration();
+ t = t.timeline;
+ }
+ return this;
};
p.reversed = function(value) {
if (!arguments.length) {
return this._reversed;
@@ -6941,11 +6976,11 @@
p.ratio = 0;
p._firstPT = p._targets = p._overwrittenProps = p._startAt = null;
p._notifyPluginsOfEnabled = p._lazy = false;
- TweenLite.version = "1.20.2";
+ TweenLite.version = "1.20.3";
TweenLite.defaultEase = p._ease = new Ease(null, null, 1, 1);
TweenLite.defaultOverwrite = "auto";
TweenLite.ticker = _ticker;
TweenLite.autoSleep = 120;
TweenLite.lagSmoothing = function(threshold, adjustedLag) {
@@ -6969,11 +7004,11 @@
_setRatio = function(v) {
var pt = this._firstPT,
min = 0.000001,
val;
while (pt) {
- val = !pt.blob ? pt.c * v + pt.s : (v === 1 && this.end) ? this.end : v ? this.join("") : this.start;
+ val = !pt.blob ? pt.c * v + pt.s : (v === 1 && this.end != null) ? this.end : v ? this.join("") : this.start;
if (pt.m) {
val = pt.m(val, this._target || pt.t);
} else if (val < min) if (val > -min && !pt.blob) { //prevents issues with converting very small numbers to strings in the browser
val = 0;
}
@@ -7040,11 +7075,11 @@
if (s) {
a.push(s);
}
a.setRatio = _setRatio;
if (_relExp.test(end)) { //if the end string contains relative values, delete it so that on the final render (in _setRatio()), we don't actually set it to the string with += or -= characters (forces it to use the calculated value).
- a.end = 0;
+ a.end = null;
}
return a;
},
//note: "funcParam" is only necessary for function-based getters/setters that require an extra parameter like getAttribute("width") and setAttribute("width", value). In this example, funcParam would be "width". Used by AttrPlugin for example.
_addPropTween = function(target, prop, start, end, overwriteProp, mod, funcParam, stringFilter, index) {
@@ -7262,15 +7297,17 @@
}
startVars = {};
for (p in v.startAt) { //copy the properties/values into a new object to avoid collisions, like var to = {x:0}, from = {x:500}; timeline.fromTo(e, 1, from, to).fromTo(e, 1, to, from);
startVars[p] = v.startAt[p];
}
+ startVars.data = "isStart";
startVars.overwrite = false;
startVars.immediateRender = true;
startVars.lazy = (immediate && v.lazy !== false);
startVars.startAt = startVars.delay = null; //no nesting of startAt objects allowed (otherwise it could cause an infinite loop).
startVars.onUpdate = v.onUpdate;
+ startVars.onUpdateParams = v.onUpdateParams;
startVars.onUpdateScope = v.onUpdateScope || v.callbackScope || this;
this._startAt = TweenLite.to(this.target, 0, startVars);
if (immediate) {
if (this._time > 0) {
this._startAt = null; //tweens that render immediately (like most from() and fromTo() tweens) shouldn't revert when their parent timeline's playhead goes backward past the startTime because the initial render could have happened anytime and it shouldn't be directly correlated to this tween's startTime. Imagine setting up a complex animation where the beginning states of various objects are rendered immediately but the tween doesn't happen for quite some time - if we revert to the starting values as soon as the playhead goes backward past the tween's startTime, it will throw things off visually. Reversion should only happen in TimelineLite/Max instances where immediateRender was false (which is the default in the convenience methods like from()).
@@ -7519,11 +7556,11 @@
this._active = true; //so that if the user renders a tween (as opposed to the timeline rendering it), the timeline is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the tween already finished but the user manually re-renders it as halfway done.
}
if (prevTime === 0) {
if (this._startAt) {
if (time >= 0) {
- this._startAt.render(time, suppressEvents, force);
+ this._startAt.render(time, true, force);
} else if (!callback) {
callback = "_dummyGS"; //if no callback is defined, use a dummy value just so that the condition at the end evaluates as true because _startAt should render AFTER the normal render loop when the time is negative. We could handle this in a more intuitive way, of course, but the render loop is the MOST important thing to optimize, so this technique allows us to avoid adding extra conditional logic in a high-frequency area.
}
}
if (this.vars.onStart) if (this._time !== 0 || duration === 0) if (!suppressEvents) {
@@ -7540,18 +7577,18 @@
pt = pt._next;
}
if (this._onUpdate) {
if (time < 0) if (this._startAt && time !== -0.0001) { //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values.
- this._startAt.render(time, suppressEvents, force); //note: for performance reasons, we tuck this conditional logic inside less traveled areas (most tweens don't have an onUpdate). We'd just have it at the end before the onComplete, but the values should be updated before any onUpdate is called, so we ALSO put it here and then if it's not called, we do so later near the onComplete.
+ this._startAt.render(time, true, force); //note: for performance reasons, we tuck this conditional logic inside less traveled areas (most tweens don't have an onUpdate). We'd just have it at the end before the onComplete, but the values should be updated before any onUpdate is called, so we ALSO put it here and then if it's not called, we do so later near the onComplete.
}
if (!suppressEvents) if (this._time !== prevTime || isComplete || force) {
this._callback("onUpdate");
}
}
if (callback) if (!this._gc || force) { //check _gc because there's a chance that kill() could be called in an onUpdate
if (time < 0 && this._startAt && !this._onUpdate && time !== -0.0001) { //-0.0001 is a special value that we use when looping back to the beginning of a repeated TimelineMax, in which case we shouldn't render the _startAt values.
- this._startAt.render(time, suppressEvents, force);
+ this._startAt.render(time, true, force);
}
if (isComplete) {
if (this._timeline.autoRemoveChildren) {
this._enabled(false, false);
}
\ No newline at end of file