Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InfiniteSlider #113

Open
FrancescoSaverioZuppichini opened this issue Jan 30, 2025 · 2 comments
Open

InfiniteSlider #113

FrancescoSaverioZuppichini opened this issue Jan 30, 2025 · 2 comments

Comments

@FrancescoSaverioZuppichini

Hi there,

Using InfiniteSlider when the number of children is big, the speed is super fast and even by setting it there is not way to reduce it

@FrancescoSaverioZuppichini
Copy link
Author

I gpt the issue, and this one works perfectly

"use client"

import { useEffect, useRef, useState } from "react"
import { animate, motion, useMotionValue } from "framer-motion"

import { cn } from "@/lib/utils"

export type InfiniteSliderProps = {
  children: React.ReactNode
  speed?: number
  gap?: number
  direction?: "horizontal" | "vertical"
  className?: string
}

export function InfiniteSlider({
  children,
  speed = 50, // pixels per second
  gap = 2,
  direction = "horizontal",
  className,
}: InfiniteSliderProps) {
  const contentRef = useRef<HTMLDivElement>(null)
  const [contentSize, setContentSize] = useState(0)
  const translation = useMotionValue(0)

  useEffect(() => {
    if (contentRef.current) {
      setContentSize(
        direction === "horizontal"
          ? contentRef.current.scrollWidth
          : contentRef.current.scrollHeight
      )
    }
  }, [children, direction])

  useEffect(() => {
    const controls = animate(translation, [-contentSize, 0], {
      ease: "linear",
      duration: contentSize / speed,
      repeat: Infinity,
      repeatType: "loop",
    })

    return controls.stop
  }, [translation, contentSize, speed])

  const isHorizontal = direction === "horizontal"

  return (
    <div className={cn("overflow-hidden", className)}>
      <motion.div
        className={cn("flex", isHorizontal ? "flex-row" : "flex-col")}
        style={{
          ...(isHorizontal ? { x: translation } : { y: translation }),
          ...(isHorizontal
            ? { width: "max-content" }
            : { height: "max-content" }),
        }}
      >
        <div
          ref={contentRef}
          className={cn(
            `flex gap-${gap}`,
            isHorizontal ? "flex-row" : "flex-col"
          )}
        >
          {children}
        </div>
        <div
          className={cn(
            `flex gap-${gap}`,
            isHorizontal ? "flex-row" : "flex-col"
          )}
          aria-hidden="true"
        >
          {children}
        </div>
      </motion.div>
    </div>
  )
}

@FrancescoSaverioZuppichini
Copy link
Author

I think the speed should be based on the size of the wrapper div

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant