I have a very small problem, but unfortunately I could not solve it, so I hope someone can help me, so I'm trying to make a scroll animation and move some element using the css matrix attribute and the matrix have this parameters
scaleX(), skewY(), skewX(), scaleY(), translateX(), translateY()
so i use the scale and translateX and translateY to animate and move the element,
i use the scrollY position value to know when to start the animation and use the y position value to move the element like this
matrix(1, 0, 0, 1, ${yPositionValue}, -35)
so when the user scroll the y value increment or decrement, now my first way to solve the problem is to hardcode the values like if the yScroll value is 1000 then i want the animation to start so i make a event listener to the scroll if the value is 1000 then subtract the 1000 from the scroll Y position then i will start from 0 then i will move my element until i want them to stop, as you can see it's a stupid way there are many if, so what i think is a good way is to use the scroll y position value and generate a new number according to the y value that start from min and max value, so i try the next
so my first problem is when is start the animation and i use the Observer API and use the thresholds values so if the 50% of the element is visible then i start the animation, know for the scroll position i use the min and max values to give my a number between two values just like this
const PositionValue = (Math.min(250, Math.max(0, yOffset)));
so the yOffset is the y scroll position this code is work great but the problem that i it dont work very well with small number like if i want a number between 0.55 and 1.0 it doesn't give what i want so instead of this
const PositionValue = (Math.min(1, Math.max(0.55, yOffset)));
i did this
const PositionValue = (Math.min(100, Math.max(55, yOffset))) / 100;
so i can get number between 0.55, 1.0, i want to flip this number so instead of start from 0.55 to 1.0 i want to start from 1.0 to 0.55, i tried to make a variable and assigned a 1 and if the PositionValue is bigger then 0.55 it will decrement by 0.01, all i want is a way to generate a number according to the y value, i know that there is a libraries like GSAP but i like to make it by my self i use react this is my full code
// observer testing
const [isIntersectionRatioComplete, setisIntersectionRatioComplete] = useState(false);
const observerElement = useRef(null);
const leftSwitchRef = useRef(null);
const centerSwitchRef = useRef(null);
const rightSwitchRef = useRef(null);
const observerOptions = {
root: null,
rootMargin: '0px',
threshold: []
}
let cenetrSwitchScalingValue = 1;
const HandelScrollTriggerAnimation = () => {
const yOffset = window.pageYOffset - 1230;
if (yOffset > 0) {
const SwitchPositionValue = (Math.min(250, Math.max(0, yOffset)));
// const cenetrSwitchScalingValue = (Math.min(100, Math.max(56, yOffset))) / 100; // 0.56, 1
if (cenetrSwitchScalingValue >= 0.56) {
cenetrSwitchScalingValue = cenetrSwitchScalingValue - 0.01;
}
if (leftSwitchRef.current && centerSwitchRef.current && rightSwitchRef.current) {
leftSwitchRef.current.style.transform = `matrix(1, 0, 0, 1, ${-SwitchPositionValue}, -35)`;
centerSwitchRef.current.style.transform = `matrix(${cenetrSwitchScalingValue}, 0, 0, ${cenetrSwitchScalingValue}, 70, ${-SwitchPositionValue})`;
rightSwitchRef.current.style.transform = `matrix(1, 0, 0, 1, ${SwitchPositionValue}, -35)`;
} return
} return
}
const observerCallbackFunction = (entries) => {
const [ entry ] = entries;
if (entry.intersectionRatio >= 0.1) { //0.5
// alert("done")
setisIntersectionRatioComplete(true)
} else {
setisIntersectionRatioComplete(false)
}
}
useEffect(() => {
for(let i = 0; i <= 1.0; i = 0.1) {
observerOptions.threshold.push(i);
}
const observer = new IntersectionObserver(observerCallbackFunction, observerOptions);
if (observerElement.current) observer.observe(observerElement.current);
if (isIntersectionRatioComplete) {
window.addEventListener('scroll', HandelScrollTriggerAnimation, { passive: true });
}
return () => {
if (observerElement.current) {
observer.unobserve(observerElement.current);
window.removeEventListener('scroll', HandelScrollTriggerAnimation);
}
}
}, [isIntersectionRatioComplete])
for more explanation if you see apple website here you can see there animation how smooth it is what is the right approach to make like this animation thank you.
CodePudding user response:
What about const PositionValue = (Math.max(55, Math.min(100, 100-yOffset))) / 100;
?