UNPKG

rc-banner-anim

Version:
178 lines (158 loc) 5.82 kB
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 from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; import Tween from 'rc-tween-one/es/Tween'; import { stylesToCss } from 'style-utils'; import { currentScrollTop, toArrayChildren, windowHeight } from './utils'; import animType from './anim'; var BgElement = function (_React$Component) { _inherits(BgElement, _React$Component); function BgElement(props) { _classCallCheck(this, BgElement); var _this = _possibleConstructorReturn(this, _React$Component.call(this, props)); _this.onScroll = function () { var scrollTop = currentScrollTop(); var domRect = _this.dom.parentNode.getBoundingClientRect(); var offsetTop = domRect.top + scrollTop; var height = Math.max(domRect.height, windowHeight()); var elementShowHeight = scrollTop - offsetTop + height; var scale = elementShowHeight / (height + domRect.height); scale = scale || 0; scale = scale >= 1 ? 1 : scale; _this.tween.frame(scale * _this.scrollParallaxDuration); }; _this.onResize = function () { if (!_this.props.show) { return; } var domRect = _this.dom.getBoundingClientRect(); var videoDomRect = _this.video.getBoundingClientRect(); _this.videoLoad = true; var scale = void 0; var videoRect = { display: 'block', position: 'relative', top: 0, left: 0 }; if (domRect.width / domRect.height > videoDomRect.width / videoDomRect.height) { scale = domRect.width / videoDomRect.width; videoRect.width = domRect.width; videoRect.height = videoDomRect.height * scale; videoRect.top = -(videoRect.height - domRect.height) / 2; } else { scale = domRect.height / videoDomRect.height; videoRect.height = domRect.height; videoRect.width = videoDomRect.width * scale; videoRect.left = -(videoRect.width - domRect.width) / 2; } Object.keys(videoRect).forEach(function (key) { _this.video.style[key] = stylesToCss(key, videoRect[key]); }); }; _this.videoLoadedData = function () { _this.onResize(); if (window.addEventListener) { window.addEventListener('resize', _this.onResize); } else { window.attachEvent('onresize', _this.onResize); } }; _this.isVideo = toArrayChildren(_this.props.children).some(function (item) { return item.type === 'video'; }); if (_this.isVideo) { // 如果是 video,删除 grid 系列,位置发生变化,重加载了 video; delete animType.grid; delete animType.gridBar; } if (_this.props.scrollParallax) { _this.scrollParallaxDuration = _this.props.scrollParallax.duration || 450; } _this.video = null; _this.videoLoad = false; return _this; } BgElement.prototype.componentDidMount = function componentDidMount() { this.dom = ReactDOM.findDOMNode(this); if (!this.videoLoad) { if (this.video && this.props.videoResize) { this.video.onloadeddata = this.videoLoadedData; } } if (this.props.scrollParallax) { this.tween = new Tween(this.dom, [_extends({ ease: 'linear' }, this.props.scrollParallax)], { attr: 'style' }); this.tween.frame(0); this.onScroll(); if (window.addEventListener) { window.addEventListener('scroll', this.onScroll); } else { window.attachEvent('onscroll', this.onScroll); } } }; BgElement.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) { var _this2 = this; if (nextProps.show) { // 取 dom 在 render 之后; setTimeout(function () { if (_this2.video && _this2.props.videoResize && _this2.videoLoad) { _this2.onResize(); } if (_this2.props.scrollParallax) { _this2.onScroll(); } }); } }; BgElement.prototype.componentWillUnmount = function componentWillUnmount() { if (window.addEventListener) { window.removeEventListener('resize', this.onResize); window.removeEventListener('scroll', this.onScroll); } else { window.detachEvent('onresize', this.onResize); window.detachEvent('onscroll', this.onScroll); } }; BgElement.prototype.render = function render() { var _this3 = this; var props = _extends({}, this.props); ['videoResize', 'scrollParallax', 'scrollParallaxDuration', 'show', 'component'].forEach(function (key) { return delete props[key]; }); if (this.isVideo && this.props.videoResize) { var children = toArrayChildren(props.children).map(function (item, i) { return React.cloneElement(item, _extends({}, item.props, { key: item.key || 'bg-video-' + i, ref: function ref(c) { _this3.video = c; if (typeof item.ref === 'function') { item.ref(c); } } })); }); props.children = children.length === 1 ? children[0] : children; } return React.createElement(this.props.component, props); }; return BgElement; }(React.Component); export default BgElement; BgElement.propTypes = { className: PropTypes.string, style: PropTypes.object, children: PropTypes.any, component: PropTypes.any, videoResize: PropTypes.bool, scrollParallax: PropTypes.object, show: PropTypes.bool }; BgElement.defaultProps = { component: 'div', videoResize: true }; BgElement.isBannerAnimBgElement = true;