UNPKG

vantui-edit

Version:

一套适用于Taro3及React的vantui组件库

602 lines (517 loc) 21.5 kB
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _typeof from "@babel/runtime/helpers/typeof"; var _excluded = ["children", "direction", "className", "pageContent", "onChange", "initPage", "paginationColor", "paginationVisible", "touchable", "isPreventDefault", "isStopPropagation", "autoPlay", "isCenter", "style"]; import _regeneratorRuntime from "@babel/runtime/regenerator"; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } /* eslint-disable @typescript-eslint/no-unused-vars */ import React, { useState, useEffect, useRef, useMemo, Children, forwardRef, useImperativeHandle, isValidElement, useCallback } from 'react'; import classNames from 'classnames'; import { useReady, createSelectorQuery, nextTick } from '@tarojs/taro'; import { View, Text } from '@tarojs/components'; import { DataContext } from './context'; import { jsx as _jsx } from "react/jsx-runtime"; import { jsxs as _jsxs } from "react/jsx-runtime"; var defaultProps = { width: (typeof window === "undefined" ? "undefined" : _typeof(window)) === 'object' ? window.innerWidth : 375, height: 0, duration: 500, initPage: 0, autoPlay: 0, direction: 'horizontal', paginationColor: '#fff', paginationVisible: false, loop: true, touchable: true, isPreventDefault: true, isStopPropagation: true, isCenter: false, className: '' }; var DISTANCE = 5; var Swiper = function Swiper(props, ref) { var _classNames, _classNames2; var propSwiper = _objectSpread(_objectSpread({}, defaultProps), props); var children = propSwiper.children, direction = propSwiper.direction, className = propSwiper.className, pageContent = propSwiper.pageContent, onChange = propSwiper.onChange, initPage = propSwiper.initPage, paginationColor = propSwiper.paginationColor, paginationVisible = propSwiper.paginationVisible, touchable = propSwiper.touchable, isPreventDefault = propSwiper.isPreventDefault, isStopPropagation = propSwiper.isStopPropagation, autoPlay = propSwiper.autoPlay, isCenter = propSwiper.isCenter, style = propSwiper.style, rest = _objectWithoutProperties(propSwiper, _excluded); var container = useRef(null); var innerRef = useRef(null); var _swiper = useRef({ moving: false, autoplayTimer: null, width: 0, height: 0, offset: 0, size: 0 }); var _useState = useState(Math.random().toString(36).slice(-8)), _useState2 = _slicedToArray(_useState, 1), refRandomId = _useState2[0]; var isVertical = direction === 'vertical'; var _useState3 = useState(null), _useState4 = _slicedToArray(_useState3, 2), rect = _useState4[0], setRect = _useState4[1]; // eslint-disable-next-line prefer-const var _useState5 = useState(0), _useState6 = _slicedToArray(_useState5, 2), active = _useState6[0], setActive = _useState6[1]; var _useState7 = useState(0), _useState8 = _slicedToArray(_useState7, 2), width = _useState8[0], setWidth = _useState8[1]; var _useState9 = useState(0), _useState10 = _slicedToArray(_useState9, 2), height = _useState10[0], setHeight = _useState10[1]; var _useState11 = useState(0), _useState12 = _slicedToArray(_useState11, 2), offset = _useState12[0], setOffset = _useState12[1]; var _useState13 = useState([]), _useState14 = _slicedToArray(_useState13, 2), childOffset = _useState14[0], setChildOffset = _useState14[1]; var _useState15 = useState(false), _useState16 = _slicedToArray(_useState15, 2), ready = _useState16[0], setReady = _useState16[1]; var size = isVertical ? height : width; var _useState17 = useState({ startX: 0, startY: 0, deltaX: 0, deltaY: 0, offsetX: 0, offsetY: 0, stateDirection: '', delta: 0, touchTime: 0 }), _useState18 = _slicedToArray(_useState17, 1), touch = _useState18[0]; var _useMemo = useMemo(function () { var childCount = 0; var childs = Children.map(propSwiper.children, function (child) { if (! /*#__PURE__*/isValidElement(child)) return null; childCount++; return child; }); return { childs: childs, childCount: childCount }; }, [propSwiper.children]), childs = _useMemo.childs, childCount = _useMemo.childCount; var trackSize = childCount * Number(size); // 父组件参数传入子组件item var parent = { propSwiper: propSwiper, size: size }; // 浏览器 帧 事件 var requestFrame = useCallback(function (fn) { window.requestAnimationFrame.call(window, fn); }, []); // 取值 方法 var range = useCallback(function (num, min, max) { return Math.min(Math.max(num, min), max); }, []); var getDirection = useCallback(function (x, y) { if (x > y && x > DISTANCE) return 'horizontal'; if (y > x && y > DISTANCE) return 'vertical'; return ''; }, []); var getMinOffset = useCallback(function () { if (rect) { var base = isVertical ? rect === null || rect === void 0 ? void 0 : rect.height : rect === null || rect === void 0 ? void 0 : rect.width; return base - Number(size) * childCount; } return 0; }, [childCount, isVertical, rect, size]); // 确定当前active 元素 var getActive = function getActive(pace) { if (pace) { var _active = active + pace; if (propSwiper.loop) { return range(_active, -1, childCount); } return range(_active, 0, childCount - 1); } return active; }; // 计算位移 var getOffset = useCallback(function (active) { var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var minOffset = getMinOffset(); var currentPosition = active * Number(size); if (!propSwiper.loop) { currentPosition = Math.min(currentPosition, -minOffset); } var targetOffset = offset - currentPosition; if (!propSwiper.loop) { targetOffset = range(targetOffset, minOffset, 0); } return targetOffset; }, [getMinOffset, propSwiper.loop, range, size]); var getStyle = useCallback(function () { var moveOffset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : offset; var target = innerRef.current; var _offset = 0; if (!isCenter) { _offset = moveOffset; } else { var _size = isVertical ? height : width; var val = isVertical ? (rect === null || rect === void 0 ? void 0 : rect.height) - _size : (rect === null || rect === void 0 ? void 0 : rect.width) - _size; _offset = moveOffset + (active === childCount - 1 && !propSwiper.loop ? -val / 2 : val / 2); } target.style.transitionDuration = "".concat(_swiper.current.moving ? 0 : propSwiper.duration, "ms"); target.style[isVertical ? 'height' : 'width'] = "".concat(Number(size) * childCount, "px"); target.style[isVertical ? 'width' : 'height'] = "".concat(isVertical ? width : height, "px"); target.style.transform = "translate3D".concat(!isVertical ? "(".concat(_offset, "px,0,0)") : "(0,".concat(_offset, "px,0)")); }, [active, childCount, height, isCenter, isVertical, offset, propSwiper.duration, propSwiper.loop, rect, size, width]); // 切换方法 var move = useCallback(function (_ref) { var _ref$pace = _ref.pace, pace = _ref$pace === void 0 ? 0 : _ref$pace, _ref$offset = _ref.offset, offset = _ref$offset === void 0 ? 0 : _ref$offset, _ref$isEmit = _ref.isEmit, isEmit = _ref$isEmit === void 0 ? false : _ref$isEmit; if (childCount <= 1) return; var targetActive = getActive(pace); var minOffset = getMinOffset(); // 父级容器偏移量 var targetOffset = getOffset(targetActive, offset); // 如果循环,调整开头结尾图片位置 if (propSwiper.loop) { if (Array.isArray(children) && children[0] && targetOffset !== minOffset) { var rightBound = targetOffset < minOffset; childOffset[0] = rightBound ? trackSize : 0; } if (Array.isArray(children) && children[childCount - 1] && targetOffset !== 0) { var leftBound = targetOffset > 0; childOffset[childCount - 1] = leftBound ? -trackSize : 0; } setChildOffset(childOffset); } if (isEmit && active !== targetActive) { propSwiper.onChange && propSwiper.onChange((targetActive + childCount) % childCount); } // eslint-disable-next-line react-hooks/exhaustive-deps active = targetActive; setActive(targetActive); setOffset(targetOffset); getStyle(targetOffset); }, [active, childCount, childOffset, children, getActive, getMinOffset, getOffset, getStyle, propSwiper, trackSize]); // 重置 全部位移信息 var touchReset = useCallback(function () { touch.startX = 0; touch.startY = 0; touch.deltaX = 0; touch.deltaY = 0; touch.offsetX = 0; touch.offsetY = 0; touch.delta = 0; touch.stateDirection = ''; touch.touchTime = 0; }, [touch]); // 重置首尾位置信息 var resettPosition = useCallback(function () { _swiper.current.moving = true; if (active <= -1) { move({ pace: childCount }); } if (active >= childCount) { move({ pace: -childCount }); } }, [active, childCount, move]); // 清除定时器 var stopAutoPlay = useCallback(function () { clearTimeout(_swiper.current.autoplayTimer); _swiper.current.autoplayTimer = null; }, []); // 下一页 var next = useCallback(function () { resettPosition(); touchReset(); requestFrame(function () { requestFrame(function () { _swiper.current.moving = false; move({ pace: 1, isEmit: true }); }); }); }, [move, requestFrame, resettPosition, touchReset]); // 上一页 var prev = useCallback(function () { resettPosition(); touchReset(); requestFrame(function () { requestFrame(function () { _swiper.current.moving = false; move({ pace: -1, isEmit: true }); }); }); }, [move, requestFrame, resettPosition, touchReset]); // 前往指定页 var to = useCallback(function (index) { resettPosition(); touchReset(); requestFrame(function () { requestFrame(function () { _swiper.current.moving = false; var targetIndex; if (propSwiper.loop && childCount === index) { targetIndex = active === 0 ? 0 : index; } else { targetIndex = index % childCount; } move({ pace: targetIndex - active, isEmit: true }); }); }); }, [active, childCount, move, propSwiper.loop, requestFrame, resettPosition, touchReset]); // 定时轮播 var autoplay = useCallback(function () { if (propSwiper.autoPlay <= 0 || childCount <= 1) return; stopAutoPlay(); _swiper.current.autoplayTimer = setTimeout(function () { next(); autoplay(); }, Number(propSwiper.autoPlay)); }, [childCount, next, propSwiper.autoPlay, stopAutoPlay]); // 触摸事件开始 var touchStart = useCallback(function (e) { var _e$touches$, _e$touches$2; touchReset(); touch.startX = (e === null || e === void 0 ? void 0 : (_e$touches$ = e.touches[0]) === null || _e$touches$ === void 0 ? void 0 : _e$touches$.clientX) || 0; touch.startY = (e === null || e === void 0 ? void 0 : (_e$touches$2 = e.touches[0]) === null || _e$touches$2 === void 0 ? void 0 : _e$touches$2.clientY) || 0; }, [touch, touchReset]); // 触摸事件移动 var touchMove = useCallback(function (e) { var _e$touches$3, _e$touches$4; touch.deltaX = ((e === null || e === void 0 ? void 0 : (_e$touches$3 = e.touches[0]) === null || _e$touches$3 === void 0 ? void 0 : _e$touches$3.clientX) || 0) - touch.startX; touch.deltaY = ((e === null || e === void 0 ? void 0 : (_e$touches$4 = e.touches[0]) === null || _e$touches$4 === void 0 ? void 0 : _e$touches$4.clientY) || 0) - touch.startY; touch.offsetX = Math.abs(touch.deltaX); touch.offsetY = Math.abs(touch.deltaY); touch.delta = isVertical ? touch.deltaY : touch.deltaX; if (!touch.stateDirection) { touch.stateDirection = getDirection(touch.offsetX, touch.offsetY); } }, [getDirection, isVertical, touch]); var contentClass = classNames((_classNames = {}, _defineProperty(_classNames, 'van-swiper__inner', true), _defineProperty(_classNames, 'van-swiper__vertical', isVertical), _classNames)); var onTouchStart = useCallback(function (e) { if (propSwiper.isPreventDefault) e.preventDefault(); if (propSwiper.isStopPropagation) e.stopPropagation(); if (!propSwiper.touchable) return; touchStart(e); touch.touchTime = Date.now(); stopAutoPlay(); resettPosition(); }, [propSwiper.isPreventDefault, propSwiper.isStopPropagation, propSwiper.touchable, resettPosition, stopAutoPlay, touch, touchStart]); var onTouchMove = useCallback(function (e) { if (propSwiper.touchable && _swiper.current.moving) { touchMove(e); if (touch.stateDirection === propSwiper.direction) { move({ offset: touch.delta }); } } }, [move, propSwiper.direction, propSwiper.touchable, touch.delta, touch.stateDirection, touchMove]); var onTouchEnd = useCallback(function () { if (!propSwiper.touchable || !_swiper.current.moving) return; var speed = touch.delta / (Date.now() - touch.touchTime); var isShouldMove = Math.abs(speed) > 0.2 || Math.abs(touch.delta) > +(size / 2).toFixed(2); var pace = 0; _swiper.current.moving = false; if (isShouldMove && touch.stateDirection === propSwiper.direction) { var _offset2 = isVertical ? touch.offsetY : touch.offsetX; if (propSwiper.loop) { if (_offset2 > 0) { pace = touch.delta > 0 ? -1 : 1; } else { pace = 0; } } else { pace = -Math[touch.delta > 0 ? 'ceil' : 'floor'](touch.delta / size); } move({ pace: pace, isEmit: true }); } else if (touch.delta) { move({ pace: 0 }); } else { getStyle(); } autoplay(); }, [autoplay, getStyle, isVertical, move, propSwiper.direction, propSwiper.loop, propSwiper.touchable, size, touch.delta, touch.offsetX, touch.offsetY, touch.stateDirection, touch.touchTime]); useEffect(function () { _swiper.current.activePagination = (active + childCount) % childCount; // eslint-disable-next-line react-hooks/exhaustive-deps }, [active]); var queryRect = useCallback(function (element) { return new Promise(function (resolve) { var query = createSelectorQuery(); query.select("#".concat(element.id)) && query.select("#".concat(element.id)).boundingClientRect(); query.exec(function (res) { resolve(res[0]); }); }); }, []); var init = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() { var active, rect, _active, _width, _height, targetOffset, _args = arguments; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: active = _args.length > 0 && _args[0] !== undefined ? _args[0] : +propSwiper.initPage; _context.next = 3; return queryRect(container.current); case 3: rect = _context.sent; _active = Math.max(Math.min(childCount - 1, active), 0); _width = propSwiper.width ? +propSwiper.width : rect === null || rect === void 0 ? void 0 : rect.width; _height = propSwiper.height ? +propSwiper.height : rect === null || rect === void 0 ? void 0 : rect.height; // eslint-disable-next-line react-hooks/exhaustive-deps size = isVertical ? _height : _width; // eslint-disable-next-line react-hooks/exhaustive-deps trackSize = childCount * Number(size); targetOffset = getOffset(_active); _swiper.current.moving = true; if (ready) { _swiper.current.moving = false; } setRect(rect); setActive(_active); setWidth(_width); setHeight(_height); setOffset(targetOffset); setReady(true); case 18: case "end": return _context.stop(); } } }, _callee); })), [childCount, getOffset, propSwiper.height, propSwiper.initPage, propSwiper.width, queryRect, ready]); useEffect(function () { if (ready) { getStyle(); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [isVertical, width, height, offset, ready]); useEffect(function () { if (ready && rect) { stopAutoPlay(); autoplay(); } return function () { setReady(false); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [ready, rect]); useEffect(function () { stopAutoPlay(); autoplay(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [children]); useEffect(function () { nextTick(function () { init(); }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [propSwiper.initPage]); useEffect(function () { return function () { stopAutoPlay(); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useReady(function () { nextTick(function () { setTimeout(function () { init(); }); }); }); var itemStyle = useCallback(function (index) { var style = {}; var _direction = propSwiper.direction || direction; var _size = size; if (_size) { style[_direction === 'horizontal' ? 'width' : 'height'] = "".concat(_size, "px"); } var offset = childOffset[index]; if (offset) { style.transform = "translate3D".concat(_direction === 'horizontal' ? "(".concat(offset, "px,0,0)") : "(0,".concat(offset, "px,0)")); } return style; }, [childOffset, direction, propSwiper.direction, size]); useImperativeHandle(ref, function () { return { to: to, next: next, prev: prev }; }); return /*#__PURE__*/_jsx(DataContext.Provider, { value: parent, children: /*#__PURE__*/_jsxs(View, _objectSpread(_objectSpread({ className: "van-swiper ".concat(className), ref: container }, rest), {}, { id: 'container-' + refRandomId, onTouchStart: onTouchStart, onTouchMove: onTouchMove, onTouchEnd: onTouchEnd // @ts-ignore , catchMove: isVertical, style: _objectSpread(_objectSpread({}, style), {}, { height: height }), children: [/*#__PURE__*/_jsxs(View, { className: contentClass, ref: innerRef, children: [Children.map(childs, function (child, index) { return /*#__PURE__*/_jsx(View, { className: 'van-swiper-item-wrapper', style: itemStyle(index), children: child }, index); }), process.env.TARO_ENV !== 'h5' && /*#__PURE__*/_jsx(View, { className: 'van-swiper-item-wrapper', style: itemStyle(0), children: childs && childs.length ? childs[0] : '' })] }), propSwiper.paginationVisible && !('pageContent' in propSwiper) ? /*#__PURE__*/_jsx(View, { className: classNames((_classNames2 = {}, _defineProperty(_classNames2, 'van-swiper__pagination', true), _defineProperty(_classNames2, 'van-swiper__pagination-vertical', isVertical), _classNames2)), children: Children.map(childs, function (_, index) { var _classNames3; return /*#__PURE__*/_jsx(Text, { style: (active + childCount) % childCount === index ? { backgroundColor: propSwiper.paginationColor } : undefined, className: classNames((_classNames3 = {}, _defineProperty(_classNames3, 'van-swiper__pagination-item', true), _defineProperty(_classNames3, "active", (active + childCount) % childCount === index), _classNames3)) }, index); }) }) : /*#__PURE__*/_jsx(View, { children: pageContent })] })) }); }; export var Swiper_ = /*#__PURE__*/forwardRef(Swiper); export default Swiper_;