UNPKG

@vtbag/utensil-drawer

Version:

Pull out just what you need to craft seamless transitions. The Utensil Drawer holds reusable functions to help you build websites with view transitions. It is a bit sparse right now, but like the one in your kitchen, it is bound to fill up over time.

58 lines (57 loc) 2.77 kB
/* Sets the view transition name in the style attribute of selected elements, see setGivenViewTransitionNames. `selector´is an arbitrary CSS selector for the current document */ export function setSelectedViewTransitionNames(selector, prefix, force = false) { let selected; let stripped = selector.replace(/:in-viewport\s*$/, ''); try { selected = document.querySelectorAll(stripped); } catch (e) { console.error(e.message.replace(/.*:/, '[vtbag] Error selecting elements for view transition names:')); return; } let elements = [...selected]; if (selector.length !== stripped.length) { elements = elements.filter((e) => { const rect = e.getBoundingClientRect(); const overlapX = Math.max(0, Math.min(rect.right, window.innerWidth) - Math.max(rect.left, 0)); const overlapY = Math.max(0, Math.min(rect.bottom, window.innerHeight) - Math.max(rect.top, 0)); console.log(rect, overlapX, overlapY); return overlapX > 0 && overlapY > 0; }); } setGivenViewTransitionNames(elements, prefix, force); } /* Sets the view transition name in the style attribute of the given elements. If `elements` has exactly one entry, `prefix` is used as a name. Otherwise the `elements` are named with the `prefix` with an appended index starting from 0. If `force` is true, the names are always set, otherwise only if they are not already set. If the prefix string ends with a '~', the character is replaced by a '-' and the names are assigned in random order. */ export function setGivenViewTransitionNames(elements, prefix, force = false) { if (prefix[prefix.length - 1] === '~') { prefix = prefix.slice(0, -1) + '-'; shuffle(elements); } prefix = CSS.escape(prefix); elements.forEach((element, idx, array) => { const name = `${prefix}${array.length > 1 && prefix !== '' && prefix !== 'none' && prefix !== 'auto' && prefix !== 'match-element' ? idx : ''}`; (force && (element.style.viewTransitionName = name)) || (element.style.viewTransitionName ||= name); }); } export function setOldPageViewTransitionNames(selector, prefix) { addEventListener('pageswap', () => setSelectedViewTransitionNames(selector, prefix)); } // The pagereveal event fires very early. Thus scripts using this code should load inside the <head> export function setNewPageViewTransitionNames(selector, prefix) { addEventListener('pagereveal', () => setSelectedViewTransitionNames(selector, prefix)); } function shuffle(array) { for (let i = array.length - 1; i > 0; --i) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array; }