Bug 1248338 - Implement iterationStart; r=birtles

This commit is contained in:
Daisuke Akatsuka 2016-03-02 16:23:34 +09:00
parent 357a88afa2
commit 242e38458f
13 changed files with 1045 additions and 26 deletions

View File

@ -19,6 +19,7 @@ TimingParams::TimingParams(const dom::AnimationEffectTimingProperties& aRhs,
: mDuration(aRhs.mDuration)
, mDelay(TimeDuration::FromMilliseconds(aRhs.mDelay))
, mIterations(aRhs.mIterations)
, mIterationStart(aRhs.mIterationStart)
, mDirection(aRhs.mDirection)
, mFill(aRhs.mFill)
{
@ -113,6 +114,7 @@ TimingParams::operator==(const TimingParams& aOther) const
return durationEqual &&
mDelay == aOther.mDelay &&
mIterations == aOther.mIterations &&
mIterationStart == aOther.mIterationStart &&
mDirection == aOther.mDirection &&
mFill == aOther.mFill &&
mFunction == aOther.mFunction;

View File

@ -51,6 +51,7 @@ struct TimingParams
dom::OwningUnrestrictedDoubleOrString mDuration;
TimeDuration mDelay; // Initializes to zero
double mIterations = 1.0; // Can be NaN, negative, +/-Infinity
double mIterationStart = 0.0;
dom::PlaybackDirection mDirection = dom::PlaybackDirection::Normal;
dom::FillMode mFill = dom::FillMode::Auto;
Maybe<ComputedTimingFunction> mFunction;
@ -85,7 +86,7 @@ public:
double Delay() const { return mTiming.mDelay.ToMilliseconds(); }
double EndDelay() const { return 0.0; }
FillMode Fill() const { return mTiming.mFill; }
double IterationStart() const { return 0.0; }
double IterationStart() const { return mTiming.mIterationStart; }
double Iterations() const { return mTiming.mIterations; }
void GetDuration(OwningUnrestrictedDoubleOrString& aRetVal) const
{

View File

@ -36,6 +36,7 @@ GetComputedTimingDictionary(const ComputedTiming& aComputedTiming,
aRetVal.mDelay = aTiming.mDelay.ToMilliseconds();
aRetVal.mFill = aComputedTiming.mFill;
aRetVal.mIterations = aComputedTiming.mIterations;
aRetVal.mIterationStart = aComputedTiming.mIterationStart;
aRetVal.mDuration.SetAsUnrestrictedDouble() =
aComputedTiming.mDuration.ToMilliseconds();
aRetVal.mDirection = aTiming.mDirection;
@ -45,6 +46,7 @@ GetComputedTimingDictionary(const ComputedTiming& aComputedTiming,
aRetVal.mEndTime = aComputedTiming.mEndTime.ToMilliseconds();
aRetVal.mLocalTime = AnimationUtils::TimeDurationToDouble(aLocalTime);
aRetVal.mProgress = aComputedTiming.mProgress;
if (!aRetVal.mProgress.IsNull()) {
// Convert the returned currentIteration into Infinity if we set
// (uint64_t) aComputedTiming.mCurrentIteration to UINT64_MAX
@ -244,6 +246,8 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
result.mIterations = IsNaN(aTiming.mIterations) || aTiming.mIterations < 0.0f ?
1.0f :
aTiming.mIterations;
result.mIterationStart = std::max(aTiming.mIterationStart, 0.0);
result.mActiveDuration = ActiveDuration(result.mDuration, result.mIterations);
// Bug 1244635: Add endDelay to the end time calculation
result.mEndTime = aTiming.mDelay + result.mActiveDuration;
@ -273,10 +277,11 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
return result;
}
activeTime = result.mActiveDuration;
// Note that infinity == floor(infinity) so this will also be true when we
// have finished an infinitely repeating animation of zero duration.
double finiteProgress =
(IsInfinite(result.mIterations) ? 0.0 : result.mIterations)
+ result.mIterationStart;
isEndOfFinalIteration = result.mIterations != 0.0 &&
result.mIterations == floor(result.mIterations);
fmod(finiteProgress, 1.0) == 0;
} else if (localTime < aTiming.mDelay) {
result.mPhase = ComputedTiming::AnimationPhase::Before;
if (!result.FillsBackwards()) {
@ -292,49 +297,66 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
activeTime = localTime - aTiming.mDelay;
}
// Calculate the scaled active time
// (We handle the case where the iterationStart is zero separately in case
// the duration is infinity, since 0 * Infinity is undefined.)
StickyTimeDuration startOffset =
result.mIterationStart == 0.0
? StickyTimeDuration(0)
: result.mDuration.MultDouble(result.mIterationStart);
StickyTimeDuration scaledActiveTime = activeTime + startOffset;
// Get the position within the current iteration.
StickyTimeDuration iterationTime;
if (result.mDuration != zeroDuration) {
if (result.mDuration != zeroDuration &&
scaledActiveTime != StickyTimeDuration::Forever()) {
iterationTime = isEndOfFinalIteration
? result.mDuration
: activeTime % result.mDuration;
} /* else, iterationTime is zero */
: scaledActiveTime % result.mDuration;
} /* else, either the duration is zero and iterationTime is zero,
or the scaledActiveTime is infinity in which case the iterationTime
should become infinity but we will not use the iterationTime in that
case so we just leave it as zero */
// Determine the 0-based index of the current iteration.
if (isEndOfFinalIteration) {
if (result.mPhase == ComputedTiming::AnimationPhase::Before ||
result.mIterations == 0) {
result.mCurrentIteration = static_cast<uint64_t>(result.mIterationStart);
} else if (result.mPhase == ComputedTiming::AnimationPhase::After) {
result.mCurrentIteration =
IsInfinite(result.mIterations) // Positive Infinity?
IsInfinite(result.mIterations)
? UINT64_MAX // In GetComputedTimingDictionary(), we will convert this
// into Infinity.
: static_cast<uint64_t>(result.mIterations) - 1;
} else if (activeTime == zeroDuration) {
// If the active time is zero we're either in the first iteration
// (including filling backwards) or we have finished an animation with an
// iteration duration of zero that is filling forwards (but we're not at
// the exact end of an iteration since we deal with that above).
result.mCurrentIteration =
result.mPhase == ComputedTiming::AnimationPhase::After
? static_cast<uint64_t>(result.mIterations) // floor
: 0;
: static_cast<uint64_t>(ceil(result.mIterations +
result.mIterationStart)) - 1;
} else if (result.mDuration == StickyTimeDuration::Forever()) {
result.mCurrentIteration = static_cast<uint64_t>(result.mIterationStart);
} else {
result.mCurrentIteration =
static_cast<uint64_t>(activeTime / result.mDuration); // floor
static_cast<uint64_t>(scaledActiveTime / result.mDuration); // floor
}
// Normalize the iteration time into a fraction of the iteration duration.
if (result.mPhase == ComputedTiming::AnimationPhase::Before) {
result.mProgress.SetValue(0.0);
if (result.mPhase == ComputedTiming::AnimationPhase::Before ||
result.mIterations == 0) {
double progress = fmod(result.mIterationStart, 1.0);
result.mProgress.SetValue(progress);
} else if (result.mPhase == ComputedTiming::AnimationPhase::After) {
double progress = isEndOfFinalIteration
? 1.0
: fmod(result.mIterations, 1.0);
double progress;
if (isEndOfFinalIteration) {
progress = 1.0;
} else if (IsInfinite(result.mIterations)) {
progress = fmod(result.mIterationStart, 1.0);
} else {
progress = fmod(result.mIterations + result.mIterationStart, 1.0);
}
result.mProgress.SetValue(progress);
} else {
// We are in the active phase so the iteration duration can't be zero.
MOZ_ASSERT(result.mDuration != zeroDuration,
"In the active phase of a zero-duration animation?");
double progress = result.mDuration == StickyTimeDuration::Forever()
? 0.0
? fmod(result.mIterationStart, 1.0)
: iterationTime / result.mDuration;
result.mProgress.SetValue(progress);
}

View File

@ -69,6 +69,7 @@ struct ComputedTiming
// Unlike TimingParams::mIterations, this value is
// guaranteed to be in the range [0, Infinity].
double mIterations = 1.0;
double mIterationStart = 0.0;
StickyTimeDuration mDuration;
// This is the computed fill mode so it is never auto

View File

@ -589,6 +589,7 @@ SampleAnimations(Layer* aLayer, TimeStamp aPoint)
// into their start time, hence the delay is effectively zero.
timing.mDelay = TimeDuration(0);
timing.mIterations = animation.iterations();
timing.mIterationStart = animation.iterationStart();
timing.mDirection =
static_cast<dom::PlaybackDirection>(animation.direction());
// Animations typically only run on the compositor during their active

View File

@ -195,6 +195,7 @@ struct Animation {
// Values <= 0 mean the animation will not play (although events are still
// dispatched on the main thread).
float iterations;
float iterationStart;
// This uses the NS_STYLE_ANIMATION_DIRECTION_* constants.
int32_t direction;
nsCSSProperty property;

View File

@ -399,6 +399,7 @@ AddAnimationForProperty(nsIFrame* aFrame, const AnimationProperty& aProperty,
- timing.mDelay;
animation->duration() = computedTiming.mDuration;
animation->iterations() = computedTiming.mIterations;
animation->iterationStart() = computedTiming.mIterationStart;
animation->direction() = static_cast<uint32_t>(timing.mDirection);
animation->property() = aProperty.mProperty;
animation->playbackRate() = aAnimation->PlaybackRate();

View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<head>
<script type="application/javascript"
src="/tests/SimpleTest/paint_listener.js"></script>
<script type="application/javascript" src="animation_utils.js"></script>
<style type="text/css">
.target {
/* The animation target needs geometry in order to qualify for OMTA */
width: 100px;
height: 100px;
background-color: white;
}
</style>
<script>
var ok = opener.ok.bind(opener);
var is = opener.is.bind(opener);
var todo = opener.todo.bind(opener);
function finish() {
var o = opener;
self.close();
o.SimpleTest.finish();
}
</script>
</head>
<body>
<div id="display"></div>
<script type="application/javascript">
"use strict";
runOMTATest(function() {
runAllAsyncAnimTests().then(function() {
finish();
});
}, finish, opener.SpecialPowers);
addAsyncAnimTest(function *() {
var [ div ] = new_div("test");
var animation = div.animate(
{ transform: ["translate(0px)", "translate(100px)"] },
{ iterationStart: 0.5, duration: 10000, fill: "both"}
);
yield waitForPaints();
omta_is(div, "transform", { tx: 50 }, RunningOn.Compositor, "Start of Animation");
advance_clock(4000);
yield waitForPaints();
omta_is(div, "transform", { tx: 90 }, RunningOn.Compositor, "40% of Animation");
advance_clock(6000);
yield waitForPaints();
omta_is(div, "transform", { tx: 50 }, RunningOn.MainThread, "End of Animation");
done_div();
});
</script>
</body>
</html>

View File

@ -45,6 +45,8 @@ support-files = ../../reftests/fonts/Ahem.ttf file_animations_async_tests.html
[test_animations_effect_timing_duration.html]
support-files = file_animations_effect_timing_duration.html
[test_animations_event_order.html]
[test_animations_iterationstart.html]
support-files = file_animations_iterationstart.html
[test_animations_omta.html]
[test_animations_omta_start.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # bug 1041017

View File

@ -0,0 +1,28 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1248338
-->
<head>
<title>Test for iterationStart on compositor animations (Bug 1248338)</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1248338">Mozilla Bug 1248338</a>
<div id="display"></div>
<pre id="test">
<script type="application/javascript">
"use strict";
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv(
{ "set": [[ "dom.animations-api.core.enabled", true]] },
function() {
window.open("file_animations_iterationstart.html");
});
</script>
</pre>
</body>
</html>

View File

@ -28155,6 +28155,14 @@
"path": "web-animations/keyframe-effect/getComputedTiming.html",
"url": "/web-animations/keyframe-effect/getComputedTiming.html"
},
{
"path": "web-animations/keyframe-effect/getComputedTiming-currentIteration.html",
"url": "/web-animations/keyframe-effect/getComputedTiming-currentIteration.html"
},
{
"path": "web-animations/keyframe-effect/getComputedTiming-progress.html",
"url": "/web-animations/keyframe-effect/getComputedTiming-progress.html"
},
{
"path": "webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html",
"url": "/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html"

View File

@ -0,0 +1,446 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>currentIteration of KeyframeEffectReadOnly getComputedTiming() tests</title>
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffectreadonly-getcomputedtiming">
<link rel="author" title="Daisuke Akatsuka" href="mailto:daisuke@mozilla-japan.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../testcommon.js"></script>
<link rel="stylesheet" href="/resources/testharness.css">
<body>
<div id="log"></div>
<script>
'use strict';
function executeTests(tests, description) {
tests.forEach(function(currentTest) {
var testParams = '';
for (var attr in currentTest.input) {
testParams += ' ' + attr + ':' + currentTest.input[attr];
}
test(function(t) {
var div = createDiv(t);
var anim = div.animate({ opacity: [ 0, 1 ] }, currentTest.input);
assert_equals(anim.effect.getComputedTiming().currentIteration,
currentTest.before);
anim.currentTime = currentTest.input.delay || 0;
assert_equals(anim.effect.getComputedTiming().currentIteration,
currentTest.active);
if (typeof currentTest.after !== 'undefined') {
anim.finish();
assert_equals(anim.effect.getComputedTiming().currentIteration,
currentTest.after);
}
}, description + testParams);
});
}
async_test(function(t) {
var div = createDiv(t);
var anim = div.animate({ opacity: [ 0, 1 ] }, { delay: 1 });
assert_equals(anim.effect.getComputedTiming().currentIteration, null);
anim.finished.then(t.step_func(function() {
assert_equals(anim.effect.getComputedTiming().currentIteration, null);
t.done();
}));
}, 'Test currentIteration during before and after phase when fill is none');
var gTests_zero_iterations = [
{
input: { iterations: 0,
iterationStart: 0,
duration: 0,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 0
},
{
input: { iterations: 0,
iterationStart: 0,
duration: 100,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 0
},
{
input: { iterations: 0,
iterationStart: 0,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 0
},
{
input: { iterations: 0,
iterationStart: 2.5,
duration: 0,
delay: 1,
fill: 'both' },
before: 2,
active: 2,
after: 2
},
{
input: { iterations: 0,
iterationStart: 2.5,
duration: 100,
delay: 1,
fill: 'both' },
before: 2,
active: 2,
after: 2
},
{
input: { iterations: 0,
iterationStart: 2.5,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 2,
active: 2,
after: 2
},
{
input: { iterations: 0,
iterationStart: 3,
duration: 0,
delay: 1,
fill: 'both' },
before: 3,
active: 3,
after: 3
},
{
input: { iterations: 0,
iterationStart: 3,
duration: 100,
delay: 1,
fill: 'both' },
before: 3,
active: 3,
after: 3
},
{
input: { iterations: 0,
iterationStart: 3,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 3,
active: 3,
after: 3
}
];
var gTests_integer_iterations = [
{
input: { iterations: 3,
iterationStart: 0,
duration: 0,
delay: 1,
fill: 'both' },
before: 0,
active: 2,
after: 2
},
{
input: { iterations: 3,
iterationStart: 0,
duration: 100,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 2
},
{
input: { iterations: 3,
iterationStart: 0,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0,
active: 0
},
{
input: { iterations: 3,
iterationStart: 2.5,
duration: 0,
delay: 1,
fill: 'both' },
before: 2,
active: 5,
after: 5
},
{
input: { iterations: 3,
iterationStart: 2.5,
duration: 100,
delay: 1,
fill: 'both' },
before: 2,
active: 2,
after: 5
},
{
input: { iterations: 3,
iterationStart: 2.5,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 2,
active: 2
},
{
input: { iterations: 3,
iterationStart: 3,
duration: 0,
delay: 1,
fill: 'both' },
before: 3,
active: 5,
after: 5
},
{
input: { iterations: 3,
iterationStart: 3,
duration: 100,
delay: 1,
fill: 'both' },
before: 3,
active: 3,
after: 5
},
{
input: { iterations: 3,
iterationStart: 3,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 3,
active: 3
}
];
var gTests_fractional_iterations = [
{
input: { iterations: 3.5,
iterationStart: 0,
duration: 0,
delay: 1,
fill: 'both' },
before: 0,
active: 3,
after: 3
},
{
input: { iterations: 3.5,
iterationStart: 0,
duration: 100,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 3
},
{
input: { iterations: 3.5,
iterationStart: 0,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0,
active: 0
},
{
input: { iterations: 3.5,
iterationStart: 2.5,
duration: 0,
delay: 1,
fill: 'both' },
before: 2,
active: 5,
after: 5
},
{
input: { iterations: 3.5,
iterationStart: 2.5,
duration: 100,
delay: 1,
fill: 'both' },
before: 2,
active: 2,
after: 5
},
{
input: { iterations: 3.5,
iterationStart: 2.5,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 2,
active: 2
},
{
input: { iterations: 3.5,
iterationStart: 3,
duration: 0,
delay: 1,
fill: 'both' },
before: 3,
active: 6,
after: 6
},
{
input: { iterations: 3.5,
iterationStart: 3,
duration: 100,
delay: 1,
fill: 'both' },
before: 3,
active: 3,
after: 6
},
{
input: { iterations: 3.5,
iterationStart: 3,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 3,
active: 3
}
];
var gTests_infinity_iterations = [
{
input: { iterations: Infinity,
iterationStart: 0,
duration: 0,
delay: 1,
fill: 'both' },
before: 0,
active: Infinity,
after: Infinity
},
{
input: { iterations: Infinity,
iterationStart: 0,
duration: 100,
delay: 1,
fill: 'both' },
before: 0,
active: 0
},
{
input: { iterations: Infinity,
iterationStart: 0,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0,
active: 0
},
{
input: { iterations: Infinity,
iterationStart: 2.5,
duration: 0,
delay: 1,
fill: 'both' },
before: 2,
active: Infinity,
after: Infinity
},
{
input: { iterations: Infinity,
iterationStart: 2.5,
duration: 100,
delay: 1,
fill: 'both' },
before: 2,
active: 2
},
{
input: { iterations: Infinity,
iterationStart: 2.5,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 2,
active: 2
},
{
input: { iterations: Infinity,
iterationStart: 3,
duration: 0,
delay: 1,
fill: 'both' },
before: 3,
active: Infinity,
after: Infinity
},
{
input: { iterations: Infinity,
iterationStart: 3,
duration: 100,
delay: 1,
fill: 'both' },
before: 3,
active: 3
},
{
input: { iterations: Infinity,
iterationStart: 3,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 3,
active: 3
}
];
executeTests(gTests_zero_iterations, "Test zero iterations:");
executeTests(gTests_integer_iterations, "Test integer iterations:");
executeTests(gTests_fractional_iterations, "Test fractional iterations:");
executeTests(gTests_infinity_iterations, "Test infinity iterations:");
</script>
</body>

View File

@ -0,0 +1,446 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>progress of KeyframeEffectReadOnly getComputedTiming() tests</title>
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffectreadonly-getcomputedtiming">
<link rel="author" title="Daisuke Akatsuka" href="mailto:daisuke@mozilla-japan.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../testcommon.js"></script>
<link rel="stylesheet" href="/resources/testharness.css">
<body>
<div id="log"></div>
<script>
'use strict';
function executeTests(tests, description) {
tests.forEach(function(currentTest) {
var testParams = '';
for (var attr in currentTest.input) {
testParams += ' ' + attr + ':' + currentTest.input[attr];
}
test(function(t) {
var div = createDiv(t);
var anim = div.animate({ opacity: [ 0, 1 ] }, currentTest.input);
assert_equals(anim.effect.getComputedTiming().progress,
currentTest.before);
anim.currentTime = currentTest.input.delay || 0;
assert_equals(anim.effect.getComputedTiming().progress,
currentTest.active);
if (typeof currentTest.after !== 'undefined') {
anim.finish();
assert_equals(anim.effect.getComputedTiming().progress,
currentTest.after);
}
}, description + testParams);
});
}
async_test(function(t) {
var div = createDiv(t);
var anim = div.animate({ opacity: [ 0, 1 ] }, { delay: 1 });
assert_equals(anim.effect.getComputedTiming().progress, null);
anim.finished.then(t.step_func(function() {
assert_equals(anim.effect.getComputedTiming().progress, null);
t.done();
}));
}, 'Test progress during before and after phase when fill is none');
var gTests_zero_iterations = [
{
input: { iterations: 0,
iterationStart: 0,
duration: 0,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 0
},
{
input: { iterations: 0,
iterationStart: 0,
duration: 100,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 0
},
{
input: { iterations: 0,
iterationStart: 0,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 0
},
{
input: { iterations: 0,
iterationStart: 2.5,
duration: 0,
delay: 1,
fill: 'both' },
before: 0.5,
active: 0.5,
after: 0.5
},
{
input: { iterations: 0,
iterationStart: 2.5,
duration: 100,
delay: 1,
fill: 'both' },
before: 0.5,
active: 0.5,
after: 0.5
},
{
input: { iterations: 0,
iterationStart: 2.5,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0.5,
active: 0.5,
after: 0.5
},
{
input: { iterations: 0,
iterationStart: 3,
duration: 0,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 0
},
{
input: { iterations: 0,
iterationStart: 3,
duration: 100,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 0
},
{
input: { iterations: 0,
iterationStart: 3,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 0
}
];
var gTests_integer_iterations = [
{
input: { iterations: 3,
iterationStart: 0,
duration: 0,
delay: 1,
fill: 'both' },
before: 0,
active: 1,
after: 1
},
{
input: { iterations: 3,
iterationStart: 0,
duration: 100,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 1
},
{
input: { iterations: 3,
iterationStart: 0,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0,
active: 0
},
{
input: { iterations: 3,
iterationStart: 2.5,
duration: 0,
delay: 1,
fill: 'both' },
before: 0.5,
active: 0.5,
after: 0.5
},
{
input: { iterations: 3,
iterationStart: 2.5,
duration: 100,
delay: 1,
fill: 'both' },
before: 0.5,
active: 0.5,
after: 0.5
},
{
input: { iterations: 3,
iterationStart: 2.5,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0.5,
active: 0.5
},
{
input: { iterations: 3,
iterationStart: 3,
duration: 0,
delay: 1,
fill: 'both' },
before: 0,
active: 1,
after: 1
},
{
input: { iterations: 3,
iterationStart: 3,
duration: 100,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 1
},
{
input: { iterations: 3,
iterationStart: 3,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0,
active: 0
}
];
var gTests_fractional_iterations = [
{
input: { iterations: 3.5,
iterationStart: 0,
duration: 0,
delay: 1,
fill: 'both' },
before: 0,
active: 0.5,
after: 0.5
},
{
input: { iterations: 3.5,
iterationStart: 0,
duration: 100,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 0.5
},
{
input: { iterations: 3.5,
iterationStart: 0,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0,
active: 0
},
{
input: { iterations: 3.5,
iterationStart: 2.5,
duration: 0,
delay: 1,
fill: 'both' },
before: 0.5,
active: 1,
after: 1
},
{
input: { iterations: 3.5,
iterationStart: 2.5,
duration: 100,
delay: 1,
fill: 'both' },
before: 0.5,
active: 0.5,
after: 1
},
{
input: { iterations: 3.5,
iterationStart: 2.5,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0.5,
active: 0.5
},
{
input: { iterations: 3.5,
iterationStart: 3,
duration: 0,
delay: 1,
fill: 'both' },
before: 0,
active: 0.5,
after: 0.5
},
{
input: { iterations: 3.5,
iterationStart: 3,
duration: 100,
delay: 1,
fill: 'both' },
before: 0,
active: 0,
after: 0.5
},
{
input: { iterations: 3.5,
iterationStart: 3,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0,
active: 0
}
];
var gTests_infinity_iterations = [
{
input: { iterations: Infinity,
iterationStart: 0,
duration: 0,
delay: 1,
fill: 'both' },
before: 0,
active: 1,
after: 1
},
{
input: { iterations: Infinity,
iterationStart: 0,
duration: 100,
delay: 1,
fill: 'both' },
before: 0,
active: 0
},
{
input: { iterations: Infinity,
iterationStart: 0,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0,
active: 0
},
{
input: { iterations: Infinity,
iterationStart: 2.5,
duration: 0,
delay: 1,
fill: 'both' },
before: 0.5,
active: 0.5,
after: 0.5
},
{
input: { iterations: Infinity,
iterationStart: 2.5,
duration: 100,
delay: 1,
fill: 'both' },
before: 0.5,
active: 0.5
},
{
input: { iterations: Infinity,
iterationStart: 2.5,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0.5,
active: 0.5
},
{
input: { iterations: Infinity,
iterationStart: 3,
duration: 0,
delay: 1,
fill: 'both' },
before: 0,
active: 1,
after: 1
},
{
input: { iterations: Infinity,
iterationStart: 3,
duration: 100,
delay: 1,
fill: 'both' },
before: 0,
active: 0
},
{
input: { iterations: Infinity,
iterationStart: 3,
duration: Infinity,
delay: 1,
fill: 'both' },
before: 0,
active: 0
}
];
executeTests(gTests_zero_iterations, "Test zero iterations:");
executeTests(gTests_integer_iterations, "Test integer iterations:");
executeTests(gTests_fractional_iterations, "Test fractional iterations:");
executeTests(gTests_infinity_iterations, "Test infinity iterations:");
</script>
</body>