When I view observable pages in Safari (my default), generator functions that yield results on each cycle seem much slower when the page is first viewed. Re-triggering the generator via an input element sets the generator off more quickly.
For example, in the following, in Safari, the generator takes about 8 seconds to complete all its yielded values when initially opened, but only about 2 seconds when retriggered with the ‘reset’ button. If I view the page in Chrome, I get a consistent time of around 2 seconds whether viewed for the first time or re-triggered.
I tend to use this generator pattern quite frequently when I want to show animations that can be reset with a button, so I’d love to find a fix/workaround for Safari users.
Is this a bug, or am I not using the correct generator pattern?
Neither. Top level generators in Observable are processed via requestAnimationFrame. Safari limits the frame rate (as well as timeouts) until the first user interaction. If you want to utilize the full frame rate you’ll have to make your users start the animation.
You can find more details here:
For animations I would generally recommend to design them in a way that lets you produce a frame for any given point in time. That way you can define the desired duration, and then calculate the current animation offset since the animation start on every yield.
Very helpful ,thanks. I did search the forum for such posts, but my keyword choices didn’t pick this up. I’ll add a ‘start’ button in such cases, which is probably a better UX policy anyway, especially when animation not displayed at the top of the page.
You can await the
visibility() promise in each cell to delay execution until the cell is scrolled into the viewport. However, this still seems to suffer from the same frame rate issues and can also fire too early if some of the preceding content takes a moment to load.