diff --git a/test/testcases.js b/test/testcases.js index 35a25dbb..57c4de63 100644 --- a/test/testcases.js +++ b/test/testcases.js @@ -22,6 +22,7 @@ var tests = [ 'auto-test-iterations-basic.html', 'auto-test-iterations-fill.html', 'auto-test-keyframe-creation.html', + 'auto-test-keyframe-easing.html', 'auto-test-length-units.html', 'auto-test-matrix-transforms.html', 'auto-test-non-numeric.html', diff --git a/test/testcases/auto-test-keyframe-easing-checks.js b/test/testcases/auto-test-keyframe-easing-checks.js new file mode 100644 index 00000000..c1fc1db4 --- /dev/null +++ b/test/testcases/auto-test-keyframe-easing-checks.js @@ -0,0 +1,65 @@ +timing_test(function() { + at(0, function() { + assert_styles("#target",{'height':'0px'}); + }); + at(0.25, function() { + assert_styles("#target",{'height':'12.5px'}); + }); + at(0.5, function() { + assert_styles("#target",{'height':'25px'}); + }); + at(0.75, function() { + assert_styles("#target",{'height':'37.5px'}); + }); + at(1, function() { + assert_styles("#target",{'height':'50px'}); + }); + at(1.25, function() { + assert_styles("#target",{'height':'62.5px'}); + }); + at(1.5, function() { + assert_styles("#target",{'height':'75px'}); + }); + at(1.75, function() { + assert_styles("#target",{'height':'87.5px'}); + }); + at(2, function() { + assert_styles("#target",{'height':'100px'}); + }); + at(2.25, function() { + assert_styles("#target",{'height':'106.5px'}); + }); + at(2.5, function() { + assert_styles("#target",{'height':'125px'}); + }); + at(2.75, function() { + assert_styles("#target",{'height':'143.5px'}); + }); + at(3, function() { + assert_styles("#target",{'height':'150px'}); + }); + at(3.25, function() { + assert_styles("#target",{'height':'150px'}); + }); + at(3.5, function() { + assert_styles("#target",{'height':'150px'}); + }); + at(3.75, function() { + assert_styles("#target",{'height':'200px'}); + }); + at(4, function() { + assert_styles("#target",{'height':'200px'}); + }); + at(4.25, function() { + assert_styles("#target",{'height':'200px'}); + }); + at(4.5, function() { + assert_styles("#target",{'height':'225px'}); + }); + at(4.75, function() { + assert_styles("#target",{'height':'225px'}); + }); + at(5, function() { + assert_styles("#target",{'height':'250px'}); + }); +}, "Auto generated tests"); diff --git a/test/testcases/auto-test-keyframe-easing.html b/test/testcases/auto-test-keyframe-easing.html new file mode 100644 index 00000000..f13bd015 --- /dev/null +++ b/test/testcases/auto-test-keyframe-easing.html @@ -0,0 +1,64 @@ + + +
+
+
+
+ + diff --git a/web-animations.js b/web-animations.js index 46235590..7fc49fb3 100644 --- a/web-animations.js +++ b/web-animations.js @@ -2006,7 +2006,8 @@ var expandShorthand = function(property, value, result) { var normalizeKeyframeDictionary = function(properties) { var result = { offset: null, - composite: null + composite: null, + easing: presetTimingFunctions.linear }; var animationProperties = []; for (var property in properties) { @@ -2020,6 +2021,8 @@ var normalizeKeyframeDictionary = function(properties) { properties.composite === 'replace') { result.composite = properties.composite; } + } else if (property === 'easing') { + result.easing = TimingFunction.createFromString(properties.easing); } else { // TODO: Check whether this is a supported property. animationProperties.push(property); @@ -2186,6 +2189,9 @@ KeyframeEffect.prototype = createObject(AnimationEffect.prototype, { } var intervalDistance = (timeFraction - startKeyframe.offset) / (endKeyframe.offset - startKeyframe.offset); + if (startKeyframe.easing) { + intervalDistance = startKeyframe.easing.scaleTime(intervalDistance); + } return new BlendedCompositableValue( new AddReplaceCompositableValue(startKeyframe.rawValue(), this._compositeForKeyframe(startKeyframe)), @@ -2207,8 +2213,8 @@ KeyframeEffect.prototype = createObject(AnimationEffect.prototype, { } var frame = distributedFrames[i]; this._cachedPropertySpecificKeyframes[property].push( - new PropertySpecificKeyframe(frame.offset, - frame.composite, property, frame.cssValues[property])); + new PropertySpecificKeyframe(frame.offset, frame.composite, + frame.easing, property, frame.cssValues[property])); } } @@ -2221,12 +2227,12 @@ KeyframeEffect.prototype = createObject(AnimationEffect.prototype, { // Add synthetic keyframes at offsets of 0 and 1 if required. if (frames[0].offset !== 0.0) { var keyframe = new PropertySpecificKeyframe(0.0, 'add', - property, cssNeutralValue); + presetTimingFunctions.linear, property, cssNeutralValue); frames.unshift(keyframe); } if (frames[frames.length - 1].offset !== 1.0) { var keyframe = new PropertySpecificKeyframe(1.0, 'add', - property, cssNeutralValue); + presetTimingFunctions.linear, property, cssNeutralValue); frames.push(keyframe); } ASSERT_ENABLED && assert( @@ -2372,7 +2378,7 @@ KeyframeEffect.prototype = createObject(AnimationEffect.prototype, { * * @constructor */ -var KeyframeInternal = function(offset, composite) { +var KeyframeInternal = function(offset, composite, easing) { ASSERT_ENABLED && assert( typeof offset === 'number' || offset === null, 'Invalid offset value'); @@ -2381,6 +2387,7 @@ var KeyframeInternal = function(offset, composite) { 'Invalid composite value'); this.offset = offset; this.composite = composite; + this.easing = easing; this.cssValues = {}; }; @@ -2405,9 +2412,12 @@ KeyframeInternal.createFromNormalizedProperties = function(properties) { ASSERT_ENABLED && assert( isDefinedAndNotNull(properties) && typeof properties === 'object', 'Properties must be an object'); - var keyframe = new KeyframeInternal(properties.offset, properties.composite); + var keyframe = new KeyframeInternal(properties.offset, properties.composite, + properties.easing); for (var candidate in properties) { - if (candidate !== 'offset' && candidate !== 'composite') { + if (candidate !== 'offset' && + candidate !== 'composite' && + candidate !== 'easing') { keyframe.addPropertyValuePair(candidate, properties[candidate]); } } @@ -2417,9 +2427,11 @@ KeyframeInternal.createFromNormalizedProperties = function(properties) { /** @constructor */ -var PropertySpecificKeyframe = function(offset, composite, property, cssValue) { +var PropertySpecificKeyframe = function(offset, composite, easing, property, + cssValue) { this.offset = offset; this.composite = composite; + this.easing = easing; this.property = property; this.cssValue = cssValue; // Calculated lazily