framer-motion-ticker
Version:
A React component that acts like a ticker, or marquee.
92 lines (91 loc) • 2.89 kB
JavaScript
import React from 'react';
import { useAnimate, useInView } from 'framer-motion';
var TICKER_DIRECTION_LEFT = -1;
var TICKER_DIRECTION_RIGHT = 1;
var noop = () => {};
var Ticker = props => {
var {
children,
duration = 10,
onMouseEnter = noop,
onMouseLeave = noop,
isPlaying = true,
direction = TICKER_DIRECTION_LEFT
} = props;
var tickerRef = React.useRef(null);
var tickerContentsRef = React.useRef(null);
var [tickerContentWidth, setTickerContentWidth] = React.useState(2);
var [numDupes, setNumDupes] = React.useState(1);
var [scope, animate] = useAnimate();
var [animationControls, setAnimationControls] = React.useState(undefined);
var isInView = useInView(scope);
React.useEffect(() => {
if (tickerRef.current && tickerContentsRef.current) {
var contentWidth = tickerContentsRef.current.getBoundingClientRect().width;
setTickerContentWidth(contentWidth);
setNumDupes(Math.max(Math.ceil(2 * tickerRef.current.clientWidth / contentWidth), 1));
}
}, [tickerRef.current, tickerContentsRef.current]);
React.useEffect(() => {
if (isInView && !animationControls) {
var 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 /*#__PURE__*/React.createElement("div", {
className: "FMT__container",
ref: tickerRef,
style: {
width: '100%',
height: '100%',
overflow: 'hidden'
},
onMouseEnter: onMouseEnter,
onMouseLeave: onMouseLeave
}, /*#__PURE__*/React.createElement("div", {
ref: scope,
className: "FMT__container__contents",
style: {
display: 'flex',
width: 'max-content',
marginLeft: "-" + tickerContentWidth * numDupes + "px"
}
}, /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex'
}
}, [...Array(numDupes)].map(_ => children.map((item, index) => /*#__PURE__*/React.createElement(React.Fragment, {
key: index
}, item)))), /*#__PURE__*/React.createElement("div", {
ref: tickerContentsRef,
style: {
display: 'flex'
}
}, children.map((item, index) => /*#__PURE__*/React.createElement(React.Fragment, {
key: index
}, item))), /*#__PURE__*/React.createElement("div", {
style: {
display: 'flex'
}
}, [...Array(numDupes)].map(_ => children.map((item, index) => /*#__PURE__*/React.createElement(React.Fragment, {
key: index
}, item))))));
};
export default Ticker;
export { TICKER_DIRECTION_LEFT, TICKER_DIRECTION_RIGHT };