FLIP


(Last modified: )
/**
 * FLIP
 * F = First
 * L = Last
 * I = Invert
 * P = Play
 *
 * @source Keyframers, https://codepen.io/team/keyframers
 * @param {Function} doSomething Function that causes a layout change.
 * @param {Node}     firstEl     The element to track at the start.
 * @param {Fuction}  getLastEl   Function to determine the element at the end. Defaults to firstEl.
 */
function flip(doSomething, firstEl, getLastEl = () => firstEl) {
    const getRect = (el) => {
        return el.getBoundingClientRect();
    };

    // First
    const firstRect = getRect(firstEl);

    requestAnimationFrame(() => {
        // (something that changes layout)
        doSomething();

        // Last
        let lastEl = getLastEl();
        const lastRect = getRect(lastEl);

        // Invert
        const dx = lastRect.x - firstRect.x;
        const dy = lastRect.y - firstRect.y;
        const dw = lastRect.width / firstRect.width;
        const dh = lastRect.height / firstRect.height;

        // (so CSS knows it's being flipped)
        // data-flipping="true"
        lastEl.dataset.flipping = true;

        lastEl.style.setProperty("--dx", dx);
        lastEl.style.setProperty("--dy", dy);
        lastEl.style.setProperty("--dw", dw);
        lastEl.style.setProperty("--dh", dh);

        // Play
        // setTimeout(() => {
        //     delete lastEl.dataset.flipping;
        // }, 1000);
        requestAnimationFrame(() => {
            delete lastEl.dataset.flipping;
        });
    });
}