GithubHelp home page GithubHelp logo

scroll-timeline's Introduction

Scroll-timeline Polyfill

A polyfill of ScrollTimeline and ViewTimeline as defined by the spec.

View a cool demo showing its usage!

Usage

To use this polyfill, import the module into your site and you can start creating animations that use a ScrollTimeline or ViewTimeline.

import 'https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js';

document.getElementById('parallax').animate(
    { transform: ['translateY(0)', 'translateY(100px)']},
    { fill: 'both',
      timeline: new ScrollTimeline({
        source: document.documentElement,
      }),
      rangeStart: new CSSUnitValue(0, 'px'),
      rangeEnd: new CSSUnitValue(200, 'px'),
    });

Also works with CSS Animations that use a view-timeline or scroll-timeline

<script src="https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js"></script>
@keyframes parallax-effect {
  to { transform: translateY(100px) }
}
#parallax {
  animation: parallax-effect linear both;
  animation-timeline: scroll(block root);
  animation-range: 0px 200px;
}

For more details on and use-cases of scroll-driven animations, please refer to https://developer.chrome.com/articles/scroll-driven-animations/ and https://scroll-driven-animations.style/

Contributing

1. Polyfill dev

Running a dev environment

npm i
npm run dev 

Then open the browser http://localhost:3000, choose one of the demos (test) to see how your changes.

2. Configure & Run Tests

Test configurations are available in: test/tests.config.json that file includes:

  1. polyfillFiles: an array of our JS shim / polyfill files, those will be injected in WPT tests files.
  2. harnessTests: an array of WPT harness tests we want to test the polyfill against.
  3. browsers.local: Browser our local selenium-webdriver will test against
  4. browsers.sauce: Browser our local selenium-webdriver will test against in Saucelabs / CI environment.

Run the tests locally

Simple test will serve the WPT tests folder and intercepts requests, if the request path matches a harness test we are interested in polyfilling, it will inject the polyfill.

Required environment variables:

WPT_DIR=test/wpt #defaults to test/wpt
WPT_SERVER_PORT=8081 # choose any port available on your machine

Command

npm run test:simple

Go to localhost:8081/scroll-animations/current-time-nan.html as an example.

Run the tests via Web Driver

Local web driver

Required environment variables:

WPT_DIR=test/wpt #defaults to test/wpt
WPT_SERVER_PORT=8081 # choose any port available on your machine
LOCAL_BROWSER=chrome # choose one of 'chrome', 'edge', 'firefox', 'safari'
LOCAL_WEBDRIVER_BIN=? #/path/to/webdriver-binaries

Command

npm run test:wpt
SauceLabs / CI

Required environment variables:

TEST_ENV=sauce
WPT_DIR=test/wpt #defaults to test/wpt
WPT_SERVER_PORT=8081 # choose any port available on your machine
SC_TUNNEL_ID=sc-wpt-tunnel # please specify 'sc-wpt-tunnel' as a SauceConnect Proxy Tunnel ID

SAUCE_NAME=<secret> # Your saucelabs account username
SAUCE_KEY=<secret> # Your API key

Command

TEST_ENV=sauce npm run test:wpt

scroll-timeline's People

Contributors

argyleink avatar bramus avatar calinoracation avatar dependabot[bot] avatar dream-ellie avatar egirard avatar flackr avatar gaubee avatar jh3y avatar johannesodland avatar kevers-google avatar martijnnieuwenhuizen avatar mehdi-kazemi avatar ogerchikov avatar zouhir avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scroll-timeline's Issues

index.js:29 Non-Inline StyleSheets detected: ScrollTimeline polyfill currently only supports inline styles within style tags

<!doctype html>
<html lang="en">
	<head>
<script type="text/javascript" src="https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js"></script>
</head>
<body heigh="300vh">
	<div>
<svg id="enCOL3QZM1s1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 300 300" shape-rendering="geometricPrecision" text-rendering="geometricPrecision">
<g><g><path d="M199.4,26c-15.3-6.1-32-9.5-49.4-9.5C76.3,16.5,16.5,76.3,16.5,150c0,17.5,3.4,34.2,9.5,49.4" transform="translate(-.6 3.85)" fill="#fff" stroke="#000" stroke-width="28" stroke-miterlimit="10" stroke-dashoffset="7" stroke-dasharray="100,0"/><path d="M100.6,274c15.3,6.1,32,9.5,49.4,9.5c73.7,0,133.5-59.8,133.5-133.5c0-17.5-3.4-34.2-9.5-49.4" fill="#fff" stroke="#000" stroke-width="28" stroke-miterlimit="10"/></g><g><g id="eck_open" transform="translate(142.049995,156.349998)"><polyline points="182.4,196.7 182.4,116 101.7,116" transform="translate(-142.049995,-156.349998)" fill="none" stroke="#000" stroke-width="28" stroke-miterlimit="10"/></g><g id="enCOL3QZM1s8_to" transform="translate(155.950001,143.150002)"><polyline points="115.6,102.8 115.6,183.5 196.3,183.5" transform="translate(-155.950001,-143.150002)" fill="none" stroke="#000" stroke-width="28" stroke-miterlimit="10"/></g></g></g></svg></div>
<script>


document.getElementById('eck_oben').animate(
    { transform: ['translateY(0)', 'translateY(100px)']},
    { duration: 10000, // Totally arbitrary!
      fill: 'both',
      timeline: new ScrollTimeline({
          scrollOffsets: [
              new CSSUnitValue(0, 'px'),
              new CSSUnitValue(200, 'px')
          ]
      })
    });</script>
</body>
</html>

This is my code and I get this error. Actually I need die polyfill in react. Want to animate the SVG file by scrolling.
What do I wrong? Also get this obvious error: Uncaught TypeError: Cannot read properties of null (reading 'animate')
at anim_logo.html:13:36. Try a lot now. This the body height should be endless. I it worked with a weird link von codepen or something. There I came on this library. The text horizontal progress bar. This URL was working without this error and I did it in CSS.

Please help,

tom

PS: I tried in react by my self but it doesn't work well … enabled.io

Return currentTime of null when ScrollTimeline should be inactive.

There are many tests currently failing with Error: assert_equals: Sanity check the timeline is inactive:

  • Canceling an animation with inactive timeline should cause its start time and hold time to be unresolved
  • oncancel event is fired when the timeline is inactive.
  • Finishing idle animation attached to inactive timeline pauses the animation.
  • Finishing running animation attached to inactive timeline pauses the animation.
  • Pause pending task doesn't run when the timeline is inactive.
  • Animation start and current times are correct if scroll timeline is activated after animation.pause call.
  • Play pending task doesn't run when the timeline is inactive.
  • Animation start and current times are correct if scroll timeline is activated after animation.play call.
  • Animation start and current times are correct if scroll timeline is activated after setting start time.
  • Animation current time is correct when the timeline becomes newly inactive and then active again.
  • Setting the start time clears the hold time when the timeline is inactive
  • Setting an unresolved start time sets the hold time to unresolved when the timeline is inactive
  • Setting the start time resolves a pending ready promise when the timelineis inactive
  • Setting an unresolved start time on a play-pending animation makes it idle when the timeline is inactive

Ensuring that we return a null currentTime for an inactive timeline should get us past these errors.

Require timeline names to be `<dashed-ident>`s

A late change in the spec requires that the names of timelines must be <dashed-ident>s. The polyfill still allows just any <custom-ident> as the value for view-timeline-name/scroll-timeline-name, animation-timeline.

Add unit/integration tests

Currently the polyfill does not have any tests.

I suggest we look into adding test and setting up a CI pipeline to check new commits against those tests.

Tests

Should be fairly easy to add some basic tests around timeline time calculations and animations correctly running.

One idea is to import/adapt the wpt tests for ScrollTimeline and run them against the polyfill. I haven't fully thought this through but it seems possible albeit may require us to change tests in a way that we can't easily keep syncing them.

Test harness and CI

Key requirement here is to be able to test against all mainstream browsers.

In the past I have had success using Karma testing framework in conjunction with Sauce Labs to run tests against multiple browsers. But this was some times ago and there may be better solutions now.

Safari support

This polyfill is really cool! It makes use of the CSS Typed Object Model with CSSUnitValue, CSSKeywordValue, and CSSMathSum, none of which Safari supports. Do you think it's worth forking this and working on a version that accounts for this, or am I likely to run into other blockers?

Referring to an unknown timeline throws

Using animation-timeline: unknown; throws an error

Uncaught TypeError: Cannot read properties of null (reading 'timeline')
    at scroll-timeline-css.js:89:18
    at Array.forEach (<anonymous>)
    at scroll-timeline-css.js:87:89

NPM support

First, thank you for such a great polyfill! The performance is much smoother than traditional scroll events. I was curious if this package will be available on NPM? I noticed scroll-timeline-polyfill doesn't exist in the registry, but it looks like everything is set up for this to work. I'm currently wanting to play with this polyfill in a React Codesandbox which uses create react app and doesn't seem to currently support URL imports. I was able to copy the dist file, but was curious if an NPM package will be supported to make things a little easier in these situations.

ViewTimeline does not respond to layout changes

See this demo I put together for the CSSWG issue w3c/csswg-drafts#7778

https://jsbin.com/kibidim/edit?html,css,js,output

When you drag the slider the observed subject is moved. The native implementation responds to the updated position but the polyfill does not. I think that for view timeline we could probably use IntersectionObserver and/or ResizeObserver to detect when the position of the observed subject changes with respect to the scrolling box and trigger an update.

Typescript Support

It would be great if have typescript support for it and publish it along with the polyfill to npm :)

CSS Polyfill conflicts with browsers that have support enabled

Trying out https://codepen.io/bramus/pen/popYBRz/19bf451ebc93a14378b4d439124a0d61 in stock Chrome works like a charm.

Trying the same demo out in a browser with support (i.e. Chrome with the --enable-experimental-web-platform-features flag or Firefox with layout.css.scroll-linked-animations.enabled set to true) doesn't do anything.

I would have expected the polyfill to only do its thing when @scroll-timeline is not available.

The easy fix would be to wrap the call to initCSSPolyfill() in a if (!CSS.supports("animation-timeline: works")) { … } block.

Implement animation event listeners

ProxyAnimation currently does not currently implement addEventListener or on* for animation events. We should implement these functions and fire the event listeners at the appropriate times so that events work properly with the polyfill.

scrollOffset not working anymore

Hello, can you explain why you removed the possibility to add an offset ? And if there is another way to achieve that (run the animation from a certain point).
And is there any official documentation ? Because I have no idea how to achieve things.

Best regards

Is the public script up to date?

@flackr @bramus @kevers-google
Hello, I've been using this polyfill on a production site for several months. Recently the scrollOffsets properties (as defined in the ScrollTimeline class) stopped functioning as they did when I originally configured the animations... I checked here and saw there had been some updates relating to this, although I admit I do not understand them very well...

On the demo page I noticed that all the ScrollTimeline classes had been replaced by ViewTimeline:

timeline: new ViewTimeline({ subject: container }),
timeRange: 'contain 20% 80%' 

So I tried updating my animations accordingly, but the animations completely break, without any console errors.

I'm using the script referenced in the readme: https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js

Is the above script up to date? How can I get my animations back on track. Thanks!

This is what I currently have for one of my animations:

element.animate(
  [
    { clipPath: 'inset(0% 60% 0% 0%)' },
    { clipPath: 'inset(0% 0% 0% 0%)', offset: 0.46 },
    { clipPath: 'inset(0% 0% 0% 0%)', offset: 0.46 },
    { clipPath: 'inset(0% 60% 0% 0%)' }
  ],
  {
    duration: 1,
    easing: 'cubic-bezier(0,.44,1,.57)',
    fill: "both",
    timeline: new ScrollTimeline({
        scrollSource: document.documentElement,
        scrollOffsets: [
          { target: element, edge: 'end', threshold: 0 },
          { target: element, edge: 'start', threshold: 0 }
        ],
        fill: 'both',
    }),
  }
);

The goal is to have the above keyframes start as the top of the element first comes into the bottom of the viewport, and end as the bottom of the element leaves the top of the viewport. This was working as expected up until recently. Last time I checked it is not. And I'm not sure what exactly it's doing... The animation seems to start before the element comes into the viewport, and it barely gets halfway through before the element has left the viewport. Perhaps the animation timeline is based on the entire document scroll...?

Any suggestions would be so much appreciated. It's very difficult to find support for this on the web. I'm not sure who to ask besides you. Thanks so much!

Implement scrollOffsets behavior.

scroll-timeline-base.js currently allows setting the scroll offsets array but otherwise ignores it. We should follow the chromium implementation of having start/end timeline update the scroll offsets array entries.

Polyfill does not play nice with @layer

When using some of the props inside @layer

@layer foo {
	@supports (animation-timeline: scroll()) {
		/* Hide Warning */
		.warning {
			display: none;
		}
	}
}

… it throws this:

Uncaught DOMException: Failed to execute 'matches' on 'Element': '@layer foo' is not a valid selector.
    at t.getAnimationTimelineOptions (https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js:1:25932)
    at https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js:1:32971
    at https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js:1:33181
    at Array.forEach (<anonymous>)
    at https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js:1:32922

When not using a @layer, it works fine.

@supports (animation-timeline: scroll()) {
	/* Hide Warning */
	.warning {
		display: none;
	}
}

CSS View Timelines are shared?

I’ve created a CoverFlow demo which approaches the problem using the JS side of things. Each <li> is linked to a ViewTimeline, and during its contain phase animations are running. This works fine.

Kapture.2022-10-03.at.16.53.24.mp4

When trying to build a CSS version of it, it doesn’t seem to work: all animations on all <li> elements only run when the very last <li> of the bunch comes into view. It looks like the timeline is shared between all instances, whereas it is expected for each <li> to have their own instance attached.

Kapture.2022-10-03.at.16.55.28.mp4

Used Code:

.cards li {
	view-timeline-name: li-in-and-out-of-view;
	view-timeline-axis: inline;

	animation: 1s linear adjust-z-index;
	animation-timeline: li-in-and-out-of-view;
	animation-time-range: contain 0% 100%;
}

.cards li > img {
	animation: 1s linear rotate-cover;
	animation-timeline: li-in-and-out-of-view;
	animation-time-range: contain 0% 100%;
}

(Used property names follow those the current version of the polyfill supports, not of the latest spec)

Support setting timeline on ProxyAnimation.

Setting the timeline requires custom logic in a set timeline method in proxy-animation.js in order to correctly switch to/from ScrollTimelines and perform the appropriate changes to the animation expected by setting-timeline.tentative.html.

The following tests currently fail with Error: promise_test: Unhandled rejection with value: object "TypeError: Failed to set the 'timeline' property on 'Animation': Failed to convert value to 'AnimationTimeline'.":

  • Setting a scroll timeline on a play-pending animation synchronizes currentTime of the animation with the scroll position.
  • Setting a scroll timeline on a pause-pending animation fixes the currentTime of the animation based on the scroll position once resumed
  • Setting a scroll timeline on a reversed play-pending animation synchronizes the currentTime of the animation with the scroll position.
  • Setting a scroll timeline on a running animation synchronizes the currentTime of the animation with the scroll position.
  • Setting a scroll timeline on a paused animation fixes the currentTime of the animation based on the scroll position when resumed
  • Setting a scroll timeline on a reversed paused animation fixes the currentTime of the animation based on the scroll position when resumed
  • Transitioning from a scroll timeline to a document timeline on a running animation preserves currentTime
  • Transitioning from a scroll timeline to a document timeline on a pause-pending animation preserves currentTime
  • Transitioning from a scroll timeline to a null timeline on a running animation preserves the play state
  • Switching from one scroll timeline to another updates currentTime
  • Switching from a document timeline to a scroll timeline updates currentTime when unpaused via CSS.
  • Switching from a document timeline to a scroll timeline and updating currentTime preserves the new value when unpaused.
  • Switching from a document timeline to a scroll timeline and updating startTime preserves the new value when play is called.

And one test fails with Error: promise_test: Unhandled rejection with value: object "TypeError: Cannot set property timeline of #<t> which has only a getter":

  • Switching from a null timeline to a scroll timeline on an animation with a resolved start time preserved the play state

Testing framework should run with "use strict"

Leaving off a "const/let" on a variable declaration has caused at least 2 build failures when trying to use the library. We should figure out how to run the tests in strict mode to ensure this type of breakage doesn't keep recurring.

Setup unit tests with Jest

Use Jest to unit test the polyfill's time calculations, option parsing, conditional installation and force installation.

Those test should run locally or in CI via npm run test:unit

This is a child task of: #3

ScrollTimeline offsets are no longer respected after last update.

@flackr @bramus @kevers-google

After the latest update (#60) the ScrollTimeline -> scrollOffsets are no longer honored. No matter how I configure the animation bounding offsets, either by element or by static css units, the animation timeline is based on the length of the page, NOT the offsets.

I don't know what to do about this, and all my animations are broken.

Please, if anyone can help me out I would really appreciate it.

Here is an example animation I'm using:

element.animate(
  [
    { clipPath: 'inset(0% 60% 0% 0%)' },
    { clipPath: 'inset(0% 0% 0% 0%)', offset: 0.46 },
    { clipPath: 'inset(0% 0% 0% 0%)', offset: 0.46 },
    { clipPath: 'inset(0% 60% 0% 0%)' }
  ],
  {
    duration: 1,
    easing: 'cubic-bezier(0,.44,1,.57)',
    fill: "both",
    timeline: new ScrollTimeline({
        scrollSource: document.documentElement,
        scrollOffsets: [
          { target: element, edge: 'end', threshold: 0 },
          { target: element, edge: 'start', threshold: 0 }
        ],
        fill: 'both',
    }),
  }
);

The goal is to have the above keyframes start as the top of the element first comes into the bottom of the viewport, and end as the bottom of the element leaves the top of the viewport. This was working as expected up until recently, but now it is not.

How do I remedy this? Thanks in advance!

Does not support strict mode?

Hello everyone,

I made this small pen https://codepen.io/lukasgerm/pen/oNQJbWa which is using the polyfill. But the SDK is throwing an error

ReferenceError: assignment to undeclared variable parts

It is probably related to codepen enabling strict mode by or so (just an assumption). What do you guys suggest here?

Add more demos

We have a bunch of scattered demos for scroll timelines. Specially a few that don't use element-based offsets. I think it will be a good idea to consolidate them all here under the polyfill to showcase different features of scroll animations in one place and also allow polyfill to be exercised in different ways.

Here is the ones I know about:

Handle `auto` duration in the `animation` shorthand

The polyfill can’t handle this, whereas the native implementation does handle it just fine:

animation: reveal auto linear both;

Removing auto from the shorthand makes the polyfill work again

animation: reveal linear both;

Console Errors

The demo projects seem to run fine but when I copy the dist files to my existing application (it's a large angular 14 app, hence tons of style tags in the header ... if that's helpful to know) and link to scroll-timeline.js, I get the errors (pasted below) thrown upon initial load, before I have even attempted to implement any sort of scroll based animations.

Of note: The polyfill does seem to succeed and it turns out I can programmatically create animations via ScrollTimeline.

scroll-timeline-css-parser.js:630 Uncaught TypeError: this.parseError is not a function
    at n.advance (scroll-timeline-css-parser.js:630:18)
    at n.eatUntil (scroll-timeline-css-parser.js:637:12)
    at n.parseSelector (scroll-timeline-css-parser.js:650:10)
    at n.parseQualifiedRule (scroll-timeline-css-parser.js:562:27)
    at n.transpileStyleSheet (scroll-timeline-css-parser.js:79:27)
    at e (scroll-timeline-css.js:39:25)
    at MutationObserver.observe.childList (scroll-timeline-css.js:13:11)
scroll-timeline-css.js:70 Uncaught TypeError: Cannot read properties of null (reading 'animation-timeline')
    at scroll-timeline-css.js:70:24
    at scroll-timeline-css.js:162:24
    at Array.forEach (<anonymous>)
    at scroll-timeline-css.js:153:89

Replace timeline lookup mechanism with `timeline-scope` support

Demos such as /demo/view-timeline-css/with-delays-using-animation-time-range.html track a subject that is a sibling of the animated elements. For those to work properly in the native implementation, one needs to hoist up the scope of the timeline using timeline-scope.

The polyfill however ignores this timeline-scope declaration and performs timeline lookups based on an earlier version of the spec.

I am filing this bug to:

  • Fix the current lookup behavior so that it aligns with the spec.
  • Add support for timeline-scope instead.

The CSS parser accesses code parts that should not be accessed

See https://codepen.io/bramus/pen/MWGozRq/146cdcc8b5b24389d70ac9066d80dcd9?editors=0110 (which is a fork of https://flackr.github.io/scroll-timeline/demo/view-timeline-css/)

The animation in that demo will run during the enter phase, even though that line of code has been commented out.

#box {
	animation: linear 2s reveal forwards;
	animation-timeline: reveal-image;
/* 	animation-time-range: enter 0% 100%; */
}

Same thing happens if you create a Custom Property that has the same name as the property:

#box {
	animation: linear 2s reveal forwards;
	animation-timeline: reveal-image;
 	--animation-time-range: enter 0% 100%;
}

Actual Result: The animation runs during the enter phase
Expected Result: The animation to run during default range, which is cover

Bundle the polyfill with rollup and ensure it runs synchronously

Proposed solution
Compile the es-modules JavaScript source files with microbundle and produce an iife (Immediately invoked function expression) that syncroously appends ScrollTimeline constructor to the Window object.

Why microbundle as a bundler of choice
This bundler module is capable of creating a small, optimized JS bundle from source files using rollup under the hood with Zero-configurations needed.
It is currently used by some other project and polyfills such:

this is a child task of #3

Use SauceLabs for e2e browser integrations tests

Cypress.io has a nice API for writing automated browser test but it does not support Safari and support for FireFox is in Beta, that makes Saucelabs the best option for automated browser testing at this moment.

SauceLabs testing strategies:

1: The Web-animations-js polyfill strategy**

That polyfill have a mix of: JavaScript unit tests and e2e integration tests, all run in CI via Saucelabs which we are planning to use for ScrollTimeline.

Unit tests written in Mocha and running against real browser APIs (not JSDOM) via Karma test runner.

I believe the e2e integration test setup (for WPT, Blink test files) is counter-intuitive and hard to maintain, for those reasons:

  • Karma excels at running JS tests against DOM or web pages as a context, and not running tests in HTML files.
  • Web-animations-js polyfills has a long chain of configurations: a framework-specific task runner modules that pre-processes target files and has a modified testharnessreporter (forked from WPT) as well as custom Karma test harness runners you can see here. Being as close as possible to WPT files is beneficial and the more pre-processing and customization, the harder it will be for us to maintain.

2: Philip Walton's Blog Post on using Saucelabs Rest API read

The solution outline in Philip Walton's (Engineer @ Google) Blog is more straight-forward than Web-animations-js polyfill solution, he uses Mocha (the client side library) to run tests inside the HTML pages, and post those pages to sauce labs using their REST API, all needed there is a custom "failLogger" when the tests are finished, which is 1 JS function that acts as an adapter between Mocha results and Saucelabs.

One note is that the Saucelabs rest API does not support localhost:xxxx addresses, the developer in that post used ngrok and mentioned using Sauce Connect VPN tunnel if it's possible

Frame 1 (1)

3: Using Webdriver with Saucelabs read

I found connect WPT from lcoalhost:xxxx to Saucelabs via a sauce connect tunnel and using selenium web driver to test against a matrix of browsers is the simplest & most effective way to run WPT harness tests, and even do more if needed (screenshots, ref, etc).

Some of the pros:

  • not much pre-processing needed: we only need to inject the polyfill script below the WPT/**/*.html test </title>
  • all tests are ran via WPT test runner, no customization to the runner or reporter.

4: WPT test runner --sauce flag

Monday, April 20, Stephen McGruer from the Chromium project highlighted on the slack channel that we can use --sauce-* flags, they are documented here I believe if this works after we inject the HTML, will even be an improvements to saucelabs' Web Driver implementation


This is a child task of: #3

View Timeline does not work with `animation-time-range: entry;` or `exit`

Safari doesn't throw an error but it just doesn't do anything.

Chrome, throws an Error and a lot of the values in the timing object are NaN

Uncaught TypeError: Failed to execute 'updateTiming' on 'AnimationEffect': Failed to read the 'delay' property from 'OptionalEffectTiming': The provided double value is non-finite.
    at Object.apply (proxy-animation.js:708:30)
    at proxy-animation.js:105:39
    at F (proxy-animation.js:370:18)
    at W (proxy-animation.js:91:24)
    at z (proxy-animation.js:262:24)
    at e.get (proxy-animation.js:1094:36)
    at e.get (proxy-animation.js:1172:56)
    at B (proxy-animation.js:447:20)
    at n.play (proxy-animation.js:1306:5)
    at scroll-timeline-css.js:178:24

Breaks "TypeIt" animations

TL;DR
When this polyfill is imported, it breaks page animations that use TypeIt (https://github.com/alexmacarthur/typeit)

Details
There is a TypeIt animation on the page that works just fine until we add the polyfill in the <script> tag to the html page.

  <script src="https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js" defer></script>
  <script src="https://unpkg.com/[email protected]/dist/index.umd.js" defer></script>

The animation disappears and doesn't work any more.
The same happens if we import the polyfill using "import" in a JS module file.

In my own setup I get the following exception in the browser console:

Uncaught (in promise) TypeError: Cannot set property id of #<e> which has only a getter
    at D (index.umd.js:2:2778)
    at R (index.umd.js:2:4767)
    at Object.go (index.umd.js:2:7725)
    at type.js:27:4

Digging into the polyfill code I found that the proxyAnimation class does not expose a setter for the id:

get id() {
return proxyAnimations.get(this).animation.id;
}

And it looks like the code that throws, is trying to set it.

      , C = e=>e?.getAnimations().find((t=>t.id === e.dataset.tiAnimationId))
      , D = ({cursor: e, frames: t, options: n})=>{
        let r = e.animate(t, n);
        return r.pause(),
        r.id = e.dataset.tiAnimationId,  // <===== THIS IS THE LINE THAT THROWS
        L((()=>{
            L((()=>{
                r.play()
            }
            ))
        }
        )),
        r

As I urgently want to fix it, will a PR with the following patch do the trick?

+  set id(value) {
+    proxyAnimations.get(this).animation.id = value;
+  }

Let me know if that will do it and I can submit a PR asap.

Here is a sandbox project to play with: https://codesandbox.io/s/interesting-buck-yyev82?file=/index.html

Polyfill should co-exist better with native implementation

Here are a few improvements to current polyfill that would make it work better in presence of native implementation.

Polyfill should not install if there is native implementation

Currently polyfill install itself unconditionally. As more browsers implement the API, it should take advantage of the native implementation it if exists. For example majority of the API is implemented on Chrome Canary when web platform experimental flags are used.

Option to Force

It will also be nice to still have the option (not default) of force installing the polyfill to replace the native implementation even if it exists. This can be useful to create demos where we compare the polyfill/native implementation behavior in the same browser.

Detecting sub features

While Chrome implements most of the features of Scroll Timeline but it does not yet support all of them.
For example:

So ideally polyfill should be made granular i.e., use native scroll timeline but implement time range auto or element-based offsets in the polyfill. This is a more involved undertaking that may require re-architecting the polyfill in a major way. So I suggest doing the first two as a first step.

Safari: Unhandled unit type %

Creating this timeline:

const myScrollTimeline = new ScrollTimeline({
    source: document.scrollingElement,
    scrollSource: document.scrollingElement, // For legacy implementations
    orientation: 'block',
    scrollOffsets: [
        new CSSUnitValue(0, '%'),
        new CSSUnitValue(100, '%'),
    ],
});

will throw a TypeError in Safari:

TypeError: Unhandled unit type %

The problem is the use of % as a unit for CSSUnitValue.

Looking at the source, percent is accepted as a unit but % isn't. Looking at how other browsers behave (although it might not be specced that way): they also accept %.

Support anonymous View Timelines (`view()`)

The polyfill can’t handle this:

animation: reveal linear both;
animation-timeline: view();

Switching to a named timeline works fine:

view-timeline: --self;
animation: reveal linear both;
animation-timeline: --self;

Uncaught TypeError: Failed to execute 'updateTiming' on 'AnimationEffect': duration must be non-negative or auto

In https://codepen.io/bramus/pen/WNzZmdP I am trying to animate a horizontal strip .pin-wrap while its parent #sectionPin is in the contain phase.

It should behave like https://codepen.io/bramus/pen/MWVvrEE, but instead I am getting this error in the Console:

Uncaught TypeError: Failed to execute 'updateTiming' on 'AnimationEffect': duration must be non-negative or auto
at Object.apply (proxy-animation.js:708:30)
at proxy-animation.js:105:39
at V (proxy-animation.js:370:18)
at N (proxy-animation.js:91:24)
at _ (proxy-animation.js:262:24)
at e.get (proxy-animation.js:1094:36)
at e.get (proxy-animation.js:1172:56)
at H (proxy-animation.js:447:20)
at n.play (proxy-animation.js:1306:5)
at HTMLDivElement.value [as animate] (proxy-animation.js:1721:20)

Note that the parent is taller than the viewport, which might have to do with this.

Support styles outside of style tag

Currently using the polyfill with CSS styles only works if the styles are inlined into the head:

<style>
  .trigger { view-timeline-name: --trigger; }
  .el { animation-timeline: --trigger; }
</style>

If you put those styles in a file like style.css and link them with:

<link rel="stylesheet" href="style.css" />

The polyfill fails silently because it doesn't consider loaded styles.

Until that's supported, might it be worth adding a console.warn that any styles not inlined won't be detected? Happy to open a PR for this.

@jh3y

Issue with background-loaded pages

I've noticed this weird behavior where the polyfill doesn't work correctly when a page is loaded in the background. When loading the page in the background and focussing the tab once it's been loaded, one can find all scroll-linked animations at 100% progress.

See a recording at https://youtu.be/es1d39VFupA

As you can see it doesn't happen all the time: I only could trigger it in the attempt at the 30" mark. I'm able to reproduce this in Chromium and Firefox (haven't tested Safari).

This also happens for examples that use element-based offsets.

Improve performance and correctness when using multiple ScrollTimelines

Currently when you create multiple ScrollTimelines (even for the same scroller), each one adds a "scroll" event listener which results in the timelines one by one doing the following:

  1. Computing their current time
  2. Updating associated animations

This is both inefficient because subsequent measurements of scroll position (step 1) require cleaning the layout from earlier ScrollTimelines updated animations (step 2), and incorrect because per spec the scroll position is to be sampled once per frame before any animation effects have taken place.

At minimum the polyfill should ensure that all Scrolltimelines attached to a single scroller compute their current time before ticking any animations. This would at least ensure that we don't have multiple style and layout recalculations in a single frame unless more than one scroller changes position in that frame. We should be able to add a test for this as well.

Polyfill not working, when page is reloaded in between

Hello,

I am currently experiencing the following problem:

The animations work just fine, if the page that gets loaded is scrolled all the way to the top or to the bottom.
However, if I reload the page somewhere in between, the animations don't work.

Here is an example of one of my animations.

drahtlosDisplay2Lower.animate(
        {
            backgroundPositionX: ['100%', '0'],
        }, {
            timeline: new ViewTimeline({
                subject: drahtlosDisplay2Lower,
                axis: 'vertical',
            }),
            delay: {phase: 'contain', percent: CSS.percent(35)},
            endDelay: {phase: 'contain', percent: CSS.percent(60)},
            fill: 'both',
        });

I am just about to dig deeper into the issue, but maybe some of you have experienced similar stuff?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.