Mirror: A frag-canvas custom element to apply Shadertoy fragment shaders to a canvas or image/video element
at main 1.8 kB view raw
1let intersectionObserver: IntersectionObserver | undefined; 2const intersectionListeners = new Map<Element, (isVisible: boolean) => void>(); 3const getIntersectionObserver = () => 4 intersectionObserver || 5 (intersectionObserver = new IntersectionObserver(entries => { 6 for (const entry of entries) { 7 const listener = intersectionListeners.get(entry.target); 8 if (listener) { 9 listener(entry.isIntersecting); 10 } 11 } 12 })); 13 14export function trackVisibility( 15 element: Element, 16 onChange: (isVisible: boolean) => void 17): () => void { 18 const observer = getIntersectionObserver(); 19 intersectionListeners.set(element, onChange); 20 observer.observe(element); 21 return () => { 22 observer.unobserve(element); 23 intersectionListeners.delete(element); 24 }; 25} 26 27let resizeObserver: ResizeObserver | undefined; 28const resizeListeners = new Map< 29 Element, 30 (box: { inlineSize: number; blockSize: number }) => void 31>(); 32const getResizeObserver = () => 33 resizeObserver || 34 (resizeObserver = new ResizeObserver(entries => { 35 for (const entry of entries) { 36 const listener = resizeListeners.get(entry.target); 37 if (listener) listener(entry.devicePixelContentBoxSize[0]); 38 } 39 })); 40 41export function trackResizes( 42 element: Element, 43 onChange: (box: { inlineSize: number; blockSize: number }) => void 44): () => void { 45 const observer = getResizeObserver(); 46 resizeListeners.set(element, onChange); 47 observer.observe(element, { box: 'device-pixel-content-box' }); 48 return () => { 49 resizeListeners.delete(element); 50 }; 51} 52 53export function trackTextUpdates( 54 element: Element, 55 onChange: () => void 56): () => void { 57 const observer = new MutationObserver(onChange); 58 observer.observe(element, { subtree: true, characterData: true }); 59 return () => { 60 observer.disconnect(); 61 }; 62}