tor-browser

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

scroll-timeline-range-animation.html (5154B)


      1 <!DOCTYPE html>
      2 <title>Scroll timelines and animation attachment ranges</title>
      3 <link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#named-timeline-range">
      4 <link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#animation-range">
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 <script src="/web-animations/testcommon.js"></script>
      8 <script src="support/testcommon.js"></script>
      9 <style>
     10  @keyframes anim {
     11    from { z-index: 0; background-color: skyblue;}
     12    to { z-index: 100; background-color: coral; }
     13  }
     14  #scroller {
     15    border:  10px solid lightgray;
     16    overflow-y: scroll;
     17    width: 200px;
     18    height: 200px;
     19  }
     20  #scroller > div {
     21    margin: 800px 0px;
     22    width: 100px;
     23    height: 100px;
     24  }
     25  #target {
     26    font-size: 10px;
     27    background-color: green;
     28    z-index: -1;
     29  }
     30 </style>
     31 <main id=main>
     32 </main>
     33 
     34 <template id=template_without_scope>
     35  <div id=scroller class=timeline>
     36    <div id=target></div>
     37  </div>
     38 </template>
     39 
     40 <template id=template_with_scope>
     41  <div id=scope>
     42    <div id=target></div>
     43    <div id=scroller class=timeline>
     44      <div></div>
     45    </div>
     46  </div>
     47 </template>
     48 
     49 <script>
     50  setup(assert_implements_animation_timeline);
     51 
     52  function inflate(t, template) {
     53    t.add_cleanup(() => main.replaceChildren());
     54    main.append(template.content.cloneNode(true));
     55  }
     56  async function scrollTop(e, value) {
     57    e.scrollTop = value;
     58    await waitForNextFrame();
     59  }
     60  async function waitForAnimationReady(target) {
     61    await waitForNextFrame();
     62    await Promise.all(target.getAnimations().map(x => x.ready));
     63  }
     64  async function assertValueAt(scroller, target, args) {
     65    await waitForAnimationReady(target);
     66    await scrollTop(scroller, args.scrollTop);
     67    assert_equals(getComputedStyle(target).zIndex, args.expected.toString());
     68  }
     69  function test_animation_range(options, template, desc_suffix) {
     70    if (template === undefined)
     71      template = template_without_scope;
     72    if (desc_suffix === undefined)
     73      desc_suffix = '';
     74 
     75    promise_test(async (t) => {
     76      inflate(t, template);
     77      let scroller = main.querySelector('#scroller');
     78      let target = main.querySelector('#target');
     79      let timeline = main.querySelector('.timeline');
     80      let scope = main.querySelector('#scope');
     81      let maxScroll = scroller.scrollHeight - scroller.clientHeight;
     82 
     83      if (scope != null) {
     84        scope.style.timelineScope = '--t1';
     85      }
     86 
     87      timeline.style.scrollTimeline = '--t1';
     88      target.style.animation = 'anim auto linear';
     89      target.style.animationTimeline = '--t1';
     90      target.style.animationRangeStart = options.rangeStart;
     91      target.style.animationRangeEnd = options.rangeEnd;
     92 
     93      // Accommodates floating point precision errors at the endpoints.
     94      target.style.animationFillMode = 'both';
     95 
     96      // 0%
     97      await assertValueAt(scroller, target,
     98          { scrollTop: options.startOffset, expected: 0 });
     99      // 50%
    100      await assertValueAt(scroller, target,
    101          { scrollTop: (options.startOffset + options.endOffset) / 2, expected: 50 });
    102      // 100%
    103      await assertValueAt(scroller, target,
    104          { scrollTop: options.endOffset, expected: 100 });
    105 
    106      // Test before/after phases (need to clear the fill mode for that).
    107      target.style.animationFillMode = 'initial';
    108      let before_scroll = options.startOffset - 10;
    109      if (before_scroll >= 0) {
    110        await assertValueAt(scroller, target,
    111            { scrollTop: options.startOffset - 10, expected: -1 });
    112      }
    113      let after_scroll = options.startOffset + 10;
    114      if (after_scroll <= scroller.maxmum) {
    115        await assertValueAt(scroller, target,
    116            { scrollTop: options.endOffset + 10, expected: -1 });
    117      }
    118      // Check 50% again without fill mode.
    119      await assertValueAt(scroller, target,
    120          { scrollTop: (options.startOffset + options.endOffset) / 2, expected: 50 });
    121 
    122    }, `Animation with ranges [${options.rangeStart}, ${options.rangeEnd}] ${desc_suffix}`.trim());
    123  }
    124 
    125  test_animation_range({
    126    rangeStart: 'initial',
    127    rangeEnd: 'initial',
    128    startOffset: 0,
    129    endOffset: 1500
    130  });
    131 
    132  test_animation_range({
    133    rangeStart: '0%',
    134    rangeEnd: '100%',
    135    startOffset: 0,
    136    endOffset: 1500
    137  });
    138 
    139  test_animation_range({
    140    rangeStart: '10%',
    141    rangeEnd: '100%',
    142    startOffset: 150,
    143    endOffset: 1500
    144  });
    145 
    146  test_animation_range({
    147    rangeStart: '0%',
    148    rangeEnd: '50%',
    149    startOffset: 0,
    150    endOffset: 750
    151  });
    152 
    153  test_animation_range({
    154    rangeStart: '10%',
    155    rangeEnd: '50%',
    156    startOffset: 150,
    157    endOffset: 750
    158  });
    159 
    160  test_animation_range({
    161    rangeStart: '150px',
    162    rangeEnd: '75em',
    163    startOffset: 150,
    164    endOffset: 750
    165  });
    166 
    167  test_animation_range({
    168    rangeStart: 'calc(1% + 135px)',
    169    rangeEnd: 'calc(70em + 50px)',
    170    startOffset: 150,
    171    endOffset: 750
    172  });
    173 
    174  // Test animation-range via timeline-scope.
    175  test_animation_range({
    176    rangeStart: 'calc(1% + 135px)',
    177    rangeEnd: 'calc(70em + 50px)',
    178    startOffset: 150,
    179    endOffset: 750
    180  }, template_with_scope, '(scoped)');
    181 
    182 </script>