tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

animation-timeline-view-functional-notation.tentative.html (19460B)


      1 <!DOCTYPE html>
      2 <title>The animation-timeline: view() notation</title>
      3 <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1">
      4 <link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#view-notation">
      5 <link rel="help" src="https://github.com/w3c/csswg-drafts/issues/7587">
      6 <script src="/resources/testharness.js"></script>
      7 <script src="/resources/testharnessreport.js"></script>
      8 <script src="/web-animations/testcommon.js"></script>
      9 <script src="support/testcommon.js"></script>
     10 <style>
     11  @keyframes fade-in-out-without-timeline-range {
     12    0% { opacity: 0; }
     13    40% { opacity: 1; }
     14    60% { opacity: 1; }
     15    100% { opacity: 0; }
     16  }
     17  @keyframes fade-out-without-timeline-range {
     18    0% { opacity: 1; }
     19    100% { opacity: 0; }
     20  }
     21  @keyframes change-font-size-without-timeline-range {
     22    0% { font-size: 10px; }
     23    100% { font-size: 30px; }
     24  }
     25  @keyframes fade-in-out {
     26    entry 0% { opacity: 0; }
     27    entry 100% { opacity: 1; }
     28    exit 0% { opacity: 1; }
     29    exit 100% { opacity: 0; }
     30  }
     31  @keyframes fade-out {
     32    exit 0% { opacity: 1; }
     33    exit 100% { opacity: 0; }
     34  }
     35  @keyframes change-font-size {
     36    exit 0% { font-size: 10px; }
     37    exit 100% { font-size: 20px; }
     38  }
     39  #container {
     40    width: 200px;
     41    height: 200px;
     42    overflow-y: scroll;
     43    overflow-x: hidden;
     44  }
     45  .target {
     46    width: 100px;
     47    height: 100px;
     48    background-color: red;
     49  }
     50  .content {
     51    width: 400px;
     52    height: 400px;
     53    background-color: blue;
     54  }
     55 </style>
     56 
     57 <body>
     58 <script>
     59 "use strict";
     60 
     61 setup(assert_implements_animation_timeline);
     62 
     63 const createTargetWithStuff = function(t, divClasses) {
     64  let container = document.createElement('div');
     65  container.id = 'container';
     66  document.body.appendChild(container);
     67 
     68  // *** When testing inset
     69  // <div id='container'>
     70  //   <div class='content'></div>
     71  //   <div class='target'></div>
     72  //   <div class='content'></div>
     73  // </div>
     74  // *** When testing axis
     75  // <div id='container'>
     76  //   <div class='target'></div>
     77  //   <div class='content'></div>
     78  // </div>
     79 
     80  let divs = [];
     81  let target;
     82  for(let className of divClasses) {
     83    let div = document.createElement('div');
     84    div.className = className;
     85    container.appendChild(div);
     86 
     87    divs.push(div);
     88    if(className === 'target')
     89      target = div;
     90  }
     91 
     92  if (t && typeof t.add_cleanup === 'function') {
     93    t.add_cleanup(() => {
     94      for(let div of divs)
     95        div.remove();
     96      container.remove();
     97    });
     98  }
     99 
    100  return [container, target];
    101 };
    102 
    103 async function scrollLeft(element, value) {
    104  element.scrollLeft = value;
    105  await waitForNextFrame();
    106 }
    107 
    108 async function scrollTop(element, value) {
    109  element.scrollTop = value;
    110  await waitForNextFrame();
    111 }
    112 
    113 // ---------------------------------
    114 // Tests without timeline range name
    115 // ---------------------------------
    116 
    117 promise_test(async t => {
    118  let [container, div] = createTargetWithStuff(t, ['content', 'target', 'content']);
    119  await runAndWaitForFrameUpdate(() => {
    120    container.style.overflow = 'hidden';
    121    div.style.animation = "fade-in-out-without-timeline-range 1s linear forwards";
    122    div.style.animationTimeline = "view()";
    123 
    124  });
    125  // So the range is [200px, 500px].
    126  await scrollTop(container, 200);
    127  assert_equals(getComputedStyle(div).opacity, '0', 'At 0%');
    128  await scrollTop(container, 260);
    129  assert_equals(getComputedStyle(div).opacity, '0.5', 'At 20%');
    130  await scrollTop(container, 320);
    131  assert_equals(getComputedStyle(div).opacity, '1', 'At 40%');
    132 
    133  await scrollTop(container, 380);
    134  assert_equals(getComputedStyle(div).opacity, '1', 'At 60%');
    135  await scrollTop(container, 440);
    136  assert_equals(getComputedStyle(div).opacity, '0.5', 'At 80%');
    137  await scrollTop(container, 500);
    138  assert_equals(getComputedStyle(div).opacity, '0', 'At 100%');
    139 }, 'animation-timeline: view() without timeline range name');
    140 
    141 promise_test(async t => {
    142  let [container, div] = createTargetWithStuff(t, ['content', 'target', 'content']);
    143  await runAndWaitForFrameUpdate(() => {
    144    container.style.overflow = 'hidden';
    145    div.style.animation = "fade-in-out-without-timeline-range 1s linear forwards";
    146    div.style.animationTimeline = "view(50px)";
    147  });
    148  // So the range is [250px, 450px].
    149 
    150  await scrollTop(container, 250);
    151  assert_equals(getComputedStyle(div).opacity, '0', 'At 0%');
    152  await scrollTop(container, 290);
    153  assert_equals(getComputedStyle(div).opacity, '0.5', 'At 20%');
    154  await scrollTop(container, 330);
    155  assert_equals(getComputedStyle(div).opacity, '1', 'At 40%');
    156 
    157  await scrollTop(container, 370);
    158  assert_equals(getComputedStyle(div).opacity, '1', 'At 60%');
    159  await scrollTop(container, 410);
    160  assert_equals(getComputedStyle(div).opacity, '0.5', 'At 80%');
    161  await scrollTop(container, 450);
    162  assert_equals(getComputedStyle(div).opacity, '0', 'At 100%');
    163 }, 'animation-timeline: view(50px) without timeline range name');
    164 
    165 promise_test(async t => {
    166  let [container, div] = createTargetWithStuff(t, ['content', 'target', 'content']);
    167  await runAndWaitForFrameUpdate(() => {
    168    container.style.overflow = 'hidden';
    169    div.style.animation = "fade-in-out-without-timeline-range 1s linear forwards";
    170    div.style.animationTimeline = "view(auto 50px)";
    171  });
    172  // So the range is [250px, 500px].
    173 
    174  await scrollTop(container, 250);
    175  assert_equals(getComputedStyle(div).opacity, '0', 'At 0%');
    176  await scrollTop(container, 300);
    177  assert_equals(getComputedStyle(div).opacity, '0.5', 'At 20%');
    178  await scrollTop(container, 350);
    179  assert_equals(getComputedStyle(div).opacity, '1', 'At 40%');
    180 
    181  await scrollTop(container, 400);
    182  assert_equals(getComputedStyle(div).opacity, '1', 'At 60%');
    183  await scrollTop(container, 450);
    184  assert_equals(getComputedStyle(div).opacity, '0.5', 'At 80%');
    185  await scrollTop(container, 500);
    186  assert_equals(getComputedStyle(div).opacity, '0', 'At 100%');
    187 }, 'animation-timeline: view(auto 50px) without timeline range name');
    188 
    189 promise_test(async t => {
    190  let [container, div] = createTargetWithStuff(t, ['target', 'content']);
    191  await runAndWaitForFrameUpdate(() => {
    192    container.style.overflow = 'hidden';
    193    div.style.animation = "fade-out-without-timeline-range 1s linear forwards";
    194    div.style.animationTimeline = "view(inline)";
    195  });
    196  // So the range is [-200px, 100px], but it is impossible to scroll to the
    197  // negative part.
    198 
    199  await scrollLeft(container, 0);
    200  assert_approx_equals(parseFloat(getComputedStyle(div).opacity), 0.33333,
    201                       0.00001, 'At 66.7%');
    202  // Note: 20% for each 60px.
    203  await scrollLeft(container, 40);
    204  assert_equals(getComputedStyle(div).opacity, '0.2', 'At 80%');
    205  await scrollLeft(container, 100);
    206  assert_equals(getComputedStyle(div).opacity, '0', 'At 100%');
    207 }, 'animation-timeline: view(inline) without timeline range name');
    208 
    209 promise_test(async t => {
    210  let [container, div] = createTargetWithStuff(t, ['target', 'content']);
    211  await runAndWaitForFrameUpdate(() => {
    212    container.style.overflow = 'hidden';
    213    div.style.animation = "fade-out-without-timeline-range 1s linear forwards";
    214    div.style.animationTimeline = "view(x)";
    215  });
    216  // So the range is [-200px, 100px], but it is impossible to scroll to the
    217  // negative part.
    218 
    219  await scrollLeft(container, 0);
    220  assert_approx_equals(parseFloat(getComputedStyle(div).opacity), 0.33333,
    221                       0.00001, 'At 66.7%');
    222  // Note: 20% for each 60px.
    223  await scrollLeft(container, 40);
    224  assert_equals(getComputedStyle(div).opacity, '0.2', 'At 80%');
    225  await scrollLeft(container, 100);
    226  assert_equals(getComputedStyle(div).opacity, '0', 'At 100%');
    227 }, 'animation-timeline: view(x) without timeline range name');
    228 
    229 promise_test(async t => {
    230  let [container, div] = createTargetWithStuff(t, ['target', 'content']);
    231  await runAndWaitForFrameUpdate(() => {
    232    div.style.animation = "fade-out-without-timeline-range 1s linear forwards";
    233    div.style.animationTimeline = "view(y)";
    234  });
    235  // So the range is [-200px, 100px], but it is impossible to scroll to the
    236  // negative part.
    237 
    238  await scrollTop(container, 0);
    239  assert_approx_equals(parseFloat(getComputedStyle(div).opacity), 0.33333,
    240                       0.00001, 'At 66.7%');
    241  // Note: 20% for each 60px.
    242  await scrollTop(container, 40);
    243  assert_equals(getComputedStyle(div).opacity, '0.2', 'At 80%');
    244  await scrollTop(container, 100);
    245  assert_equals(getComputedStyle(div).opacity, '0', 'At 100%');
    246 }, 'animation-timeline: view(y) without timeline range name');
    247 
    248 promise_test(async t => {
    249  let [container, div] = createTargetWithStuff(t, ['target', 'content']);
    250  await runAndWaitForFrameUpdate(() => {
    251    container.style.overflow = 'hidden';
    252    div.style.animation = "fade-out-without-timeline-range 1s linear forwards";
    253    div.style.animationTimeline = "view(x 50px)";
    254  });
    255  // So the range is [-150px, 50px], but it is impossible to scroll to the
    256  // negative part.
    257 
    258  // Note: 25% for each 50px.
    259  await scrollLeft(container, 0);
    260  assert_equals(getComputedStyle(div).opacity, '0.25', 'At 75%');
    261  await scrollLeft(container, 10);
    262  assert_equals(getComputedStyle(div).opacity, '0.2', 'At 80%');
    263  await scrollLeft(container, 50);
    264  assert_equals(getComputedStyle(div).opacity, '0', 'At 100%');
    265 }, 'animation-timeline: view(x 50px) without timeline range name');
    266 
    267 promise_test(async t => {
    268  let [container, div] = createTargetWithStuff(t, ['target', 'content']);
    269  await runAndWaitForFrameUpdate(() => {
    270    container.style.overflow = 'hidden';
    271    div.style.animation
    272      = "fade-out-without-timeline-range 1s linear forwards, " +
    273        "change-font-size-without-timeline-range 1s linear forwards";
    274    div.style.animationTimeline = "view(50px), view(inline 50px)";
    275  });
    276 
    277  await scrollLeft(container, 0);
    278  assert_equals(getComputedStyle(div).fontSize, '25px', 'At 75% inline');
    279  await scrollLeft(container, 10);
    280  assert_equals(getComputedStyle(div).fontSize, '26px', 'At 80% inline');
    281  await scrollLeft(container, 50);
    282  assert_equals(getComputedStyle(div).fontSize, '30px', 'At 100% inline');
    283 
    284  await scrollLeft(container, 0);
    285 
    286  await scrollTop(container, 0);
    287  assert_equals(getComputedStyle(div).opacity, '0.25', 'At 75% block');
    288  await scrollTop(container, 10);
    289  assert_equals(getComputedStyle(div).opacity, '0.2', 'At 80% block');
    290  await scrollTop(container, 50);
    291  assert_equals(getComputedStyle(div).opacity, '0', 'At 100% block');
    292 
    293  await scrollLeft(container, 10);
    294  await scrollTop(container, 10);
    295  assert_equals(getComputedStyle(div).fontSize, '26px', 'At 80% inline');
    296  assert_equals(getComputedStyle(div).opacity, '0.2', 'At 80% block');
    297 }, 'animation-timeline: view(50px), view(inline 50px) without timeline range ' +
    298   'name');
    299 
    300 promise_test(async t => {
    301  let [container, div] = createTargetWithStuff(t, ['target', 'content']);
    302  await runAndWaitForFrameUpdate(() => {
    303    container.style.overflow = 'hidden';
    304    div.style.animation = "fade-out-without-timeline-range 1s linear forwards";
    305    div.style.animationTimeline = "view(inline)";
    306  });
    307  await scrollLeft(container, 0);
    308  assert_approx_equals(parseFloat(getComputedStyle(div).opacity), 0.33333,
    309                       0.00001, 'At 66.7%');
    310  await scrollLeft(container, 40);
    311  assert_equals(getComputedStyle(div).opacity, '0.2', 'At 80%');
    312  await scrollLeft(container, 100);
    313  assert_equals(getComputedStyle(div).opacity, '0', 'At 100%');
    314 
    315  div.style.animationTimeline = "view(inline 50px)";
    316  await scrollLeft(container, 0);
    317  assert_equals(getComputedStyle(div).opacity, '0.25', 'At 75%');
    318  await scrollLeft(container, 50);
    319  assert_equals(getComputedStyle(div).opacity, '0', 'At 100%');
    320 }, 'animation-timeline: view(inline) changes to view(inline 50px), without' +
    321   'timeline range name');
    322 
    323 
    324 // ---------------------------------
    325 // Tests with timeline range name
    326 // ---------------------------------
    327 
    328 promise_test(async t => {
    329  let [container, div] = createTargetWithStuff(t, ['content', 'target', 'content']);
    330  await runAndWaitForFrameUpdate(() => {
    331    div.style.animation = "fade-in-out 1s linear forwards";
    332    div.style.animationTimeline = "view()";
    333  });
    334 
    335  await scrollTop(container, 200);
    336  assert_equals(getComputedStyle(div).opacity, '0', 'At entry 0%');
    337  await scrollTop(container, 250);
    338  assert_equals(getComputedStyle(div).opacity, '0.5', 'At entry 50%');
    339  await scrollTop(container, 300);
    340  assert_equals(getComputedStyle(div).opacity, '1', 'At entry 100%');
    341 
    342  await scrollTop(container, 400);
    343  assert_equals(getComputedStyle(div).opacity, '1', 'At exit 0%');
    344  await scrollTop(container, 450);
    345  assert_equals(getComputedStyle(div).opacity, '0.5', 'At exit 50%');
    346  await scrollTop(container, 500);
    347  assert_equals(getComputedStyle(div).opacity, '0', 'At exit 100%');
    348 }, 'animation-timeline: view()');
    349 
    350 promise_test(async t => {
    351  let [container, div] = createTargetWithStuff(t, ['content', 'target', 'content']);
    352  await runAndWaitForFrameUpdate(() => {
    353    div.style.animation = "fade-in-out 1s linear forwards";
    354    div.style.animationTimeline = "view(50px)";
    355  });
    356 
    357  await scrollTop(container, 250);
    358  assert_equals(getComputedStyle(div).opacity, '0', 'At entry 0%');
    359  await scrollTop(container, 300);
    360  assert_equals(getComputedStyle(div).opacity, '0.5', 'At entry 50%');
    361 
    362  await scrollTop(container, 350);
    363  assert_equals(getComputedStyle(div).opacity, '1', 'At entry 100% & exit 0%');
    364 
    365  await scrollTop(container, 400);
    366  assert_equals(getComputedStyle(div).opacity, '0.5', 'At exit 50%');
    367  await scrollTop(container, 450);
    368  assert_equals(getComputedStyle(div).opacity, '0', 'At exit 100%');
    369 }, 'animation-timeline: view(50px)');
    370 
    371 promise_test(async t => {
    372  let [container, div] = createTargetWithStuff(t, ['content', 'target', 'content']);
    373  await runAndWaitForFrameUpdate(() => {
    374    div.style.animation = "fade-in-out 1s linear forwards";
    375    div.style.animationTimeline = "view(auto 50px)";
    376  });
    377 
    378  await scrollTop(container, 250);
    379  assert_equals(getComputedStyle(div).opacity, '0', 'At entry 0%');
    380  await scrollTop(container, 300);
    381  assert_equals(getComputedStyle(div).opacity, '0.5', 'At entry 50%');
    382  await scrollTop(container, 350);
    383  assert_equals(getComputedStyle(div).opacity, '1', 'At entry 100%');
    384 
    385  await scrollTop(container, 400);
    386  assert_equals(getComputedStyle(div).opacity, '1', 'At exit 0%');
    387  await scrollTop(container, 450);
    388  assert_equals(getComputedStyle(div).opacity, '0.5', 'At exit 50%');
    389  await scrollTop(container, 500);
    390  assert_equals(getComputedStyle(div).opacity, '0', 'At exit 100%');
    391 }, 'animation-timeline: view(auto 50px)');
    392 
    393 promise_test(async t => {
    394  let [container, div] = createTargetWithStuff(t, ['target', 'content']);
    395  await runAndWaitForFrameUpdate(() => {
    396    container.style.overflow = 'scroll';
    397    div.style.animation = "fade-out 1s linear forwards";
    398    div.style.animationTimeline = "view(inline)";
    399  });
    400 
    401  await scrollLeft(container, 0);
    402  assert_equals(getComputedStyle(div).opacity, '1', 'At exit 0%');
    403  await scrollLeft(container, 50);
    404  assert_equals(getComputedStyle(div).opacity, '0.5', 'At exit 50%');
    405  await scrollLeft(container, 100);
    406  assert_equals(getComputedStyle(div).opacity, '0', 'At exit 100%');
    407 }, 'animation-timeline: view(inline)');
    408 
    409 promise_test(async t => {
    410  let [container, div] = createTargetWithStuff(t, ['target', 'content']);
    411  await runAndWaitForFrameUpdate(() => {
    412    container.style.overflow = 'scroll';
    413    div.style.animation = "fade-out 1s linear forwards";
    414    div.style.animationTimeline = "view(x)";
    415  });
    416 
    417  await scrollLeft(container, 0);
    418  assert_equals(getComputedStyle(div).opacity, '1', 'At exit 0%');
    419  await scrollLeft(container, 50);
    420  assert_equals(getComputedStyle(div).opacity, '0.5', 'At exit 50%');
    421  await scrollLeft(container, 100);
    422  assert_equals(getComputedStyle(div).opacity, '0', 'At exit 100%');
    423 }, 'animation-timeline: view(x)');
    424 
    425 promise_test(async t => {
    426  let [container, div] = createTargetWithStuff(t, ['target', 'content']);
    427  await runAndWaitForFrameUpdate(() => {
    428    container.style.overflow = 'scroll';
    429    div.style.animation = "fade-out 1s linear forwards";
    430    div.style.animationTimeline = "view(y)";
    431  });
    432 
    433  await scrollTop(container, 0);
    434  assert_equals(getComputedStyle(div).opacity, '1', 'At exit 0%');
    435  await scrollTop(container, 50);
    436  assert_equals(getComputedStyle(div).opacity, '0.5', 'At exit 50%');
    437  await scrollTop(container, 100);
    438  assert_equals(getComputedStyle(div).opacity, '0', 'At exit 100%');
    439 }, 'animation-timeline: view(y)');
    440 
    441 promise_test(async t => {
    442  let [container, div] = createTargetWithStuff(t, ['target', 'content']);
    443  await runAndWaitForFrameUpdate(() => {
    444    container.style.overflowY = 'hidden';
    445    container.style.overflowX = 'scroll';
    446    div.style.animation = "fade-out 1s linear forwards";
    447    div.style.animationTimeline = "view(x 50px)";
    448  });
    449 
    450  await scrollLeft(container, 0);
    451  assert_equals(getComputedStyle(div).opacity, '0.5', 'At exit 50%');
    452  await scrollLeft(container, 50);
    453  assert_equals(getComputedStyle(div).opacity, '0', 'At exit 100%');
    454 }, 'animation-timeline: view(x 50px)');
    455 
    456 promise_test(async t => {
    457  let [container, div] = createTargetWithStuff(t, ['target', 'content']);
    458  await runAndWaitForFrameUpdate(() => {
    459    container.style.overflow = 'scroll';
    460    div.style.animation
    461        = "fade-out 1s linear forwards, change-font-size 1s linear forwards";
    462    div.style.animationTimeline = "view(), view(inline)";
    463  });
    464 
    465  const assert_font_size_equals = (expected, description) => {
    466      assert_approx_equals(parseFloat(getComputedStyle(div).fontSize), parseFloat(expected), 0.0001, 'At exit 0% inline');
    467  };
    468 
    469  await scrollLeft(container, 0);
    470  assert_font_size_equals('10px', 'At exit 0% inline');
    471  await scrollLeft(container, 50);
    472  assert_font_size_equals('15px', 'At exit 50% inline');
    473  await scrollLeft(container, 100);
    474  assert_font_size_equals('20px', 'At exit 100% inline');
    475 
    476  await scrollLeft(container, 0);
    477 
    478  await scrollTop(container, 0);
    479  assert_equals(getComputedStyle(div).opacity, '1', 'At exit 0% block');
    480  await scrollTop(container, 50);
    481  assert_equals(getComputedStyle(div).opacity, '0.5', 'At exit 50% block');
    482  await scrollTop(container, 100);
    483  assert_equals(getComputedStyle(div).opacity, '0', 'At exit 100% block');
    484 
    485  await scrollLeft(container, 50);
    486  await scrollTop(container, 50);
    487  assert_font_size_equals('15px', 'At exit 50% inline');
    488  assert_equals(getComputedStyle(div).opacity, '0.5', 'At exit 50% block');
    489 }, 'animation-timeline: view(), view(inline)');
    490 
    491 promise_test(async t => {
    492  let [container, div] = createTargetWithStuff(t, ['target', 'content']);
    493  await runAndWaitForFrameUpdate(() => {
    494    container.style.overflowY = 'hidden';
    495    container.style.overflowX = 'scroll';
    496    div.style.animation = "fade-out 1s linear forwards";
    497  });
    498 
    499  div.style.animationTimeline = "view(inline)";
    500  await scrollLeft(container, 0);
    501  assert_equals(getComputedStyle(div).opacity, '1', 'At exit 0%');
    502  await scrollLeft(container, 50);
    503  assert_equals(getComputedStyle(div).opacity, '0.5', 'At exit 50%');
    504  await scrollLeft(container, 100);
    505  assert_equals(getComputedStyle(div).opacity, '0', 'At exit 100%');
    506 
    507  div.style.animationTimeline = "view(inline 50px)";
    508  await scrollLeft(container, 0);
    509  assert_equals(getComputedStyle(div).opacity, '0.5', 'At exit 50%');
    510  await scrollLeft(container, 50);
    511  assert_equals(getComputedStyle(div).opacity, '0', 'At exit 100%');
    512 }, 'animation-timeline: view(inline) changes to view(inline 50px)');
    513 
    514 </script>
    515 </body>