UNPKG

acud

Version:

acg react 组件库

210 lines • 8.26 kB
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray"; import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import React, { useState, useEffect, useRef, useMemo, useCallback } from 'react'; import classNames from 'classnames'; import { ConfigContext } from '../config-provider'; import CarouselSwitch from './switch'; import CarouselIndicator from './indicator'; var Carousel = function Carousel(_ref) { var className = _ref.className, style = _ref.style, children = _ref.children, _ref$dotPosition = _ref.dotPosition, dotPosition = _ref$dotPosition === void 0 ? 'bottom' : _ref$dotPosition, _ref$playInterval = _ref.playInterval, playInterval = _ref$playInterval === void 0 ? 5000 : _ref$playInterval, _ref$autoplay = _ref.autoplay, autoplay = _ref$autoplay === void 0 ? true : _ref$autoplay, _ref$width = _ref.width, width = _ref$width === void 0 ? 1920 : _ref$width, _ref$dotType = _ref.dotType, dotType = _ref$dotType === void 0 ? 'dot' : _ref$dotType, _ref$animationTime = _ref.animationTime, animationTime = _ref$animationTime === void 0 ? 400 : _ref$animationTime, multi = _ref.multi, _ref$showNumber = _ref.showNumber, showNumber = _ref$showNumber === void 0 ? 3 : _ref$showNumber, _ref$multiShift = _ref.multiShift, multiShift = _ref$multiShift === void 0 ? false : _ref$multiShift, indicatorStyle = _ref.indicatorStyle, _ref$infinite = _ref.infinite, infinite = _ref$infinite === void 0 ? true : _ref$infinite; var carouselRef = useRef(); var timer = useRef(); var _useState = useState(false), _useState2 = _slicedToArray(_useState, 2), isHover = _useState2[0], setIsHover = _useState2[1]; var _React$useContext = React.useContext(ConfigContext), getPrefixCls = _React$useContext.getPrefixCls; var prefixCls = getPrefixCls('carousel'); // 判断子元素是否是数组,如果不是,那就不存在轮播的情况 var childrenIsArray = useMemo(function () { return Array.isArray(children); }, [children]); // 因为要实现无缝轮播,所以前后会增加一个key。例如对用户看到有3张图片,但渲染中前后会添加得到5张 var extraCount = multi ? showNumber : 1; var _useState3 = useState({ lastKey: extraCount, currentKey: extraCount }), _useState4 = _slicedToArray(_useState3, 2), _useState4$ = _useState4[0], lastKey = _useState4$.lastKey, currentKey = _useState4$.currentKey, setKey = _useState4[1]; var length = Array.isArray(children) ? children.length : undefined; var next = useCallback(function () { // 向右滑动,最后一帧无缝滑动到第一帧使用的是额外添加的帧,滑动动画结束后,立刻切换到原始帧 if (infinite) { if (currentKey === length + extraCount) { setKey({ lastKey: currentKey, currentKey: extraCount }); setTimeout(function () { // 重置掉自动轮播 clearTimeout(timer.current); var nextKey = extraCount + (multiShift ? extraCount : 1); setKey({ lastKey: extraCount, currentKey: nextKey > length + extraCount ? length + extraCount : nextKey }); }, 100); } else { var nextKey = currentKey + (multiShift ? extraCount : 1); setKey({ lastKey: currentKey, currentKey: nextKey > length + extraCount ? length + extraCount : nextKey }); } } else { var _nextKey = currentKey + (multiShift ? extraCount : 1); setKey({ lastKey: currentKey, currentKey: _nextKey > length + extraCount ? length + extraCount : _nextKey }); } }, [currentKey, extraCount, length, multiShift, infinite]); // 向左滑动,第一帧无缝滑动到最后一帧使用的是额外添加的帧,滑动动画结束后,立刻切换到原始帧 var prev = useCallback(function () { if (infinite) { if (currentKey === 0) { setKey({ lastKey: currentKey, currentKey: length }); setTimeout(function () { // 重置掉自动轮播 clearTimeout(timer.current); var nextKey = length - (multiShift ? extraCount : 1); setKey({ lastKey: length, currentKey: nextKey < 0 ? 0 : length - (multiShift ? extraCount : 1) }); }); } else { var nextKey = currentKey - (multiShift ? extraCount : 1); setKey({ lastKey: currentKey, currentKey: nextKey < 0 ? 0 : currentKey - (multiShift ? extraCount : 1) }); } } else { var _nextKey2 = currentKey - (multiShift ? extraCount : 1); setKey({ lastKey: currentKey, currentKey: _nextKey2 < 0 ? 0 : _nextKey2 }); } }, [currentKey, extraCount, length, multiShift, infinite]); // 监听是否hover热区,hover情况下不会自动轮播 useEffect(function () { carouselRef.current.addEventListener('mouseover', function () { setIsHover(true); }); carouselRef.current.addEventListener('mouseleave', function () { setIsHover(false); }); }); // 自动轮播 useEffect(function () { clearTimeout(timer.current); if (length > 1 && autoplay && !isHover) { timer.current = setTimeout(next, playInterval); } return function () { return clearTimeout(timer.current); }; }, [autoplay, length, playInterval, next, isHover]); var getDuration = useCallback(function () { // next中立即切换的情况 if (lastKey === length + extraCount && currentKey === extraCount) { return '0s'; } // prev中立即切换的情况 if (lastKey === 0 && currentKey === length) { return '0s'; } // 正常切换的情况 return "".concat(animationTime / 1000, "s"); }, [lastKey, length, extraCount, currentKey, animationTime]); // 渲染的元素数组,首位增加实现无缝轮播 var renderChildren = useMemo(function () { var elements = Array.isArray(children) ? children : [children]; if (elements.length >= 1) { var extraPre = elements.slice(elements.length - extraCount); var extraPost = elements.slice(0, extraCount); elements = [].concat(_toConsumableArray(extraPre), _toConsumableArray(elements), _toConsumableArray(extraPost)); } return elements; }, [children, extraCount]); var cardWidth = useMemo(function () { if (multi) { return (width - 4 * (extraCount - 1)) / extraCount; } return width; }, [multi, width, extraCount]); var getLeft = function getLeft(idx) { return (multi ? cardWidth + 8 : cardWidth) * (idx - currentKey); }; var wrapperClassName = classNames(prefixCls, className, _defineProperty({}, "".concat(prefixCls, "-multi"), multi)); var isPrevDisabled = !infinite && currentKey === extraCount; var isNextDisabled = !infinite && currentKey === length; return /*#__PURE__*/React.createElement("div", { ref: carouselRef, style: style, className: wrapperClassName }, childrenIsArray ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(CarouselSwitch, { prefixCls: prefixCls, next: next, prev: prev, isPrevDisabled: isPrevDisabled, isNextDisabled: isNextDisabled }), !multi && /*#__PURE__*/React.createElement(CarouselIndicator, { prefixCls: prefixCls, setKey: setKey, length: length, currentKey: currentKey, autoplay: autoplay, playInterval: playInterval, dotPosition: dotPosition, dotType: dotType, multi: multi, showNumber: showNumber, style: indicatorStyle }), /*#__PURE__*/React.createElement("div", { className: "".concat(prefixCls, "-content") }, /*#__PURE__*/React.createElement("ul", null, renderChildren.map(function (child, idx) { return /*#__PURE__*/React.createElement("li", { key: idx, style: { left: getLeft(idx), width: cardWidth, transitionDuration: getDuration() } }, child); })))) : children); }; export default Carousel;