diff --git a/example/src/App.tsx b/example/src/App.tsx
index 94a0399..c4d1fe6 100644
--- a/example/src/App.tsx
+++ b/example/src/App.tsx
@@ -2,11 +2,12 @@ import Ticker from 'framer-motion-ticker';
import React from 'react';
function App() {
+ const [isPlaying, setIsPlaying] = React.useState(true)
const colors = ['#632bf3', '#f122c8', '#f16022', '#9ef344', '#44d3f3'];
return (
-
+ setIsPlaying(false)} onMouseLeave={() => setIsPlaying(true)} isPlaying={isPlaying}>
{colors.map((item, index) => (
",
"license": "MIT",
diff --git a/src/index.tsx b/src/index.tsx
index 18f41ef..23cceee 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,14 +1,39 @@
import React from 'react';
-import { motion } from 'framer-motion';
+import { AnimationPlaybackControls, useAnimate, useInView } from 'framer-motion';
import { v4 as uuidv4 } from 'uuid';
-type TickerProps = { children: JSX.Element[]; duration?: number };
+const TICKER_DIRECTION_LEFT = -1;
+const TICKER_DIRECTION_RIGHT = 1;
-const Ticker: React.FunctionComponent
= ({ children, duration = 10 }: TickerProps) => {
+type TickerProps = {
+ children: JSX.Element[];
+ duration?: number;
+ onMouseEnter?: () => void;
+ onMouseLeave?: () => void;
+ isPlaying?: boolean;
+ direction?: number;
+};
+
+const noop = () => {};
+
+const Ticker: React.FunctionComponent = (props: TickerProps) => {
+ const {
+ children,
+ duration = 10,
+ onMouseEnter = noop,
+ onMouseLeave = noop,
+ isPlaying = true,
+ direction = TICKER_DIRECTION_LEFT,
+ } = props;
const tickerRef = React.useRef(null);
const [tickerUUID, setTickerUUID] = React.useState('');
const [tickerContentWidth, setTickerContentWidth] = React.useState(2);
const [numDupes, setNumDupes] = React.useState(1);
+ const [scope, animate] = useAnimate();
+ const [animationControls, setAnimationControls] = React.useState<
+ AnimationPlaybackControls | undefined
+ >(undefined);
+ const isInView = useInView(scope);
React.useEffect(() => {
setTickerUUID(uuidv4());
@@ -33,6 +58,28 @@ const Ticker: React.FunctionComponent = ({ children, duration = 10
}
}, [tickerRef.current, tickerContentWidth]);
+ React.useEffect(() => {
+ if (isInView && !animationControls) {
+ const controls = animate(
+ scope.current,
+ { x: tickerContentWidth * direction },
+ { ease: 'linear', duration, repeat: Infinity }
+ );
+ controls.play();
+ setAnimationControls(controls);
+ }
+ }, [isInView]);
+
+ React.useEffect(() => {
+ if (animationControls) {
+ if (!isInView || !isPlaying) {
+ animationControls.pause();
+ } else {
+ animationControls.play();
+ }
+ }
+ }, [isInView, isPlaying]);
+
return (
= ({ children, duration = 10
height: '100%',
overflow: 'hidden',
}}
+ onMouseEnter={onMouseEnter}
+ onMouseLeave={onMouseLeave}
>
-
{children.map((item, index) => (
@@ -58,9 +108,11 @@ const Ticker: React.FunctionComponent = ({ children, duration = 10
{[...Array(numDupes)].map((_) =>
children.map((item, index) => {item}
)
)}
-
+
);
};
export default Ticker;
+
+export { TICKER_DIRECTION_LEFT, TICKER_DIRECTION_RIGHT };