Skip to content

Commit

Permalink
implement play/pause and mouse events
Browse files Browse the repository at this point in the history
  • Loading branch information
andremov committed Apr 3, 2023
1 parent 9070612 commit 15f2d07
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 11 deletions.
3 changes: 2 additions & 1 deletion example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<div className="App">
<Ticker duration={20}>
<Ticker duration={5} onMouseEnter={() => setIsPlaying(false)} onMouseLeave={() => setIsPlaying(true)} isPlaying={isPlaying}>
{colors.map((item, index) => (
<div
key={index}
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "framer-motion-ticker",
"version": "1.0.17",
"version": "1.0.18",
"description": "A React component that acts like a ticker, or marquee.",
"author": "Andres Movilla <[email protected]>",
"license": "MIT",
Expand Down
68 changes: 60 additions & 8 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -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<TickerProps> = ({ 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<TickerProps> = (props: TickerProps) => {
const {
children,
duration = 10,
onMouseEnter = noop,
onMouseLeave = noop,
isPlaying = true,
direction = TICKER_DIRECTION_LEFT,
} = props;
const tickerRef = React.useRef<HTMLDivElement>(null);
const [tickerUUID, setTickerUUID] = React.useState<string>('');
const [tickerContentWidth, setTickerContentWidth] = React.useState<number>(2);
const [numDupes, setNumDupes] = React.useState<number>(1);
const [scope, animate] = useAnimate();
const [animationControls, setAnimationControls] = React.useState<
AnimationPlaybackControls | undefined
>(undefined);
const isInView = useInView(scope);

React.useEffect(() => {
setTickerUUID(uuidv4());
Expand All @@ -33,6 +58,28 @@ const Ticker: React.FunctionComponent<TickerProps> = ({ 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 (
<div
className="FMT__container"
Expand All @@ -42,12 +89,15 @@ const Ticker: React.FunctionComponent<TickerProps> = ({ children, duration = 10
height: '100%',
overflow: 'hidden',
}}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
<motion.div
<div
ref={scope}
className="FMT__container__contents"
initial={false}
animate={{ x: -tickerContentWidth }}
transition={{ ease: 'linear', duration, repeat: Infinity }}
// initial={false}
// animate={{ x: tickerContentWidth * direction }}
// transition={{ ease: 'linear', duration, repeat: Infinity }}
style={{ display: 'flex' }}
>
{children.map((item, index) => (
Expand All @@ -58,9 +108,11 @@ const Ticker: React.FunctionComponent<TickerProps> = ({ children, duration = 10
{[...Array(numDupes)].map((_) =>
children.map((item, index) => <div key={index}>{item}</div>)
)}
</motion.div>
</div>
</div>
);
};

export default Ticker;

export { TICKER_DIRECTION_LEFT, TICKER_DIRECTION_RIGHT };

0 comments on commit 15f2d07

Please sign in to comment.