Skip to main content

Marquee

A marquee is an element used to display scrolling content horizontally within a confined space. It's commonly seen in applications to information such as news tickers, advertisements, or any content that needs continuous display within a limited area.

Loading...

Now, let's understand how this example works:

The MeasureElement component measures the width of its children and passes this information to its parent component, Marquee.

Marquee
const MeasureElement = ({ onLayout, children }) => (
<Animated.ScrollView
horizontal
style={marqueeStyles.hidden}
pointerEvents="box-none">
<View onLayout={(ev) => onLayout(ev.nativeEvent.layout.width)}>
{children}
</View>
</Animated.ScrollView>
);

We use the useFrameCallback hook to execute the animation logic on each frame.

  useFrameCallback((i) => {
// prettier-ignore
offset.value += (coeff.value * ((i.timeSincePreviousFrame ?? 1) * childrenWidth)) / duration;
offset.value = offset.value % childrenWidth;
}, true);

It is located inside ChildrenScroller component that manages the scrolling animation by updating the offset value. It determines the horizontal translation of the child components, creates clones of the children and animates them horizontally based on the specified duration.

Marquee
const ChildrenScroller = ({
duration,
childrenWidth,
parentWidth,
reverse,
children,
}) => {
const offset = useSharedValue(0);
const coeff = useSharedValue(reverse ? 1 : -1);

React.useEffect(() => {
coeff.value = reverse ? 1 : -1;
}, [reverse]);

useFrameCallback((i) => {
// prettier-ignore
offset.value += (coeff.value * ((i.timeSincePreviousFrame ?? 1) * childrenWidth)) / duration;
offset.value = offset.value % childrenWidth;
}, true);

const count = Math.round(parentWidth / childrenWidth) + 2;
const renderChild = (index) => (
<TranslatedElement
key={`clone-${index}`}
index={index}
offset={offset}
childrenWidth={childrenWidth}>
{children}
</TranslatedElement>
);

return <Cloner count={count} renderChild={renderChild} />;
};

The Marquee component serves as the main orchestrator of the marquee effect. It calculates necessary dimensions, renders child components within a container, and coordinates the animation by utilizing the ChildrenScroller component.

Marquee
  const [parentWidth, setParentWidth] = React.useState(0);
const [childrenWidth, setChildrenWidth] = React.useState(0);

return (
<View
style={style}
onLayout={(ev) => {
setParentWidth(ev.nativeEvent.layout.width);
}}
pointerEvents="box-none">
<View style={marqueeStyles.row} pointerEvents="box-none">
<MeasureElement onLayout={setChildrenWidth}>{children}</MeasureElement>

{childrenWidth > 0 && parentWidth > 0 && (
<ChildrenScroller
duration={duration}
parentWidth={parentWidth}
childrenWidth={childrenWidth}
reverse={reverse}>
{children}
</ChildrenScroller>
)}
</View>
</View>
);
};