From b65812ff7001bdee34e1163140cf604dbc4e2c95 Mon Sep 17 00:00:00 2001 From: Liam Egan Date: Sun, 30 Mar 2025 13:29:43 -0700 Subject: [PATCH 1/3] Updating the calculation for the carousel speed This ensures that the carousel runs at a constant speed, regardless of the number of items in the carousel. The speed is calculated based on the total width of the items in the carousel and the desired speed in pixels per second. Added a padding parameter, which allows the user to specify the amount of space to be added to the animation in order to ensure that the items are not cut off at the edges of the carousel. --- package-lock.json | 4 ++-- package.json | 2 +- src/lib/marquee.scss | 4 ++-- src/lib/marquee.tsx | 33 +++++++++++++++------------------ 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index 506164bb..50c60a74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@wethegit/react-marquee", - "version": "2.1.3", + "version": "2.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@wethegit/react-marquee", - "version": "2.1.3", + "version": "2.2.0", "license": "MIT", "dependencies": { "@changesets/changelog-github": "^0.5.0", diff --git a/package.json b/package.json index 01a969fc..e4c326aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@wethegit/react-marquee", - "version": "2.2.0", + "version": "2.3.0", "description": "", "files": [ "dist" diff --git a/src/lib/marquee.scss b/src/lib/marquee.scss index fa6a5b0a..d6c10334 100644 --- a/src/lib/marquee.scss +++ b/src/lib/marquee.scss @@ -4,11 +4,11 @@ @keyframes scroll { 0% { - transform: translateX(0%); + transform: translateX(calc(var(--padding) * -1px)); } 100% { - transform: translateX(calc(var(--marquee-width) * -1px)); + transform: translateX(calc((var(--padding) + var(--marquee-width)) * -1px)); } } } diff --git a/src/lib/marquee.tsx b/src/lib/marquee.tsx index 659fccda..1c7a3797 100644 --- a/src/lib/marquee.tsx +++ b/src/lib/marquee.tsx @@ -31,6 +31,12 @@ export interface MarqueeProps extends React.ComponentPropsWithoutRef<"div"> { * Whether to animate from left to right */ reverse?: boolean + /** + * Extra spacing in pixels that the slide should travel beyond its width. + * This ensures the slide is completely offscreen before the loop restarts. + * Default value is 50. + */ + padding?: number } type Timer = ReturnType @@ -40,11 +46,13 @@ export function Marquee({ reducedMotionSpeed = 20, prefersReducedMotion = false, playing = true, + padding = 10, reverse, children, className, ...props }: MarqueeProps) { + // const [containerWidth, setContainerWidth] = useState(0) const [marqueeWidth, setMarqueeWidth] = useState(0) const [duration, setDuration] = useState(0) const [neededAmount, setNeededAmount] = useState(1) @@ -56,33 +64,21 @@ export function Marquee({ const updateState = useCallback(() => { const containerWidth = container.current?.clientWidth || 0 const marqueeWidth = marquee.current?.clientWidth || 0 - - // If prefersReducedMotion, replace speed with reducedMotionSpeed const speedAmount = prefersReducedMotion ? reducedMotionSpeed : speed - // Divide the container width, by the marquee width and round it up - // to give us the ammount of items needed to fill the container. + // Calculate the number of copies needed for a seamless loop let neededAmount = Math.ceil(containerWidth / marqueeWidth) * 2 - 1 - - // check if needed ammount if less that one, if it is set to be just 1. if (neededAmount < 1 || isNaN(neededAmount)) { neededAmount = 1 } - - // Set the needed ammount to state. setNeededAmount(neededAmount) - // Set marquee width in state so we can use it for the`--marquee-width` - // inline style. + // Set the marquee width (measured width of one slide) setMarqueeWidth(marqueeWidth) - // Set duration speed, which is used below in the --duration inline style. - if (marqueeWidth < containerWidth) { - setDuration(containerWidth / speedAmount) - } else { - setDuration(marqueeWidth / speedAmount) - } - }, [prefersReducedMotion, reducedMotionSpeed, speed]) + // Include padding in the total distance + setDuration((marqueeWidth + padding) / speedAmount) + }, [prefersReducedMotion, reducedMotionSpeed, speed, padding]) useEffect(() => { updateState() @@ -113,9 +109,10 @@ export function Marquee({ ])} style={ { - "--marquee-width": marqueeWidth, + "--marquee-width": `${Math.floor(marqueeWidth)}`, "--duration": duration + `s`, "--animation-state": playing ? "running" : "paused", + "--padding": padding, } as React.CSSProperties } > From 246e9993dad1d73880e8d1416f3b40459724ea8d Mon Sep 17 00:00:00 2001 From: Liam Egan Date: Sun, 30 Mar 2025 13:34:57 -0700 Subject: [PATCH 2/3] Adding comments back in --- src/lib/marquee.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/lib/marquee.tsx b/src/lib/marquee.tsx index 1c7a3797..0788a848 100644 --- a/src/lib/marquee.tsx +++ b/src/lib/marquee.tsx @@ -64,18 +64,27 @@ export function Marquee({ const updateState = useCallback(() => { const containerWidth = container.current?.clientWidth || 0 const marqueeWidth = marquee.current?.clientWidth || 0 + + // If prefersReducedMotion, replace speed with reducedMotionSpeed const speedAmount = prefersReducedMotion ? reducedMotionSpeed : speed - // Calculate the number of copies needed for a seamless loop + // Divide the container width, by the marquee width and round it up + // to give us the ammount of items needed to fill the container. let neededAmount = Math.ceil(containerWidth / marqueeWidth) * 2 - 1 + + // check if needed ammount if less that one, if it is set to be just 1. if (neededAmount < 1 || isNaN(neededAmount)) { neededAmount = 1 } + + // Set the needed ammount to state. setNeededAmount(neededAmount) - // Set the marquee width (measured width of one slide) + // Set marquee width in state so we can use it for the`--marquee-width` + // inline style. setMarqueeWidth(marqueeWidth) + // Set duration speed, which is used below in the --duration inline style. // Include padding in the total distance setDuration((marqueeWidth + padding) / speedAmount) }, [prefersReducedMotion, reducedMotionSpeed, speed, padding]) From 1a8c14bd0b46d8ca3b7c713389d0b0f6e3d77559 Mon Sep 17 00:00:00 2001 From: Liam Egan Date: Sun, 30 Mar 2025 13:37:44 -0700 Subject: [PATCH 3/3] Udpating note on padding --- src/lib/marquee.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/marquee.tsx b/src/lib/marquee.tsx index 0788a848..d801d840 100644 --- a/src/lib/marquee.tsx +++ b/src/lib/marquee.tsx @@ -34,7 +34,7 @@ export interface MarqueeProps extends React.ComponentPropsWithoutRef<"div"> { /** * Extra spacing in pixels that the slide should travel beyond its width. * This ensures the slide is completely offscreen before the loop restarts. - * Default value is 50. + * Default value is 10. */ padding?: number }