UNPKG

zarm-mobile

Version:
471 lines (387 loc) 14.2 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _classnames2 = require('classnames'); var _classnames3 = _interopRequireDefault(_classnames2); var _events = require('../utils/events'); var _events2 = _interopRequireDefault(_events); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var Swipe = function (_Component) { _inherits(Swipe, _Component); function Swipe(props) { _classCallCheck(this, Swipe); var _this = _possibleConstructorReturn(this, (Swipe.__proto__ || Object.getPrototypeOf(Swipe)).call(this, props)); _this.moveInterval = null; _this.pointStart = 0; _this.pointEnd = 0; _this.timeStart = new Date(); _this.translateX = 0; _this.state = { items: [], activeIndex: props.activeIndex }; _this._updateResize = _this._updateResize.bind(_this); _this._transitionEnd = _this._transitionEnd.bind(_this); return _this; } _createClass(Swipe, [{ key: 'componentWillMount', value: function componentWillMount() { this._parseItem(this.props); this.startAutoPlay(this.props); } }, { key: 'componentDidMount', value: function componentDidMount() { // 监听窗口变化 _events2.default.on(window, 'resize', this._updateResize); _events2.default.on(this.swipeItems, 'webkitTransitionEnd', this._transitionEnd); _events2.default.on(this.swipeItems, 'transitionend', this._transitionEnd); // 设置起始位置编号 this.onJumpTo(this.props.activeIndex); } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { if ('children' in nextProps) { this._parseItem(nextProps); } if ('activeIndex' in nextProps) { this.onJumpTo(nextProps.activeIndex); } } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { // 自动轮播结束 this.pauseAutoPlay(); // 移除监听窗口变化 _events2.default.off(window, 'resize', this._updateResize); _events2.default.off(this.swipeItems, 'webkitTransitionEnd', this._transitionEnd); _events2.default.off(this.swipeItems, 'transitionend', this._transitionEnd); } // 滑动到指定编号 }, { key: 'onSlideTo', value: function onSlideTo(index) { this._onMoveTo(index, this.props.speed); } // 静默跳到指定编号 }, { key: 'onJumpTo', value: function onJumpTo(index) { this._onMoveTo(index, 0); } // 自动轮播开始 }, { key: 'startAutoPlay', value: function startAutoPlay() { var _this2 = this; this.moveInterval = this.props.autoPlay && setInterval(function () { var activeIndex = _this2.state.activeIndex; var maxLength = _this2.props.children.length; activeIndex = ['left', 'top'].indexOf(_this2.props.direction) > -1 ? activeIndex + 1 : activeIndex - 1; if (activeIndex > maxLength - 1) { // 不循环暂停轮播 if (!_this2.props.loop) { _this2.pauseAutoPlay(); return; } activeIndex = 0; _this2.onJumpTo(-1); } else if (activeIndex < 0) { activeIndex = maxLength - 1; _this2.onJumpTo(maxLength); } _this2.onSlideTo(activeIndex); }, this.props.autoPlayIntervalTime); } // 暂停自动轮播 }, { key: 'pauseAutoPlay', value: function pauseAutoPlay() { if (this.moveInterval) { clearInterval(this.moveInterval); } } // 处理节点(首位拼接) }, { key: '_parseItem', value: function _parseItem(props) { if (props.children.length === 0) { return; } // 增加头尾拼接节点 var items = [].concat(props.children); var firstItem = items[0]; var lastItem = items[items.length - 1]; if (props.loop) { items.push(firstItem); items.unshift(lastItem); } // 节点追加后重排key var newItems = _react2.default.Children.map(items, function (element, index) { return (0, _react.cloneElement)(element, { key: index }); }); this.setState({ items: newItems }); } // 更新窗口变化的位置偏移 }, { key: '_updateResize', value: function _updateResize() { this.onJumpTo(this.state.activeIndex); } // 移动到指定编号 }, { key: '_onMoveTo', value: function _onMoveTo(index, speed) { var dom = this.swipeItems; if (!dom) { return; } var px = this._isDirectionX() ? -dom.offsetWidth * (index + this.props.loop) : -dom.offsetHeight * (index + this.props.loop); this._doTransition(px, speed); this.translateX = px; this.setState({ activeIndex: index }); } // 执行过渡动画 }, { key: '_doTransition', value: function _doTransition(offset, duration) { var dom = this.swipeItems; var x = 0; var y = 0; if (this._isDirectionX()) { x = offset; } else { y = offset; } dom.style.webkitTransitionDuration = duration + 'ms'; dom.style.transitionDuration = duration + 'ms'; dom.style.webkitTransform = 'translate3d(' + x + 'px, ' + y + 'px, 0)'; dom.style.transform = 'translate3d(' + x + 'px, ' + y + 'px, 0)'; } }, { key: '_transitionEnd', value: function _transitionEnd() { var activeIndex = this.state.activeIndex; var maxLength = this.props.children.length; if (activeIndex > maxLength - 1) { this.onJumpTo(0); } else if (activeIndex < 0) { this.onJumpTo(maxLength - 1); } this.props.onChangeEnd(this.state.activeIndex); } // 触屏事件 }, { key: '_onTouchStart', value: function _onTouchStart(event) { this.pauseAutoPlay(); var pointX = this._getCurrentPoint(event); var activeIndex = this.state.activeIndex; var maxLength = this.props.children.length; // 跳转到头尾 if (activeIndex <= 0) { this.onJumpTo(0); } else if (activeIndex >= maxLength - 1) { this.onJumpTo(maxLength - 1); } this.pointStart = pointX; this.timeStart = new Date(); } }, { key: '_onTouchMove', value: function _onTouchMove(event) { event.preventDefault(); var pointX = this._getCurrentPoint(event); var px = this.translateX + (pointX - this.pointStart); // 设置不循环的时候 if (!this.props.loop) { // 在首页时禁止拖动 if (this._isLastIndex() && pointX - this.pointStart < 0) { return; } // 在尾页时禁止拖动 if (this._isFirstIndex() && pointX - this.pointStart > 0) { return; } } this._doTransition(px, 0); this.pointEnd = pointX; } }, { key: '_onTouchEnd', value: function _onTouchEnd() { var dom = this.swipeItems; var px = this.pointEnd !== 0 ? this.pointEnd - this.pointStart : 0; var timeSpan = new Date().getTime() - this.timeStart.getTime(); var activeIndex = this.state.activeIndex; // 判断滑动临界点 // 1.滑动距离超过0,且滑动距离和父容器长度之比超过moveDistanceRatio // 2.滑动释放时间差低于moveTimeSpan if ( // 滑动距离超过0 px !== 0 && ( // 滑动距离和父容器长度之比超过moveDistanceRatio Math.abs(px / dom.offsetWidth) >= this.props.moveDistanceRatio || // 滑动释放时间差低于moveTimeSpan timeSpan <= this.props.moveTimeSpan)) { activeIndex = px > 0 ? this.state.activeIndex - 1 : this.state.activeIndex + 1; var onChange = this.props.onChange; typeof onChange === 'function' && onChange(activeIndex); } this.onSlideTo(activeIndex); this.pointStart = 0; this.pointEnd = 0; // 恢复自动轮播 this.startAutoPlay(); } // 获取鼠标/触摸点坐标 }, { key: '_getCurrentPoint', value: function _getCurrentPoint(event, type) { var touch = type === 'mouse' ? event : event.touches[0]; var offset = this._isDirectionX() ? touch.pageX : touch.pageY; return offset; } // 判断当前是否在最后一页 }, { key: '_isLastIndex', value: function _isLastIndex() { var result = false; if (this.state.activeIndex >= this.props.children.length - 1) { result = true; } return result; } // 判断当前是否在第一页 }, { key: '_isFirstIndex', value: function _isFirstIndex() { var result = false; if (this.state.activeIndex <= 0) { result = true; } return result; } // 是否横向移动 }, { key: '_isDirectionX', value: function _isDirectionX() { return ['left', 'right'].indexOf(this.props.direction) > -1; } }, { key: 'render', value: function render() { var _classnames, _this3 = this; var _props = this.props, prefixCls = _props.prefixCls, className = _props.className, height = _props.height, children = _props.children; var classes = (0, _classnames3.default)((_classnames = {}, _defineProperty(_classnames, '' + prefixCls, true), _defineProperty(_classnames, className, !!className), _classnames)); var style = { items: {}, pagination: {} }; if (!this._isDirectionX()) { style.items.height = height; style.pagination.marginTop = 3; } else { style.items.whiteSpace = 'nowrap'; style.pagination.display = 'inline-block'; style.pagination.marginRight = 3; } return _react2.default.createElement( 'div', { className: classes }, _react2.default.createElement( 'div', { ref: function ref(ele) { _this3.swipeItems = ele; }, className: prefixCls + '-items', style: style.items, onTouchStart: function onTouchStart(event) { return _this3._onTouchStart(event); }, onTouchMove: function onTouchMove(event) { return _this3._onTouchMove(event); }, onTouchEnd: function onTouchEnd(event) { return _this3._onTouchEnd(event); } }, this.state.items ), _react2.default.createElement( 'div', { className: prefixCls + '-pagination' }, _react2.default.createElement( 'ul', null, _react.Children.map(children, function (result, index) { return _react2.default.createElement('li', { role: 'tab', key: 'pagination-' + index, className: (0, _classnames3.default)({ active: index === _this3.state.activeIndex }), style: style.pagination, onClick: function onClick() { return _this3.onSlideTo(index); } }); }) ) ) ); } }]); return Swipe; }(_react.Component); Swipe.propTypes = { prefixCls: _propTypes2.default.string, direction: _propTypes2.default.oneOf(['left', 'right', 'top', 'bottom']), height: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]), loop: _propTypes2.default.bool, activeIndex: _propTypes2.default.number, speed: _propTypes2.default.number, autoPlay: _propTypes2.default.bool, autoPlayIntervalTime: _propTypes2.default.number, moveDistanceRatio: _propTypes2.default.number, moveTimeSpan: _propTypes2.default.number, onChange: _propTypes2.default.func, onChangeEnd: _propTypes2.default.func }; Swipe.defaultProps = { prefixCls: 'za-swipe', direction: 'left', height: 160, loop: false, activeIndex: 0, speed: 300, autoPlay: false, autoPlayIntervalTime: 3000, moveDistanceRatio: 0.5, moveTimeSpan: 300, onChange: function onChange() {}, onChangeEnd: function onChangeEnd() {} }; exports.default = Swipe;