UNPKG

6.19 kBJavaScriptView Raw
1import _extends from 'babel-runtime/helpers/extends';
2import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
3import _createClass from 'babel-runtime/helpers/createClass';
4import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
5import _inherits from 'babel-runtime/helpers/inherits';
6import React from 'react';
7import ReactDOM from 'react-dom';
8import PropTypes from 'prop-types';
9import Tween from 'rc-tween-one/es/Tween';
10import { stylesToCss } from 'style-utils';
11import { currentScrollTop, toArrayChildren, windowHeight } from './utils';
12import animType from './anim';
13
14var BgElement = function (_React$Component) {
15 _inherits(BgElement, _React$Component);
16
17 function BgElement(props) {
18 _classCallCheck(this, BgElement);
19
20 var _this = _possibleConstructorReturn(this, (BgElement.__proto__ || Object.getPrototypeOf(BgElement)).call(this, props));
21
22 _this.onScroll = function () {
23 var scrollTop = currentScrollTop();
24 var domRect = _this.dom.parentNode.getBoundingClientRect();
25 var offsetTop = domRect.top + scrollTop;
26 var height = Math.max(domRect.height, windowHeight());
27 var elementShowHeight = scrollTop - offsetTop + height;
28 var scale = elementShowHeight / (height + domRect.height);
29 scale = scale || 0;
30 scale = scale >= 1 ? 1 : scale;
31 _this.tween.frame(scale * _this.scrollParallaxDuration);
32 };
33
34 _this.onResize = function () {
35 if (!_this.props.show) {
36 return;
37 }
38 var domRect = _this.dom.getBoundingClientRect();
39 var videoDomRect = _this.video.getBoundingClientRect();
40 _this.videoLoad = true;
41 var scale = void 0;
42 var videoRect = {
43 display: 'block',
44 position: 'relative',
45 top: 0,
46 left: 0
47 };
48 if (domRect.width / domRect.height > videoDomRect.width / videoDomRect.height) {
49 scale = domRect.width / videoDomRect.width;
50 videoRect.width = domRect.width;
51 videoRect.height = videoDomRect.height * scale;
52 videoRect.top = -(videoRect.height - domRect.height) / 2;
53 } else {
54 scale = domRect.height / videoDomRect.height;
55 videoRect.height = domRect.height;
56 videoRect.width = videoDomRect.width * scale;
57 videoRect.left = -(videoRect.width - domRect.width) / 2;
58 }
59
60 Object.keys(videoRect).forEach(function (key) {
61 _this.video.style[key] = stylesToCss(key, videoRect[key]);
62 });
63 };
64
65 _this.videoLoadedData = function () {
66 _this.onResize();
67 if (window.addEventListener) {
68 window.addEventListener('resize', _this.onResize);
69 } else {
70 window.attachEvent('onresize', _this.onResize);
71 }
72 };
73
74 _this.isVideo = toArrayChildren(_this.props.children).some(function (item) {
75 return item.type === 'video';
76 });
77 if (_this.isVideo) {
78 // 如果是 video,删除 grid 系列,位置发生变化,重加载了 video;
79 delete animType.grid;
80 delete animType.gridBar;
81 }
82 if (_this.props.scrollParallax) {
83 _this.scrollParallaxDuration = _this.props.scrollParallax.duration || 450;
84 }
85 _this.video = null;
86 _this.videoLoad = false;
87 return _this;
88 }
89
90 _createClass(BgElement, [{
91 key: 'componentDidMount',
92 value: function componentDidMount() {
93 this.dom = ReactDOM.findDOMNode(this);
94 if (!this.videoLoad) {
95 if (this.video && this.props.videoResize) {
96 this.video.onloadeddata = this.videoLoadedData;
97 }
98 }
99 if (this.props.scrollParallax) {
100 this.tween = new Tween(this.dom, [_extends({
101 ease: 'linear' }, this.props.scrollParallax)], { attr: 'style' });
102 this.tween.frame(0);
103 this.onScroll();
104 if (window.addEventListener) {
105 window.addEventListener('scroll', this.onScroll);
106 } else {
107 window.attachEvent('onscroll', this.onScroll);
108 }
109 }
110 }
111 }, {
112 key: 'componentWillReceiveProps',
113 value: function componentWillReceiveProps(nextProps) {
114 var _this2 = this;
115
116 if (nextProps.show) {
117 // 取 dom 在 render 之后;
118 setTimeout(function () {
119 if (_this2.video && _this2.props.videoResize && _this2.videoLoad) {
120 _this2.onResize();
121 }
122 if (_this2.props.scrollParallax) {
123 _this2.onScroll();
124 }
125 });
126 }
127 }
128 }, {
129 key: 'componentWillUnmount',
130 value: function componentWillUnmount() {
131 if (window.addEventListener) {
132 window.removeEventListener('resize', this.onResize);
133 window.removeEventListener('scroll', this.onScroll);
134 } else {
135 window.detachEvent('onresize', this.onResize);
136 window.detachEvent('onscroll', this.onScroll);
137 }
138 }
139 }, {
140 key: 'render',
141 value: function render() {
142 var _this3 = this;
143
144 var props = _extends({}, this.props, this.props.componentProps);
145 ['videoResize', 'scrollParallax', 'scrollParallaxDuration', 'show', 'component', 'componentProps'].forEach(function (key) {
146 return delete props[key];
147 });
148 if (this.isVideo && this.props.videoResize) {
149 var children = toArrayChildren(props.children).map(function (item, i) {
150 return React.cloneElement(item, _extends({}, item.props, { key: item.key || 'bg-video-' + i, ref: function ref(c) {
151 _this3.video = c;
152 if (typeof item.ref === 'function') {
153 item.ref(c);
154 }
155 }
156 }));
157 });
158 props.children = children.length === 1 ? children[0] : children;
159 }
160 return React.createElement(this.props.component, props);
161 }
162 }]);
163
164 return BgElement;
165}(React.Component);
166
167export default BgElement;
168
169
170BgElement.propTypes = {
171 className: PropTypes.string,
172 style: PropTypes.object,
173 children: PropTypes.any,
174 component: PropTypes.any,
175 videoResize: PropTypes.bool,
176 scrollParallax: PropTypes.object,
177 show: PropTypes.bool,
178 componentProps: PropTypes.object
179};
180
181BgElement.defaultProps = {
182 component: 'div',
183 videoResize: true,
184 componentProps: {}
185};
186
187BgElement.isBannerAnimBgElement = true;
\No newline at end of file