UNPKG

11.5 kBJavaScriptView Raw
1import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
2import _extends from 'babel-runtime/helpers/extends';
3import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
4import _createClass from 'babel-runtime/helpers/createClass';
5import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
6import _inherits from 'babel-runtime/helpers/inherits';
7import React, { Component } from 'react';
8import PropTypes from 'prop-types';
9import ReactDOM from 'react-dom';
10import TweenOne from 'rc-tween-one';
11import ticker from 'rc-tween-one/es/ticker';
12import easeTween from 'tween-functions';
13import { getGsapType, isConvert, stylesToCss, checkStyleName } from 'style-utils';
14
15import BgElement from './BgElement';
16import { currentScrollTop, currentScrollLeft, dataToArray, toArrayChildren } from './utils';
17
18function noop() {}
19
20var Element = function (_Component) {
21 _inherits(Element, _Component);
22
23 function Element(props) {
24 _classCallCheck(this, Element);
25
26 var _this = _possibleConstructorReturn(this, (Element.__proto__ || Object.getPrototypeOf(Element)).call(this, props));
27
28 _initialiseProps.call(_this);
29
30 _this.state = {
31 show: _this.props.show
32 };
33 _this.tickerId = -1;
34 _this.enterMouse = null;
35 _this.delayTimeout = null;
36 _this.show = _this.state.show;
37 _this.followParallax = _this.props.followParallax;
38 _this.transform = checkStyleName('transform');
39 return _this;
40 }
41
42 _createClass(Element, [{
43 key: 'componentDidMount',
44 value: function componentDidMount() {
45 this.dom = ReactDOM.findDOMNode(this);
46 }
47 }, {
48 key: 'componentWillReceiveProps',
49 value: function componentWillReceiveProps(nextProps) {
50 var show = nextProps.show;
51 if (this.tickerId !== -1) {
52 ticker.clear(this.tickerId);
53 this.tickerId = -1;
54 }
55 var followParallax = nextProps.followParallax;
56 if (this.followParallax && !followParallax) {
57 this.reFollowParallax();
58 } else {
59 this.followParallax = followParallax;
60 }
61 this.setState({ show: show, mouseMoveType: nextProps.mouseMoveType });
62 }
63 }, {
64 key: 'componentDidUpdate',
65 value: function componentDidUpdate() {
66 if (this.followParallax) {
67 this.doms = this.followParallax.data.map(function (item) {
68 return document.getElementById(item.id);
69 });
70 }
71 }
72 }, {
73 key: 'componentWillUnmount',
74 value: function componentWillUnmount() {
75 ticker.clear(this.timeoutID);
76 ticker.clear(this.delayTimeout);
77 this.delayTimeout = -1;
78 this.timeoutID = -1;
79 }
80 }, {
81 key: 'render',
82 value: function render() {
83 var _this2 = this;
84
85 var props = _extends({}, this.props, this.props.componentProps);
86 var style = _extends({}, props.style);
87 style.display = props.show ? 'block' : 'none';
88 style.position = 'absolute';
89 style.width = '100%';
90 if (this.props.mouseMoveType !== 'end') {
91 style[this.transform] = '';
92 }
93 props.style = style;
94 props.className = ('banner-anim-elem ' + (this.props.prefixCls || '')).trim();
95 var bgElem = toArrayChildren(this.props.children).filter(function (item) {
96 return item && item.type.isBannerAnimBgElement;
97 }).map(function (item) {
98 return React.cloneElement(item, { show: _this2.state.show });
99 });
100 ['prefixCls', 'callBack', 'animType', 'duration', 'delay', 'ease', 'elemOffset', 'followParallax', 'show', 'type', 'direction', 'leaveChildHide', 'sync', 'ratio', 'mouseMoveType'].forEach(function (key) {
101 return delete props[key];
102 });
103 if (this.show === this.state.show && !this.state.mouseMoveType || this.state.mouseMoveType === 'reChild') {
104 if (!this.state.show) {
105 this.enterMouse = null;
106 return React.createElement(TweenOne, props, bgElem);
107 }
108 if (this.props.followParallax) {
109 props.onMouseMove = this.getFollowMouseMove();
110 }
111 return React.createElement(TweenOne, props, this.props.mouseMoveType === 'update' ? bgElem : this.getChildren());
112 }
113 return this.animChildren(props, style, bgElem);
114 }
115 }]);
116
117 return Element;
118}(Component);
119
120var _initialiseProps = function _initialiseProps() {
121 var _this3 = this;
122
123 this.onMouseMove = function (e) {
124 _this3.domRect = _this3.dom.getBoundingClientRect();
125 _this3.enterMouse = _this3.enterMouse || { x: _this3.domRect.width / 2, y: _this3.domRect.height / 2 };
126 _this3.domWH = {
127 w: _this3.domRect.width,
128 h: _this3.domRect.height
129 };
130 _this3.offsetTop = _this3.domRect.top + currentScrollTop();
131 _this3.offsetLeft = _this3.domRect.left + currentScrollLeft();
132 var mouseXY = {
133 x: e.pageX - _this3.offsetLeft,
134 y: e.pageY - _this3.offsetTop
135 };
136 _this3.setTicker(_this3.followParallax, mouseXY);
137 };
138
139 this.setTicker = function (followParallax, mouseXY) {
140 var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : noop;
141
142 ticker.clear(_this3.tickerId);
143 _this3.tickerId = 'bannerElementTicker' + (Date.now() + Math.random());
144 var startFrame = ticker.frame;
145 var startX = _this3.enterMouse.x;
146 var startY = _this3.enterMouse.y;
147 var duration = followParallax.duration || 450;
148 var easeFunc = easeTween[followParallax.ease || 'easeOutQuad'];
149 var start = typeof followParallax.minMove === 'number' ? followParallax.minMove : 0.08;
150 ticker.wake(_this3.tickerId, function () {
151 var moment = (ticker.frame - startFrame) * ticker.perFrame;
152 var ratio = easeFunc(moment, start, 1, duration);
153 _this3.enterMouse.x = startX + (mouseXY.x - startX) * ratio;
154 _this3.enterMouse.y = startY + (mouseXY.y - startY) * ratio;
155 _this3.setFollowStyle(_this3.domWH);
156 if (moment >= duration) {
157 ticker.clear(_this3.tickerId);
158 callback();
159 }
160 });
161 };
162
163 this.getFollowMouseMove = function () {
164 var onMouseMove = void 0;
165 if (_this3.followParallax) {
166 if (_this3.followParallax.delay) {
167 onMouseMove = !_this3.delayTimeout ? null : _this3.state.onMouseMove;
168 _this3.delayTimeout = _this3.delayTimeout || ticker.timeout(function () {
169 _this3.setState({
170 onMouseMove: _this3.onMouseMove
171 });
172 }, _this3.followParallax.delay);
173 } else {
174 onMouseMove = _this3.onMouseMove;
175 }
176 }
177 return onMouseMove;
178 };
179
180 this.getFollowStyle = function (data, domWH) {
181 var style = {};
182 dataToArray(data.type).forEach(function (type) {
183 var mouseData = _this3.enterMouse.x;
184 var domData = domWH.w;
185 var value = data.value;
186 if ((type.indexOf('y') >= 0 || type.indexOf('Y') >= 0) && type !== 'opacity') {
187 mouseData = _this3.enterMouse.y;
188 domData = domWH.h;
189 }
190 var d = (mouseData - domData / 2) / (domData / 2) * value;
191 var _type = getGsapType(type);
192 var cssName = isConvert(_type);
193 if (cssName === 'transform') {
194 var transform = checkStyleName('transform');
195 style[transform] = style[transform] || {};
196 style[transform][_type] = stylesToCss(_type, d).trim();
197 } else if (cssName === 'filter') {
198 var filter = checkStyleName('filter');
199 style[filter] = style[filter] || {};
200 style[filter][_type] = stylesToCss(_type, d).trim();
201 } else {
202 style[cssName] = stylesToCss(_type, d).trim();
203 }
204 });
205 return style;
206 };
207
208 this.setFollowStyle = function (domWH) {
209 _this3.doms.forEach(function (item, i) {
210 if (!item) {
211 return;
212 }
213 var data = _this3.followParallax.data[i];
214 var style = _this3.getFollowStyle(data, domWH);
215 Object.keys(style).forEach(function (key) {
216 if (typeof style[key] === 'object') {
217 var styleStr = '';
218 Object.keys(style[key]).forEach(function (_key) {
219 styleStr += (' ' + _key + '(' + style[key][_key] + ')').trim();
220 });
221 item.style[key] = styleStr;
222 return;
223 }
224 item.style[key] = key.indexOf('backgroundPosition') >= 0 ? 'calc(' + (data.bgPosition || '0%') + ' + ' + style[key] + ' )' : style[key];
225 });
226 });
227 };
228
229 this.getChildren = function () {
230 return toArrayChildren(_this3.props.children).map(function (item) {
231 if (item && item.type === BgElement) {
232 return React.cloneElement(item, { show: _this3.state.show });
233 }
234 return item;
235 });
236 };
237
238 this.reFollowParallax = function () {
239 _this3.setTicker(_this3.followParallax, {
240 x: _this3.domRect.width / 2 - _this3.offsetLeft,
241 y: _this3.domRect.height / 2 - _this3.offsetTop
242 }, function () {
243 _this3.followParallax = null;
244 });
245 };
246
247 this.animEnd = function () {
248 var type = _this3.state.show ? 'enter' : 'leave';
249 _this3.props.callBack(type);
250 _this3.setState(function (_, props) {
251 return { show: props.show, mouseMoveType: null };
252 });
253 };
254
255 this.animChildren = function (props, style, bgElem) {
256 var _props = _this3.props,
257 elemOffset = _props.elemOffset,
258 leaveChildHide = _props.leaveChildHide,
259 ratio = _props.ratio,
260 animType = _props.animType,
261 direction = _props.direction,
262 mouseMoveType = _props.mouseMoveType,
263 ease = _props.ease,
264 duration = _props.duration,
265 delay = _props.delay,
266 show = _props.show,
267 sync = _props.sync,
268 component = _props.component;
269
270 if (_this3.tickerId) {
271 ticker.clear(_this3.tickerId);
272 }
273 if (_this3.delayTimeout) {
274 ticker.clear(_this3.delayTimeout);
275 _this3.delayTimeout = null;
276 }
277 style.display = 'block';
278
279 props.component = component;
280 _this3.show = _this3.state.show;
281 style.zIndex = _this3.state.show ? 1 : 0;
282 props.children = show && !sync ? bgElem : _this3.getChildren();
283 var childrenToRender = React.createElement(TweenOne, props);
284 var type = _this3.state.show ? 'enter' : 'leave';
285 var $ratio = mouseMoveType === 'end' && ratio <= 0.3 ? 1 - ratio : ratio;
286 var tag = animType(childrenToRender, type, direction, {
287 ease: ease,
288 duration: duration,
289 delay: delay,
290 onComplete: _this3.animEnd
291 }, elemOffset, leaveChildHide, $ratio, _this3.state.mouseMoveType === 'update');
292
293 var tagProps = _objectWithoutProperties(tag.props, []);
294
295 if (tagProps.animation) {
296 tagProps.moment = (tagProps.animation.duration + tagProps.animation.delay) * $ratio || 0;
297 tagProps.paused = _this3.state.mouseMoveType === 'update' || $ratio === 1;
298 }
299 return React.cloneElement(tag, tagProps);
300 };
301};
302
303Element.propTypes = {
304 children: PropTypes.any,
305 style: PropTypes.object,
306 prefixCls: PropTypes.string,
307 component: PropTypes.any,
308 elemOffset: PropTypes.object,
309 type: PropTypes.string,
310 animType: PropTypes.func,
311 ease: PropTypes.string,
312 duration: PropTypes.number,
313 delay: PropTypes.number,
314 direction: PropTypes.string,
315 callBack: PropTypes.func,
316 followParallax: PropTypes.any,
317 show: PropTypes.bool,
318 leaveChildHide: PropTypes.bool,
319 sync: PropTypes.bool,
320 ratio: PropTypes.number,
321 mouseMoveType: PropTypes.string,
322 componentProps: PropTypes.object
323};
324Element.defaultProps = {
325 component: 'div',
326 componentProps: {},
327 callBack: noop,
328 delay: 0
329};
330
331Element.BgElement = BgElement;
332Element.isBannerAnimElement = true;
333export default Element;
\No newline at end of file