UNPKG

rc-banner-anim

Version:
321 lines (290 loc) 11.1 kB
import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties'; import _extends from 'babel-runtime/helpers/extends'; import _classCallCheck from 'babel-runtime/helpers/classCallCheck'; import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn'; import _inherits from 'babel-runtime/helpers/inherits'; import React, { Component } from 'react'; import PropTypes from 'prop-types'; import ReactDOM from 'react-dom'; import TweenOne from 'rc-tween-one'; import ticker from 'rc-tween-one/es/ticker'; import easeTween from 'tween-functions'; import { getGsapType, isConvert, stylesToCss, checkStyleName } from 'style-utils'; import BgElement from './BgElement'; import { currentScrollTop, currentScrollLeft, dataToArray, toArrayChildren } from './utils'; function noop() {} var Element = function (_Component) { _inherits(Element, _Component); function Element(props) { _classCallCheck(this, Element); var _this = _possibleConstructorReturn(this, _Component.call(this, props)); _initialiseProps.call(_this); _this.state = { show: _this.props.show }; _this.tickerId = -1; _this.enterMouse = null; _this.delayTimeout = null; _this.show = _this.state.show; _this.followParallax = _this.props.followParallax; _this.transform = checkStyleName('transform'); return _this; } Element.prototype.componentDidMount = function componentDidMount() { this.dom = ReactDOM.findDOMNode(this); }; Element.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) { var show = nextProps.show; if (this.tickerId !== -1) { ticker.clear(this.tickerId); this.tickerId = -1; } var followParallax = nextProps.followParallax; if (this.followParallax && !followParallax) { this.reFollowParallax(); } else { this.followParallax = followParallax; } this.setState({ show: show, mouseMoveType: nextProps.mouseMoveType }); }; Element.prototype.componentDidUpdate = function componentDidUpdate() { if (this.followParallax) { this.doms = this.followParallax.data.map(function (item) { return document.getElementById(item.id); }); } }; Element.prototype.componentWillUnmount = function componentWillUnmount() { ticker.clear(this.timeoutID); ticker.clear(this.delayTimeout); this.delayTimeout = -1; this.timeoutID = -1; }; Element.prototype.render = function render() { var _this2 = this; var props = _extends({}, this.props); var style = _extends({}, props.style); style.display = props.show ? 'block' : 'none'; style.position = 'absolute'; style.width = '100%'; if (this.props.mouseMoveType !== 'end') { style[this.transform] = ''; } props.style = style; props.className = ('banner-anim-elem ' + (this.props.prefixCls || '')).trim(); var bgElem = toArrayChildren(this.props.children).filter(function (item) { return item.type.isBannerAnimBgElement; }).map(function (item) { return React.cloneElement(item, { show: _this2.state.show }); }); ['prefixCls', 'callBack', 'animType', 'duration', 'delay', 'ease', 'elemOffset', 'followParallax', 'show', 'type', 'direction', 'leaveChildHide', 'sync', 'ratio', 'mouseMoveType'].forEach(function (key) { return delete props[key]; }); if (this.show === this.state.show && !this.state.mouseMoveType || this.state.mouseMoveType === 'reChild') { if (!this.state.show) { this.enterMouse = null; return React.createElement(TweenOne, props, bgElem); } if (this.props.followParallax) { props.onMouseMove = this.getFollowMouseMove(); } return React.createElement(TweenOne, props, this.props.mouseMoveType === 'update' ? bgElem : this.getChildren()); } return this.animChildren(props, style, bgElem); }; return Element; }(Component); var _initialiseProps = function _initialiseProps() { var _this3 = this; this.onMouseMove = function (e) { _this3.domRect = _this3.dom.getBoundingClientRect(); _this3.enterMouse = _this3.enterMouse || { x: _this3.domRect.width / 2, y: _this3.domRect.height / 2 }; _this3.domWH = { w: _this3.domRect.width, h: _this3.domRect.height }; _this3.offsetTop = _this3.domRect.top + currentScrollTop(); _this3.offsetLeft = _this3.domRect.left + currentScrollLeft(); var mouseXY = { x: e.pageX - _this3.offsetLeft, y: e.pageY - _this3.offsetTop }; _this3.setTicker(_this3.followParallax, mouseXY); }; this.setTicker = function (followParallax, mouseXY) { var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : noop; ticker.clear(_this3.tickerId); _this3.tickerId = 'bannerElementTicker' + (Date.now() + Math.random()); var startFrame = ticker.frame; var startX = _this3.enterMouse.x; var startY = _this3.enterMouse.y; var duration = followParallax.duration || 450; var easeFunc = easeTween[followParallax.ease || 'easeOutQuad']; var start = typeof followParallax.minMove === 'number' ? followParallax.minMove : 0.08; ticker.wake(_this3.tickerId, function () { var moment = (ticker.frame - startFrame) * ticker.perFrame; var ratio = easeFunc(moment, start, 1, duration); _this3.enterMouse.x = startX + (mouseXY.x - startX) * ratio; _this3.enterMouse.y = startY + (mouseXY.y - startY) * ratio; _this3.setFollowStyle(_this3.domWH); if (moment >= duration) { ticker.clear(_this3.tickerId); callback(); } }); }; this.getFollowMouseMove = function () { var onMouseMove = void 0; if (_this3.followParallax) { if (_this3.followParallax.delay) { onMouseMove = !_this3.delayTimeout ? null : _this3.state.onMouseMove; _this3.delayTimeout = _this3.delayTimeout || ticker.timeout(function () { _this3.setState({ onMouseMove: _this3.onMouseMove }); }, _this3.followParallax.delay); } else { onMouseMove = _this3.onMouseMove; } } return onMouseMove; }; this.getFollowStyle = function (data, domWH) { var style = {}; dataToArray(data.type).forEach(function (type) { var mouseData = _this3.enterMouse.x; var domData = domWH.w; var value = data.value; if ((type.indexOf('y') >= 0 || type.indexOf('Y') >= 0) && type !== 'opacity') { mouseData = _this3.enterMouse.y; domData = domWH.h; } var d = (mouseData - domData / 2) / (domData / 2) * value; var _type = getGsapType(type); var cssName = isConvert(_type); if (cssName === 'transform') { var transform = checkStyleName('transform'); style[transform] = style[transform] || {}; style[transform][_type] = stylesToCss(_type, d).trim(); } else if (cssName === 'filter') { var filter = checkStyleName('filter'); style[filter] = style[filter] || {}; style[filter][_type] = stylesToCss(_type, d).trim(); } else { style[cssName] = stylesToCss(_type, d).trim(); } }); return style; }; this.setFollowStyle = function (domWH) { _this3.doms.forEach(function (item, i) { if (!item) { return; } var data = _this3.followParallax.data[i]; var style = _this3.getFollowStyle(data, domWH); Object.keys(style).forEach(function (key) { if (typeof style[key] === 'object') { var styleStr = ''; Object.keys(style[key]).forEach(function (_key) { styleStr += (' ' + _key + '(' + style[key][_key] + ')').trim(); }); item.style[key] = styleStr; return; } item.style[key] = key.indexOf('backgroundPosition') >= 0 ? 'calc(' + (data.bgPosition || '0%') + ' + ' + style[key] + ' )' : style[key]; }); }); }; this.getChildren = function () { return toArrayChildren(_this3.props.children).map(function (item) { if (item.type === BgElement) { return React.cloneElement(item, { show: _this3.state.show }); } return item; }); }; this.reFollowParallax = function () { _this3.setTicker(_this3.followParallax, { x: _this3.domRect.width / 2 - _this3.offsetLeft, y: _this3.domRect.height / 2 - _this3.offsetTop }, function () { _this3.followParallax = null; }); }; this.animEnd = function () { var type = _this3.state.show ? 'enter' : 'leave'; _this3.props.callBack(type); _this3.setState({ show: _this3.props.show, mouseMoveType: null }); }; this.animChildren = function (props, style, bgElem) { var _props = _this3.props, elemOffset = _props.elemOffset, leaveChildHide = _props.leaveChildHide, ratio = _props.ratio, animType = _props.animType, direction = _props.direction, mouseMoveType = _props.mouseMoveType, ease = _props.ease, duration = _props.duration, delay = _props.delay, show = _props.show, sync = _props.sync, component = _props.component; if (_this3.tickerId) { ticker.clear(_this3.tickerId); } if (_this3.delayTimeout) { ticker.clear(_this3.delayTimeout); _this3.delayTimeout = null; } style.display = 'block'; props.component = component; _this3.show = _this3.state.show; style.zIndex = _this3.state.show ? 1 : 0; props.children = show && !sync ? bgElem : _this3.getChildren(); var childrenToRender = React.createElement(TweenOne, props); var type = _this3.state.show ? 'enter' : 'leave'; var $ratio = mouseMoveType === 'end' && ratio <= 0.3 ? 1 - ratio : ratio; var tag = animType(childrenToRender, type, direction, { ease: ease, duration: duration, delay: delay, onComplete: _this3.animEnd }, elemOffset, leaveChildHide, $ratio, _this3.state.mouseMoveType === 'update'); var tagProps = _objectWithoutProperties(tag.props, []); if (tagProps.animation) { tagProps.moment = (tagProps.animation.duration + tagProps.animation.delay) * $ratio || 0; tagProps.paused = _this3.state.mouseMoveType === 'update' || $ratio === 1; } return React.cloneElement(tag, tagProps); }; }; Element.propTypes = { children: PropTypes.any, style: PropTypes.object, prefixCls: PropTypes.string, component: PropTypes.any, elemOffset: PropTypes.object, type: PropTypes.string, animType: PropTypes.func, ease: PropTypes.string, duration: PropTypes.number, delay: PropTypes.number, direction: PropTypes.string, callBack: PropTypes.func, followParallax: PropTypes.any, show: PropTypes.bool, leaveChildHide: PropTypes.bool, sync: PropTypes.bool, ratio: PropTypes.number, mouseMoveType: PropTypes.string }; Element.defaultProps = { component: 'div', callBack: noop, delay: 0 }; Element.BgElement = BgElement; Element.isBannerAnimElement = true; export default Element;