double requestAnimationFrame

    Google IO17 “Creating UX that ‘just feels right’ with Progressive Web Apps” https://youtu.be/mmq-KVeO-uU

    Because of the bug introduced in Chrome and some others, we have to use double requestAnimationFrame whenever we find ourselves toggling classes or performing other CSS animations that requires RAF to fire after an action is performed. It’s kinda like an escape hatch to have nice/smooth animation.
    “One weird trick to performant touch-response animations with React” > https://medium.com/@owencm/one-weird-trick-to-performant-touch-response-animations-with-react-9fe4a0838116>
    https://stackoverflow.com/questions/44145740/how-does-double-requestanimationframe-work

    Double RAF is useful for ensuring that animations start before expensive rendering is done. It helps provide smoother user experience by making animations feel reactive. Normal rendering would block the animation from starting. With double RAF as shown here the rendering function safely runs in the main thread after the animation has already started.

    https://github.com/ryanve/draf

    raf.ts from vant:

    1. import Vue from "vue";
    2. /**
    3. * requestAnimationFrame polyfill
    4. */
    5. const isServer: boolean = Vue.prototype.$isServer;
    6. let prev = Date.now();
    7. /* istanbul ignore next */
    8. function fallback(fn: FrameRequestCallback): number {
    9. const curr = Date.now();
    10. const ms = Math.max(0, 16 - (curr - prev));
    11. const id = setTimeout(fn, ms);
    12. prev = curr + ms;
    13. return id;
    14. }
    15. /* istanbul ignore next */
    16. const root = (isServer ? global : window) as Window;
    17. /* istanbul ignore next */
    18. const iRaf = root.requestAnimationFrame || fallback;
    19. /* istanbul ignore next */
    20. const iCancel = root.cancelAnimationFrame || root.clearTimeout;
    21. export function raf(fn: FrameRequestCallback): number {
    22. return iRaf.call(root, fn);
    23. }
    24. // double raf for animation
    25. export function doubleRaf(fn: FrameRequestCallback): void {
    26. raf(() => {
    27. raf(fn);
    28. });
    29. }
    30. export function cancelRaf(id: number) {
    31. iCancel.call(root, id);
    32. }