I discovered a code by Nandi Muzsik (https://framer.university/resources/image-sequence-player-override-in-framer) allowing you to use image sequencing animation on you sites. (Code below).
How it works:
You create a component, then paste this custom code and when you scroll it changes variants based on the scroll and you have a nice animation.
My problem:
I discovered, that if I place the component inside a frame 2x it's height and set the component to "Sticky" it does not track the scroll until it's "not sticky anymore".
I tried to modify the code and delete target: ref, so now it tracks scrolling of the window. It fixed the problem, but created a new one - I want to track the scroll progress just for the container, which holds the component. And I don't know how to target it nor use it as a ref.
Any ideas?
import React, { useState, ComponentType, useRef, useEffect } from "react"
import { useScroll, useMotionValueEvent } from "framer-motion"
const VARIANT_LENGTH = 61
export const withScrollVariants = (Component): ComponentType => {
const variants = Array.from(
{ length: VARIANT_LENGTH },
(_, i) => `Variant ${i}`
)
return (props) => {
const [variantIndex, setVariantIndex] = useState(0)
const [imagesLoaded, setImagesLoaded] = useState(false)
const ref = useRef(null)
const { scrollYProgress } = useScroll({
target: ref,
offset: ["start 0", "end 0"],
})
useEffect(() => {
const imageSources = []
document.querySelectorAll("img").forEach((imgElement) => {
imageSources.push(imgElement.src)
})
const imagePromises = imageSources.map((src) => {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = () => resolve(src)
img.onerror = () => reject(src)
img.src = src
})
})
Promise.all(imagePromises)
.then(() => setImagesLoaded(true))
.catch(() => setImagesLoaded(false))
}, [])
useEffect(() => {
const newVariantIndex =
Math.round(scrollYProgress.current * (VARIANT_LENGTH - 2)) + 1
setVariantIndex(newVariantIndex)
}, [scrollYProgress.current])
useMotionValueEvent(scrollYProgress, "change", (currentProgress) => {
const newVariantIndex =
Math.round(scrollYProgress.current * (VARIANT_LENGTH - 2)) + 1
if (newVariantIndex !== variantIndex && imagesLoaded) {
setVariantIndex(newVariantIndex)
}
})
return (
<>
<div style={{ display: "none" }}>
{variants.map((variant) => (
<Component key={variant} {...props} variant={variant} />
))}
</div>
<Component
{...props}
variant={variants[variantIndex]}
ref={ref}
/>
</>
)
}
}