import React, { useState, useCallback, ReactNodeArray, useEffect, useImperativeHandle } from 'react'; import styled, { css } from 'styled-components'; import { animated, useTransition } from 'react-spring'; import { cssUnitCalc } from 'utils'; type IProps = { children: ReactNodeArray; width?: number | string; height?: number | string; /** 是否开启自动播放 */ autoplay?: boolean; clickAble?: boolean; /** 自动播放每帧的时间间隔(毫秒) */ playInterval?: number; /** 轮播结束是否从头开始 */ rewind?: boolean; direction?: 'vertical' | 'horizontal'; /** 悬停在组件上暂停轮播 */ hoverPause?: boolean; Indicator: any; /** 提示点的位置 */ indicatorPosition?: 'top' | 'right' | 'bottom' | 'left'; }; const Wrap = styled.div` width: ${p => cssUnitCalc(p.width)}; height: ${p => cssUnitCalc(p.height)}; display: inline-block; position: relative; overflow: hidden; `; const ItemWrap = styled.div` width: 100%; height: 100%; position: absolute; will-change: transform, opacity; display: flex; justify-content: center; align-items: center; > * { width: 100%; height: 100%; } `; const AnimatedItemWrap = animated(ItemWrap); const Transition = function( { children, width, height, rewind, autoplay, playInterval, Indicator, direction, hoverPause, indicatorPosition, clickAble, ...rest }: IProps, ref: any ) { const [index, set] = useState(0); useImperativeHandle( ref, () => { return { set }; }, [] ); const [hover, setHover] = useState(false); const onClick = useCallback(() => { if (hoverPause && hover && !clickAble) { return; } !document.hidden && clickAble && set(state => (rewind ? (state + 1) % children.length : Math.min(state + 1, children.length - 1))); }, [hover, hoverPause, rewind, clickAble, document.hidden]); useEffect(() => { if (autoplay) { var handle = setInterval(onClick, playInterval); } return () => { clearInterval(handle); }; }, [index, hover, autoplay]); const horizontal = direction === 'horizontal'; const transitions = useTransition(index, p => p, { from: { opacity: 0, transform: `translate3d(${horizontal ? '100%' : '0'},${horizontal ? '0' : '100%'},0)` }, enter: { opacity: 1, transform: `translate3d(0%,0,0)` }, leave: { opacity: 0, transform: `translate3d(${horizontal ? '-50%' : '0'},${horizontal ? '0' : '-50%'},0)` }, }); return ( <> setHover(true)} onMouseLeave={() => setHover(false)} > {transitions.map(({ item, props, key }: any) => { return ( {children[item]} ); })} ); }; export default React.forwardRef(Transition);