I have an image carousel built with Mantine carousel that's based on Embla carousel. I'm trying to add a scale animation feature to transform the image that's currently in view by adding classes to it and then removing the classes before scrolling to the next image, essentially emulating this website's image carousel.
I've tried using Embla's selectedScrollSnap method with scrollSnapList to get the currently displayed image which returns the error: Property 'classList' does not exist on type 'number'.
ImageSlide.tsx
import { useCallback, useEffect, useRef, useState } from "react";
import Autoplay from "embla-carousel-autoplay";
import { Carousel, Embla } from "@mantine/carousel";
import Image from "next/image";
import imagesAndText from "../../public/media";
import { FaLongArrowAltRight } from "react-icons/fa";
import { BsArrowDownCircle } from "react-icons/bs";
import Link from "next/link";
export default function ImgSlides({ startRef }: { startRef: null | any }) {
const [embla, setEmbla] = useState<Embla | null>(null);
const autoplay = useRef(Autoplay({ delay: 5000 }));
// transfrom scale
const [activeIndex,setActiveIndex] = useState(0)
useEffect(()=> {
if(embla) {
setActiveIndex(embla.selectedScrollSnap())
}
},[embla])
useEffect(()=> {
const currentImage = embla?.scrollSnapList()[activeIndex]
currentImage?.classList.add("transform", "scale-150")
currentImage.addEventListener("transitioned", ()={currentImage.classList.remove("transform", "scale-150")})
})
const handleButtonClick = useCallback(
(startRef: null | any) => {
if (startRef.current) {
window.scrollTo({
top: startRef.current.offsetTop,
behavior: "smooth",
});
}
if (!embla) return;
embla.reInit();
},
[embla]
);
const slides = imagesAndText.map((item, i) => (
<Carousel.Slide key={i}>
<div className="h-screen bg-inherit flex w-full relative">
<Image
src={item.image.src}
alt="tali consultancy"
fill
className="object-cover"
data-pin-no-hover="true"
/>
<div className="absolute top-1/3 md:mt-6 h-auto flex flex-col">
<div className="text-sm opacity-90 w-fit mb-2 pl-11 lg:pl-12 text-gray-100 font-bold px-2 py-2 ">
{item.headline}
</div>
<Link
href="/"
className="pl-11 lg:pl-12 text-gray-50 mb-4 lg:mb-6 text-4xl lg:text-5xl xl:text-6xl font-semibold md:left-16 z-10"
>
{item.article}
</Link>
<Link
href="/"
className="text-gray-50 lg:pl-12 pl-11 uppercase flex items-center font-semibold text-sm"
>
Learn more
<FaLongArrowAltRight className="text-2xl font-semibold pt-1 pl-2" />
</Link>
</div>
<div className="flex justify-center absolute bottom-10 pb-8 lg:pb-0 lg:bottom-7 w-full">
<button
className="text-gray-50 font-bold left-1/2 animate-bounce text-lg lg:text-base"
onClick={() => handleButtonClick(startRef)}
>
<BsArrowDownCircle />
</button>
</div>
</div>
</Carousel.Slide>
));
return (
<Carousel
mx="auto"
// withIndicators
plugins={[autoplay.current]}
onMouseEnter={autoplay.current.stop}
onMouseLeave={autoplay.current.reset}
loop={true}
getEmblaApi={setEmbla}
>
{slides}
</Carousel>
);
}
Media.tsx
import img1 from "./img19-large.png";
import img2 from "./img1-large.png";
import img3 from "./img18.png";
import img4 from "./img13.png";
const imagesAndText = [
{
image: img1,
headline: "Sustainability and Climate Change",
article: "Profitability through Creating Shared Value",
},
{
image: img2,
headline: "Innovation and Strategy",
article: "Assessing the potential of disruptive technologies",
},
{
image: img3,
headline: "Talent Acquisition and Retention",
article: "How the best businesses win the War for Talent",
},
{
image: img4,
headline: "Cyber Security",
article: "Are Incident Response Plans worth it?",
},
];
export default imagesAndText;
Thanks in advance!