| OLD | NEW | 
| (Empty) |  | 
 |    1 <!DOCTYPE html> | 
 |    2 <meta charset=utf-8> | 
 |    3 <title>Tests for calculation of the transformed distance when computing an effec
     t value</title> | 
 |    4 <link rel="help" href="https://w3c.github.io/web-animations/#the-effect-value-of
     -a-keyframe-animation-effect"> | 
 |    5 <script src="/resources/testharness.js"></script> | 
 |    6 <script src="/resources/testharnessreport.js"></script> | 
 |    7 <script src="../../testcommon.js"></script> | 
 |    8 <script src="../../resources/easing-tests.js"></script> | 
 |    9 <body> | 
 |   10 <div id="log"></div> | 
 |   11 <div id="target"></div> | 
 |   12 <script> | 
 |   13 'use strict'; | 
 |   14  | 
 |   15 // Test that applying easing to keyframes is applied as expected | 
 |   16  | 
 |   17 gEasingTests.forEach(params => { | 
 |   18   test(function(t) { | 
 |   19     const target = createDiv(t); | 
 |   20     const anim   = target.animate([ { width: '0px' }, | 
 |   21                                     // We put the easing on the second keyframe | 
 |   22                                     // so we can test that it is only applied | 
 |   23                                     // to the specified keyframe. | 
 |   24                                     { width: '100px', easing: params.easing }, | 
 |   25                                     { width: '200px' } ], | 
 |   26                                   { duration: 2000, | 
 |   27                                     fill: 'forwards' }); | 
 |   28  | 
 |   29     [ 0, 999, 1000, 1100, 1500, 2000 ].forEach(sampleTime => { | 
 |   30       anim.currentTime = sampleTime; | 
 |   31  | 
 |   32       const portion = (sampleTime - 1000) / 1000; | 
 |   33       const expectedWidth = sampleTime < 1000 | 
 |   34                             ? sampleTime / 10 // first segment is linear | 
 |   35                             : 100 + params.easingFunction(portion) * 100; | 
 |   36       assert_approx_equals(parseFloat(getComputedStyle(target).width), | 
 |   37                            expectedWidth, | 
 |   38                            0.01, | 
 |   39                            'The width should be approximately ' + | 
 |   40                            `${expectedWidth} at ${sampleTime}ms`); | 
 |   41     }); | 
 |   42   }, `A ${params.desc} on a keyframe affects the resulting style`); | 
 |   43 }); | 
 |   44  | 
 |   45 // Test that a linear-equivalent cubic-bezier easing applied to a keyframe does | 
 |   46 // not alter (including clamping) the result. | 
 |   47  | 
 |   48 gEasingTests.forEach(params => { | 
 |   49   const linearEquivalentEasings = [ 'cubic-bezier(0, 0, 0, 0)', | 
 |   50                                     'cubic-bezier(1, 1, 1, 1)' ]; | 
 |   51   test(function(t) { | 
 |   52     linearEquivalentEasings.forEach(linearEquivalentEasing => { | 
 |   53       const timing = { duration: 1000, | 
 |   54                        fill: 'forwards', | 
 |   55                        easing: params.easing }; | 
 |   56  | 
 |   57       const linearTarget = createDiv(t); | 
 |   58       const linearAnim = linearTarget.animate([ { width: '0px' }, | 
 |   59                                                 { width: '100px' } ], | 
 |   60                                               timing); | 
 |   61  | 
 |   62       const equivalentTarget = createDiv(t); | 
 |   63       const equivalentAnim = | 
 |   64         equivalentTarget.animate([ { width: '0px', | 
 |   65                                      easing: linearEquivalentEasing }, | 
 |   66                                    { width: '100px' } ], | 
 |   67                                  timing); | 
 |   68  | 
 |   69       [ 0, 250, 500, 750, 1000 ].forEach(sampleTime => { | 
 |   70         linearAnim.currentTime = sampleTime; | 
 |   71         equivalentAnim.currentTime = sampleTime; | 
 |   72  | 
 |   73         assert_equals(getComputedStyle(linearTarget).width, | 
 |   74                       getComputedStyle(equivalentTarget).width, | 
 |   75                       `The 'width' of the animated elements should be equal ` + | 
 |   76                       `at ${sampleTime}ms`); | 
 |   77       }); | 
 |   78     }); | 
 |   79   }, 'Linear-equivalent cubic-bezier keyframe easing applied to an effect ' + | 
 |   80      `with a ${params.desc} does not alter the result`); | 
 |   81 }); | 
 |   82  | 
 |   83 // Test that different easing functions correctly handle inputs outside the | 
 |   84 // range [0, 1]. This only occurs when we have an easing specified on the | 
 |   85 // effect that produces a value outside [0, 1] which we then pass to an easing | 
 |   86 // on a keyframe. | 
 |   87  | 
 |   88 function assert_style_left_at(animation, time, easingFunction) { | 
 |   89   animation.currentTime = time; | 
 |   90   var portion = time / animation.effect.timing.duration; | 
 |   91   assert_approx_equals(pxToNum(getComputedStyle(animation.effect.target).left), | 
 |   92                        easingFunction(portion) * 100, | 
 |   93                        0.01, | 
 |   94                        'The left of the animation should be approximately ' + | 
 |   95                        easingFunction(portion) * 100 + ' at ' + time + 'ms'); | 
 |   96 } | 
 |   97  | 
 |   98 test(function(t) { | 
 |   99   var target = createDiv(t); | 
 |  100   target.style.position = 'absolute'; | 
 |  101   var anim = target.animate([ { left: '0px', easing: 'step-start' }, | 
 |  102                               { left: '100px' } ], | 
 |  103                             { duration: 1000, | 
 |  104                               fill: 'forwards', | 
 |  105                               easing: 'cubic-bezier(0, 1.5, 1, 1.5)' }); | 
 |  106  | 
 |  107   // The bezier function produces values greater than 1 (but always less than 2) | 
 |  108   // in (0.23368794, 1) | 
 |  109   anim.currentTime = 0; | 
 |  110   assert_equals(getComputedStyle(target).left, '100px'); | 
 |  111   anim.currentTime = 230; | 
 |  112   assert_equals(getComputedStyle(target).left, '100px'); | 
 |  113   anim.currentTime = 250; | 
 |  114   assert_equals(getComputedStyle(target).left, '200px'); | 
 |  115   anim.currentTime = 1000; | 
 |  116   assert_equals(getComputedStyle(target).left, '100px'); | 
 |  117 }, 'step-start easing with input progress greater than 1'); | 
 |  118  | 
 |  119 test(function(t) { | 
 |  120   var target = createDiv(t); | 
 |  121   target.style.position = 'absolute'; | 
 |  122   var anim = target.animate([ { left: '0px', easing: 'step-end' }, | 
 |  123                               { left: '100px' } ], | 
 |  124                             { duration: 1000, | 
 |  125                               fill: 'forwards', | 
 |  126                               easing: 'cubic-bezier(0, 1.5, 1, 1.5)' }); | 
 |  127  | 
 |  128   // The bezier function produces values greater than 1 (but always less than 2) | 
 |  129   // in (0.23368794, 1) | 
 |  130   anim.currentTime = 0; | 
 |  131   assert_equals(getComputedStyle(target).left, '0px'); | 
 |  132   anim.currentTime = 230; | 
 |  133   assert_equals(getComputedStyle(target).left, '0px'); | 
 |  134   anim.currentTime = 250; | 
 |  135   assert_equals(getComputedStyle(target).left, '100px'); | 
 |  136   anim.currentTime = 1000; | 
 |  137   assert_equals(getComputedStyle(target).left, '100px'); | 
 |  138 }, 'step-end easing with input progress greater than 1'); | 
 |  139  | 
 |  140 test(function(t) { | 
 |  141   var target = createDiv(t); | 
 |  142   target.style.position = 'absolute'; | 
 |  143   var anim = target.animate([ { left: '0px', easing: 'step-end' }, | 
 |  144                               { left: '100px' } ], | 
 |  145                             { duration: 1000, | 
 |  146                               fill: 'forwards', | 
 |  147                               easing: 'cubic-bezier(0, 3, 1, 3)' }); | 
 |  148  | 
 |  149   // The bezier function produces values greater than 2 (but always less than 3) | 
 |  150   // in the range (~0.245, ~0.882) | 
 |  151   anim.currentTime = 0; | 
 |  152   assert_equals(getComputedStyle(target).left, '0px'); | 
 |  153   anim.currentTime = 500; | 
 |  154   assert_equals(getComputedStyle(target).left, '200px'); | 
 |  155   anim.currentTime = 900; | 
 |  156   assert_equals(getComputedStyle(target).left, '100px'); | 
 |  157 }, 'step-end easing with input progress greater than 2'); | 
 |  158  | 
 |  159 test(function(t) { | 
 |  160   var target = createDiv(t); | 
 |  161   target.style.position = 'absolute'; | 
 |  162   var anim = target.animate([ { left: '0px', easing: 'step-start' }, | 
 |  163                               { left: '100px' } ], | 
 |  164                             { duration: 1000, | 
 |  165                               fill: 'forwards', | 
 |  166                               easing: 'cubic-bezier(0, -0.5, 1, -0.5)' }); | 
 |  167  | 
 |  168   // The bezier function produces negative values (but always greater than -1) | 
 |  169   // in (0, 0.766312060) | 
 |  170   anim.currentTime = 0; | 
 |  171   assert_equals(getComputedStyle(target).left, '100px'); | 
 |  172   anim.currentTime = 750; | 
 |  173   assert_equals(getComputedStyle(target).left, '0px'); | 
 |  174   anim.currentTime = 800; | 
 |  175   assert_equals(getComputedStyle(target).left, '100px'); | 
 |  176   anim.currentTime = 1000; | 
 |  177   assert_equals(getComputedStyle(target).left, '100px'); | 
 |  178 }, 'step-start easing with input progress less than 0'); | 
 |  179  | 
 |  180 test(function(t) { | 
 |  181   var target = createDiv(t); | 
 |  182   target.style.position = 'absolute'; | 
 |  183   var anim = target.animate([ { left: '0px', easing: 'step-start' }, | 
 |  184                               { left: '100px' } ], | 
 |  185                             { duration: 1000, | 
 |  186                               fill: 'forwards', | 
 |  187                               easing: 'cubic-bezier(0, -2, 1, -2)' }); | 
 |  188  | 
 |  189   // The bezier function produces values less than -1 (but always greater than | 
 |  190   // -2) in the range (~0.118, ~0.755) | 
 |  191   anim.currentTime = 0; | 
 |  192   assert_equals(getComputedStyle(target).left, '100px'); | 
 |  193   anim.currentTime = 100; | 
 |  194   assert_equals(getComputedStyle(target).left, '0px'); | 
 |  195   anim.currentTime = 500; | 
 |  196   assert_equals(getComputedStyle(target).left, '-100px'); | 
 |  197   anim.currentTime = 1000; | 
 |  198   assert_equals(getComputedStyle(target).left, '100px'); | 
 |  199 }, 'step-start easing with input progress less than -1'); | 
 |  200  | 
 |  201 test(function(t) { | 
 |  202   var target = createDiv(t); | 
 |  203   target.style.position = 'absolute'; | 
 |  204   var anim = target.animate([ { left: '0px', easing: 'step-end' }, | 
 |  205                               { left: '100px' } ], | 
 |  206                             { duration: 1000, | 
 |  207                               fill: 'forwards', | 
 |  208                               easing: 'cubic-bezier(0, -0.5, 1, -0.5)' }); | 
 |  209  | 
 |  210   // The bezier function produces negative values (but always greater than -1) | 
 |  211   // in (0, 0.766312060) | 
 |  212   anim.currentTime = 0; | 
 |  213   assert_equals(getComputedStyle(target).left, '0px'); | 
 |  214   anim.currentTime = 750; | 
 |  215   assert_equals(getComputedStyle(target).left, '-100px'); | 
 |  216   anim.currentTime = 800; | 
 |  217   assert_equals(getComputedStyle(target).left, '0px'); | 
 |  218   anim.currentTime = 1000; | 
 |  219   assert_equals(getComputedStyle(target).left, '100px'); | 
 |  220 }, 'step-end easing with input progress less than 0'); | 
 |  221  | 
 |  222 test(function(t) { | 
 |  223   var target = createDiv(t); | 
 |  224   target.style.position = 'absolute'; | 
 |  225   var anim = target.animate( | 
 |  226     // http://cubic-bezier.com/#.5,1,.5,0 | 
 |  227     [ { left: '0px', easing: 'cubic-bezier(0.5, 1, 0.5, 0)' }, | 
 |  228       { left: '100px' } ], | 
 |  229       { duration: 1000, | 
 |  230         fill: 'forwards', | 
 |  231         easing: 'cubic-bezier(0, 1.5, 1, 1.5)' }); | 
 |  232   var keyframeEasing = function(x) { | 
 |  233     assert_greater_than_equal(x, 0.0, | 
 |  234       'This function should be called in [0, 1.0] range'); | 
 |  235     assert_less_than_equal(x, 1.0, | 
 |  236       'This function should be called in [0, 1.0] range'); | 
 |  237     return cubicBezier(0.5, 1, 0.5, 0)(x); | 
 |  238   } | 
 |  239   var keyframeEasingExtrapolated = function(x) { | 
 |  240     assert_greater_than(x, 1.0, | 
 |  241       'This function should be called in (1.0, infinity) range'); | 
 |  242     // p3x + (p2y - p3y) / (p2x - p3x) * (x - p3x) | 
 |  243     return 1.0 + (0 - 1) / (0.5 - 1) * (x - 1.0); | 
 |  244   } | 
 |  245   var effectEasing = function(x) { | 
 |  246     return cubicBezier(0, 1.5, 1, 1.5)(x); | 
 |  247   } | 
 |  248  | 
 |  249   // The effect-easing produces values greater than 1 in (0.23368794, 1) | 
 |  250   assert_style_left_at(anim, 0, function(x) { | 
 |  251     return keyframeEasing(effectEasing(x)); | 
 |  252   }); | 
 |  253   assert_style_left_at(anim, 230, function(x) { | 
 |  254     return keyframeEasing(effectEasing(x)); | 
 |  255   }); | 
 |  256   assert_style_left_at(anim, 240, function(x) { | 
 |  257     return keyframeEasingExtrapolated(effectEasing(x)); | 
 |  258   }); | 
 |  259   // Near the extreme point of the effect-easing function | 
 |  260   assert_style_left_at(anim, 700, function(x) { | 
 |  261     return keyframeEasingExtrapolated(effectEasing(x)); | 
 |  262   }); | 
 |  263   assert_style_left_at(anim, 990, function(x) { | 
 |  264     return keyframeEasingExtrapolated(effectEasing(x)); | 
 |  265   }); | 
 |  266   assert_style_left_at(anim, 1000, function(x) { | 
 |  267     return keyframeEasing(effectEasing(x)); | 
 |  268   }); | 
 |  269 }, 'cubic-bezier easing with input progress greater than 1'); | 
 |  270  | 
 |  271 test(function(t) { | 
 |  272   var target = createDiv(t); | 
 |  273   target.style.position = 'absolute'; | 
 |  274   var anim = target.animate( | 
 |  275     // http://cubic-bezier.com/#0,1.5,1,1.5 | 
 |  276     [ { left: '0px', easing: 'cubic-bezier(0, 1.5, 1, 1.5)' }, | 
 |  277       { left: '100px' } ], | 
 |  278       { duration: 1000, | 
 |  279         fill: 'forwards', | 
 |  280         easing: 'cubic-bezier(0, 1.5, 1, 1.5)' }); | 
 |  281   var easing = function(x) { | 
 |  282     assert_greater_than_equal(x, 0.0, | 
 |  283       'This function should be called in [0, 1.0] range'); | 
 |  284     assert_less_than_equal(x, 1.0, | 
 |  285       'This function should be called in [0, 1.0] range'); | 
 |  286     return cubicBezier(0, 1.5, 1, 1.5)(x); | 
 |  287   } | 
 |  288   var easingExtrapolated = function(x) { | 
 |  289     assert_greater_than(x, 1.0, | 
 |  290       'This function should be called in negative range'); | 
 |  291     // For cubic-bezier(0, 1.5, 1, 1.5), the tangent at the | 
 |  292     // endpoint (x = 1.0) is infinity so we should just return 1.0. | 
 |  293     return 1.0; | 
 |  294   } | 
 |  295  | 
 |  296   // The effect-easing produces values greater than 1 in (0.23368794, 1) | 
 |  297   assert_style_left_at(anim, 0, function(x) { | 
 |  298     return easing(easing(x)) | 
 |  299   }); | 
 |  300   assert_style_left_at(anim, 230, function(x) { | 
 |  301     return easing(easing(x)) | 
 |  302   }); | 
 |  303   assert_style_left_at(anim, 240, function(x) { | 
 |  304     return easingExtrapolated(easing(x)); | 
 |  305   }); | 
 |  306   // Near the extreme point of the effect-easing function | 
 |  307   assert_style_left_at(anim, 700, function(x) { | 
 |  308     return easingExtrapolated(easing(x)); | 
 |  309   }); | 
 |  310   assert_style_left_at(anim, 990, function(x) { | 
 |  311     return easingExtrapolated(easing(x)); | 
 |  312   }); | 
 |  313   assert_style_left_at(anim, 1000, function(x) { | 
 |  314     return easing(easing(x)) | 
 |  315   }); | 
 |  316 }, 'cubic-bezier easing with input progress greater than 1 and where the ' + | 
 |  317    'tangent on the upper boundary is infinity'); | 
 |  318  | 
 |  319 test(function(t) { | 
 |  320   var target = createDiv(t); | 
 |  321   target.style.position = 'absolute'; | 
 |  322   var anim = target.animate( | 
 |  323     // http://cubic-bezier.com/#.5,1,.5,0 | 
 |  324     [ { left: '0px', easing: 'cubic-bezier(0.5, 1, 0.5, 0)' }, | 
 |  325       { left: '100px' } ], | 
 |  326       { duration: 1000, | 
 |  327         fill: 'forwards', | 
 |  328         easing: 'cubic-bezier(0, -0.5, 1, -0.5)' }); | 
 |  329   var keyframeEasing = function(x) { | 
 |  330     assert_greater_than_equal(x, 0.0, | 
 |  331       'This function should be called in [0, 1.0] range'); | 
 |  332     assert_less_than_equal(x, 1.0, | 
 |  333       'This function should be called in [0, 1.0] range'); | 
 |  334     return cubicBezier(0.5, 1, 0.5, 0)(x); | 
 |  335   } | 
 |  336   var keyframeEasingExtrapolated = function(x) { | 
 |  337     assert_less_than(x, 0.0, | 
 |  338       'This function should be called in negative range'); | 
 |  339     // p0x + (p1y - p0y) / (p1x - p0x) * (x - p0x) | 
 |  340     return (1 / 0.5) * x; | 
 |  341   } | 
 |  342   var effectEasing = function(x) { | 
 |  343     return cubicBezier(0, -0.5, 1, -0.5)(x); | 
 |  344   } | 
 |  345  | 
 |  346   // The effect-easing produces negative values in (0, 0.766312060) | 
 |  347   assert_style_left_at(anim, 0, function(x) { | 
 |  348     return keyframeEasing(effectEasing(x)); | 
 |  349   }); | 
 |  350   assert_style_left_at(anim, 10, function(x) { | 
 |  351     return keyframeEasingExtrapolated(effectEasing(x)); | 
 |  352   }); | 
 |  353   // Near the extreme point of the effect-easing function | 
 |  354   assert_style_left_at(anim, 300, function(x) { | 
 |  355     return keyframeEasingExtrapolated(effectEasing(x)); | 
 |  356   }); | 
 |  357   assert_style_left_at(anim, 750, function(x) { | 
 |  358     return keyframeEasingExtrapolated(effectEasing(x)); | 
 |  359   }); | 
 |  360   assert_style_left_at(anim, 770, function(x) { | 
 |  361     return keyframeEasing(effectEasing(x)); | 
 |  362   }); | 
 |  363   assert_style_left_at(anim, 1000, function(x) { | 
 |  364     return keyframeEasing(effectEasing(x)); | 
 |  365   }); | 
 |  366 }, 'cubic-bezier easing with input progress less than 0'); | 
 |  367  | 
 |  368 test(function(t) { | 
 |  369   var target = createDiv(t); | 
 |  370   target.style.position = 'absolute'; | 
 |  371   var anim = target.animate( | 
 |  372     // http://cubic-bezier.com/#0,-0.5,1,-0.5 | 
 |  373     [ { left: '0px', easing: 'cubic-bezier(0, -0.5, 1, -0.5)' }, | 
 |  374       { left: '100px' } ], | 
 |  375       { duration: 1000, | 
 |  376         fill: 'forwards', | 
 |  377         easing: 'cubic-bezier(0, -0.5, 1, -0.5)' }); | 
 |  378   var easing = function(x) { | 
 |  379     assert_greater_than_equal(x, 0.0, | 
 |  380       'This function should be called in [0, 1.0] range'); | 
 |  381     assert_less_than_equal(x, 1.0, | 
 |  382       'This function should be called in [0, 1.0] range'); | 
 |  383     return cubicBezier(0, -0.5, 1, -0.5)(x); | 
 |  384   } | 
 |  385   var easingExtrapolated = function(x) { | 
 |  386     assert_less_than(x, 0.0, | 
 |  387       'This function should be called in negative range'); | 
 |  388     // For cubic-bezier(0, -0.5, 1, -0.5), the tangent at the | 
 |  389     // endpoint (x = 0.0) is infinity so we should just return 0.0. | 
 |  390     return 0.0; | 
 |  391   } | 
 |  392  | 
 |  393   // The effect-easing produces negative values in (0, 0.766312060) | 
 |  394   assert_style_left_at(anim, 0, function(x) { | 
 |  395     return easing(easing(x)) | 
 |  396   }); | 
 |  397   assert_style_left_at(anim, 10, function(x) { | 
 |  398     return easingExtrapolated(easing(x)); | 
 |  399   }); | 
 |  400   // Near the extreme point of the effect-easing function | 
 |  401   assert_style_left_at(anim, 300, function(x) { | 
 |  402     return easingExtrapolated(easing(x)); | 
 |  403   }); | 
 |  404   assert_style_left_at(anim, 750, function(x) { | 
 |  405     return easingExtrapolated(easing(x)); | 
 |  406   }); | 
 |  407   assert_style_left_at(anim, 770, function(x) { | 
 |  408     return easing(easing(x)) | 
 |  409   }); | 
 |  410   assert_style_left_at(anim, 1000, function(x) { | 
 |  411     return easing(easing(x)) | 
 |  412   }); | 
 |  413 }, 'cubic-bezier easing with input progress less than 0 and where the ' + | 
 |  414    'tangent on the lower boundary is infinity'); | 
 |  415  | 
 |  416 </script> | 
 |  417 </body> | 
| OLD | NEW |