UNPKG

dragon-mobile-ui

Version:
462 lines (381 loc) 14.6 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 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 _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _classnames2 = require('classnames'); var _classnames3 = _interopRequireDefault(_classnames2); 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 _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } 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; } // import addEndEventListener from '../utils/transitionEvents'; 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 }; return _this; } _createClass(Swipe, [{ key: 'componentWillMount', value: function componentWillMount() { this.parseItem(this.props); } }, { key: 'componentDidMount', value: function componentDidMount() { var _this2 = this; // 监听窗口变化 window.addEventListener("resize", this._updateResize); this.refs.swipeItems.addEventListener("webkitTransitionEnd", function () { return _this2._transitionEnd(); }); this.refs.swipeItems.addEventListener("transitionend", function () { return _this2._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() { var _this3 = this; // 自动轮播结束 this.pauseAutoPlay(); // 移除监听窗口变化 window.removeEventListener("resize", this._updateResize); this.refs.swipeItems.removeEventListener("webkitTransitionEnd", function () { return _this3._transitionEnd(); }); this.refs.swipeItems.removeEventListener("transitionend", function () { return _this3._transitionEnd(); }); } }, { key: 'render', value: function render() { var _this4 = this; var _props = this.props, className = _props.className, height = _props.height, children = _props.children, others = _objectWithoutProperties(_props, ['className', 'height', 'children']); var classes = (0, _classnames3.default)(_defineProperty({ 'ui-swipe': true }, className, !!className)); 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', _extends({}, others, { className: classes }), _react2.default.createElement( 'div', { ref: 'swipeItems', className: 'ui-swipe-items', style: style.items, onTouchStart: function onTouchStart(event) { return _this4._onTouchStart(event); }, onTouchMove: function onTouchMove(event) { return _this4._onTouchMove(event); }, onTouchEnd: function onTouchEnd(event) { return _this4._onTouchEnd(event); } }, this.state.items ), _react2.default.createElement( 'div', { className: 'ui-swipe-pagination' }, _react2.default.createElement( 'ul', null, _react.Children.map(children, function (result, index) { return _react2.default.createElement('li', { key: "pagination-" + index, className: (0, _classnames3.default)({ 'active': index == _this4.state.activeIndex }), style: style.pagination, onClick: function onClick() { return _this4.onSlideTo(index); } }); }) ) ) ); } }, { key: 'parseItem', value: function parseItem(props) { if (props.children.length == 0) { return; } // 增加头尾拼接节点 var items = [].concat(props.children), firstItem = items[0], lastItem = items[items.length - 1]; if (props.isLoop) { 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 }); // 自动轮播开始 !this.moveInterval && this.startAutoPlay(props); } // 自动轮播开始 }, { key: 'startAutoPlay', value: function startAutoPlay() { var _this5 = this; this.moveInterval = this.props.autoPlay && setInterval(function () { var activeIndex = _this5.state.activeIndex, maxLength = _this5.props.children.length; activeIndex = ['left', 'top'].indexOf(_this5.props.direction) > -1 ? activeIndex + 1 : activeIndex - 1; if (activeIndex > maxLength - 1) { // 不循环暂停轮播 if (!_this5.props.isLoop) { _this5.pauseAutoPlay(); return; } activeIndex = 0; _this5.onJumpTo(-1); } else if (activeIndex < 0) { activeIndex = maxLength - 1; _this5.onJumpTo(maxLength); } _this5.onSlideTo(activeIndex); }, this.props.autoPlayIntervalTime); } // 暂停自动轮播 }, { key: 'pauseAutoPlay', value: function pauseAutoPlay() { if (this.moveInterval) { clearInterval(this.moveInterval); } } // 滑动到指定编号 }, { key: 'onSlideTo', value: function onSlideTo(index) { this._onMoveTo(index, this.props.speed); } // 静默跳到指定编号 }, { key: 'onJumpTo', value: function onJumpTo(index) { this._onMoveTo(index, 0); } // 更新窗口变化的位置偏移 }, { key: '_updateResize', value: function _updateResize() { this.onJumpTo(this.props.activeIndex); } // 移动到指定编号 }, { key: '_onMoveTo', value: function _onMoveTo(index, speed) { var dom = this.refs.swipeItems; if (!dom) { return; } var px = this._isDirectionX() ? -dom.offsetWidth * (index + this.props.isLoop) : -dom.offsetHeight * (index + this.props.isLoop); this._doTransition(px, speed); this.translateX = px; this.setState({ activeIndex: index }); } // 执行过渡动画 }, { key: '_doTransition', value: function _doTransition(offset, duration) { var dom = this.refs.swipeItems, x = 0, y = 0; if (this._isDirectionX()) { x = offset; } else { y = offset; } dom.style.webkitTransitionDuration = duration + "ms"; dom.style.mozTransitionDuration = duration + "ms"; dom.style.oTransitionDuration = duration + "ms"; dom.style.transitionDuration = duration + "ms"; dom.style.webkitTransform = "translate3d(" + x + "px, " + y + "px, 0)"; dom.style.mozTransform = "translate3d(" + x + "px, " + y + "px, 0)"; dom.style.oTransform = "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, 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), activeIndex = this.state.activeIndex, 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), px = this.translateX + (pointX - this.pointStart), dom = this.refs.swipeItems; // 设置不循环的时候,当前如果是在头尾页时禁止拖动 if (!this.props.isLoop && (this._isLastIndex() && pointX - this.pointStart < 0 || this._isFirstIndex() && pointX - this.pointStart > 0)) { return; } this._doTransition(px, 0); this.pointEnd = pointX; } }, { key: '_onTouchEnd', value: function _onTouchEnd(event) { var dom = this.refs.swipeItems, px = this.pointEnd !== 0 ? this.pointEnd - this.pointStart : 0, 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; } 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() { var dir = ['left', 'right'].indexOf(this.props.direction) > -1 ? true : false; return dir; } }]); return Swipe; }(_react.Component); Swipe.propTypes = { direction: _propTypes2.default.oneOf(['left', 'right', 'top', 'bottom']), height: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]), isLoop: _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, onChangeEnd: _propTypes2.default.func }; Swipe.defaultProps = { direction: 'left', height: 160, isLoop: true, activeIndex: 0, speed: 300, autoPlay: true, autoPlayIntervalTime: 3000, moveDistanceRatio: 0.5, moveTimeSpan: 300, onChangeEnd: function onChangeEnd() {} }; exports.default = Swipe;