UNPKG

14.7 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, { Component } from 'react';
7import ReactDOM from 'react-dom';
8import PropTypes from 'prop-types';
9import ticker from 'rc-tween-one/es/ticker';
10import Arrow from './Arrow';
11import Thumb from './Thumb';
12import { toArrayChildren, dataToArray } from './utils';
13import animType from './anim';
14
15var BannerAnim = function (_Component) {
16 _inherits(BannerAnim, _Component);
17
18 function BannerAnim(props) {
19 _classCallCheck(this, BannerAnim);
20
21 var _this = _possibleConstructorReturn(this, (BannerAnim.__proto__ || Object.getPrototypeOf(BannerAnim)).call(this, props));
22
23 _this.onMouseEnter = function (e) {
24 _this.props.onMouseEnter(e);
25 if (_this.props.autoPlay && _this.props.autoPlayEffect) {
26 ticker.clear(_this.autoPlayId);
27 _this.autoPlayId = -1;
28 }
29 };
30
31 _this.onMouseLeave = function (e) {
32 _this.props.onMouseLeave(e);
33 if (_this.props.autoPlay && _this.props.autoPlayEffect) {
34 _this.autoPlay();
35 }
36 };
37
38 _this.onTouchStart = function (e) {
39 if (e.touches && e.touches.length > 1 || _this.elemWrapper.length <= 1 || _this.getDomIsArrowOrThumb(e) || e.button === 2 || _this.tweenBool) {
40 return;
41 }
42 if (_this.props.autoPlay) {
43 ticker.clear(_this.autoPlayId);
44 _this.autoPlayId = -1;
45 }
46 _this.animType = _this.getAnimType(_this.props.type);
47 _this.currentShow = _this.state.currentShow;
48 // this.mouseMoveType = 'start';
49 _this.mouseStartXY = {
50 startX: e.touches === undefined ? e.clientX : e.touches[0].clientX,
51 startY: e.touches === undefined ? e.clientY : e.touches[0].clientY
52 };
53 };
54
55 _this.onTouchMove = function (e) {
56 if (!_this.mouseStartXY || e.touches && e.touches.length > 1 || _this.tweenBool) {
57 return;
58 }
59
60 var _this$getDiffer = _this.getDiffer(e, e.touches),
61 differ = _this$getDiffer.differ,
62 rectName = _this$getDiffer.rectName;
63
64 if (!differ) {
65 return;
66 }
67 var ratio = differ / _this.state.domRect[rectName] * 2;
68 var ratioType = ratio > 0 ? '+' : '-';
69 var currentShow = _this.currentShow;
70 _this.mouseMoveType = 'update';
71 if (_this.ratioType !== ratioType) {
72 _this.ratioType = ratioType;
73 _this.mouseMoveType = 'reChild';
74 _this.setState({
75 currentShow: currentShow
76 });
77 return;
78 }
79 if ((_this.animType === animType.gridBar || _this.animType === animType.grid) && e.touches) {
80 return;
81 }
82 _this.ratio = ratio;
83 if (_this.ratio) {
84 var type = void 0;
85 if (_this.ratio > 0) {
86 currentShow += 1;
87 type = 'next';
88 } else {
89 currentShow -= 1;
90 type = 'prev';
91 }
92 _this.ratio = Math.abs(_this.ratio);
93 _this.ratio = _this.ratio > 0.99 ? 0.99 : _this.ratio;
94 currentShow = currentShow >= _this.elemWrapper.length ? 0 : currentShow;
95 currentShow = currentShow < 0 ? _this.elemWrapper.length - 1 : currentShow;
96 _this.setState({
97 currentShow: currentShow,
98 direction: type
99 });
100 }
101 };
102
103 _this.onTouchEnd = function (e) {
104 if (!_this.mouseStartXY || e.changedTouches && e.changedTouches.length > 1 || _this.tweenBool) {
105 return;
106 }
107 if (_this.props.autoPlay && _this.autoPlayId === -1) {
108 _this.autoPlay();
109 }
110
111 var _this$getDiffer2 = _this.getDiffer(e, e.changedTouches),
112 differ = _this$getDiffer2.differ,
113 rectName = _this$getDiffer2.rectName;
114
115 delete _this.mouseStartXY;
116 _this.mouseMoveType = 'end';
117 if (!differ) {
118 _this.mouseMoveType = '';
119 return;
120 }
121 _this.tweenBool = true;
122 if ((_this.animType === animType.gridBar || _this.animType === animType.grid) && e.changedTouches) {
123 var currentShow = _this.currentShow;
124 var ratio = differ / _this.state.domRect[rectName] * 2;
125 if (ratio > 0) {
126 currentShow += 1;
127 } else {
128 currentShow -= 1;
129 }
130 currentShow = currentShow >= _this.elemWrapper.length ? 0 : currentShow;
131 currentShow = currentShow < 0 ? _this.elemWrapper.length - 1 : currentShow;
132 _this.ratio = 0;
133 _this.mouseMoveType = '';
134 _this.slickGoTo(currentShow, true);
135 return;
136 }
137
138 if (_this.ratio > 0.3) {
139 _this.forceUpdate(function () {
140 _this.ratio = 0;
141 _this.mouseMoveType = '';
142 });
143 } else {
144 _this.setState({
145 currentShow: _this.currentShow,
146 direction: _this.ratioType === '+' ? 'prev' : 'next'
147 }, function () {
148 _this.ratio = 0;
149 _this.mouseMoveType = '';
150 });
151 }
152 };
153
154 _this.getDiffer = function (e, touches) {
155 var currentX = touches === undefined ? e.clientX : touches[0].clientX;
156 var currentY = touches === undefined ? e.clientY : touches[0].clientY;
157 var differX = currentX - _this.mouseStartXY.startX;
158 var differY = currentY - _this.mouseStartXY.startY;
159 var differ = Math.max(Math.abs(differX), Math.abs(differY));
160 differ = differ === Math.abs(differX) ? differX : differY;
161 return {
162 differ: differ,
163 rectName: differ === Math.abs(differX) ? 'width' : 'height'
164 };
165 };
166
167 _this.getDomIsArrowOrThumb = function (e) {
168 var arrowClassName = e.target.className;
169 var thumbClassName = e.target.parentNode.className;
170 if (arrowClassName.indexOf('banner-anim-arrow') >= 0 || thumbClassName.indexOf('banner-anim-thumb') >= 0) {
171 return true;
172 }
173 return false;
174 };
175
176 _this.getRenderChildren = function (children) {
177 var elem = [];
178 var arrow = [];
179 var thumb = void 0;
180 var elementKeyNum = 0;
181 var thumbKeyNum = 0;
182
183 toArrayChildren(children).forEach(function (item, i) {
184 if (!item) {
185 return;
186 }
187 var itemProps = _extends({}, item.props);
188 if (item.type.isBannerAnimElement) {
189 itemProps.key = item.key || 'element-' + elementKeyNum;
190 elementKeyNum += 1;
191 itemProps.callBack = _this.animEnd;
192 itemProps.show = _this.state.currentShow === i;
193 itemProps.animType = _this.animType;
194 itemProps.duration = _this.props.duration;
195 itemProps.delay = _this.props.delay;
196 itemProps.ease = _this.props.ease;
197 itemProps.sync = _this.props.sync || itemProps.sync;
198 itemProps.elemOffset = {
199 top: _this.state.domRect.top,
200 width: _this.state.domRect.width,
201 height: _this.state.wrapperHeight
202 };
203 itemProps.direction = _this.state.direction;
204 itemProps.ratio = _this.ratio;
205 itemProps.mouseMoveType = _this.mouseMoveType;
206 elem.push(React.cloneElement(item, itemProps));
207 } else if (item.type.isBannerAnimArrow) {
208 itemProps.next = _this.next;
209 itemProps.prev = _this.prev;
210 itemProps.key = item.key || itemProps.arrowType;
211 itemProps.elemHeight = _this.state.wrapperHeight;
212 arrow.push(React.cloneElement(item, itemProps));
213 } else if (item.type.isBannerAnimThumb) {
214 itemProps.key = item.key || 'thumb-' + thumbKeyNum;
215 thumbKeyNum += 1;
216 itemProps.thumbClick = _this.slickGoTo;
217 itemProps.active = _this.state.currentShow;
218 thumb = React.cloneElement(item, itemProps);
219 }
220 });
221 if (elem.length > 1) {
222 if (!arrow.length && _this.props.arrow) {
223 arrow.push(React.createElement(Arrow, { arrowType: 'prev', key: 'arrowPrev', next: _this.next, prev: _this.prev, 'default': true,
224 elemHeight: _this.state.wrapperHeight
225 }), React.createElement(Arrow, { arrowType: 'next', key: 'arrowNext', next: _this.next, prev: _this.prev, 'default': true,
226 elemHeight: _this.state.wrapperHeight
227 }));
228 }
229 if (!thumb && _this.props.thumb) {
230 thumb = React.createElement(Thumb, { length: elem.length, key: 'thumb',
231 thumbClick: _this.slickGoTo,
232 active: _this.state.currentShow,
233 'default': true
234 });
235 }
236 }
237 _this.elemWrapper = elem;
238 return elem.concat(arrow, thumb);
239 };
240
241 _this.getDomDataSetToState = function () {
242 _this.dom = ReactDOM.findDOMNode(_this);
243 var domRect = _this.dom.getBoundingClientRect();
244 // 获取宽度与定位,setState刷新;
245 var wrapperHeight = _this.getElementHeight(_this.dom.getElementsByClassName('banner-anim-elem'));
246 _this.setState({
247 wrapperHeight: wrapperHeight,
248 domRect: domRect
249 });
250 _this.tweenBool = false;
251 };
252
253 _this.getElementHeight = function (children) {
254 var height = 0;
255 for (var i = 0; i < children.length; i++) {
256 var dom = children[i];
257 var _height = dom.getBoundingClientRect().height;
258 height = height > _height ? height : _height;
259 }
260 return height;
261 };
262
263 _this.getAnimType = function (type) {
264 var typeArray = type ? dataToArray(type) : Object.keys(animType);
265 var random = Math.round(Math.random() * (typeArray.length - 1));
266 return animType[typeArray[random]];
267 };
268
269 _this.autoPlay = function () {
270 _this.autoPlayId = ticker.interval(_this.next, _this.props.autoPlaySpeed);
271 };
272
273 _this.animTweenStart = function (show, type, noGetAnimType) {
274 if (!noGetAnimType) {
275 _this.animType = _this.getAnimType(_this.props.type);
276 }
277 _this.props.onChange('before', show);
278 _this.setState({
279 currentShow: show,
280 direction: type
281 });
282 };
283
284 _this.animEnd = function (type) {
285 if (type === 'enter') {
286 _this.tweenBool = false;
287 _this.props.onChange('after', _this.state.currentShow);
288 }
289 };
290
291 _this.next = function () {
292 if (!_this.tweenBool) {
293 _this.tweenBool = true;
294 var newShow = _this.state.currentShow;
295 newShow++;
296 if (newShow >= _this.elemWrapper.length) {
297 newShow = 0;
298 }
299 _this.animTweenStart(newShow, 'next');
300 }
301 };
302
303 _this.prev = function () {
304 if (!_this.tweenBool) {
305 _this.tweenBool = true;
306 var newShow = _this.state.currentShow;
307 newShow--;
308 if (newShow < 0) {
309 newShow = _this.elemWrapper.length - 1;
310 }
311 _this.animTweenStart(newShow, 'prev');
312 }
313 };
314
315 _this.slickGoTo = function (i, noGetAnimType) {
316 if (!_this.tweenBool && i !== _this.state.currentShow) {
317 _this.tweenBool = true;
318 var type = i > _this.state.currentShow ? 'next' : 'prev';
319 _this.animTweenStart(i, type, noGetAnimType);
320 }
321 };
322
323 _this.state = {
324 currentShow: _this.props.initShow,
325 direction: null,
326 wrapperHeight: 0,
327 domRect: {}
328 };
329 _this.tweenBool = false;
330 return _this;
331 }
332
333 _createClass(BannerAnim, [{
334 key: 'componentDidMount',
335 value: function componentDidMount() {
336 this.getDomDataSetToState();
337 if (window.addEventListener) {
338 window.addEventListener('resize', this.getDomDataSetToState);
339 } else {
340 window.attachEvent('onresize', this.getDomDataSetToState);
341 }
342 if (this.props.autoPlay) {
343 this.autoPlay();
344 }
345 }
346 }, {
347 key: 'componentWillReceiveProps',
348 value: function componentWillReceiveProps() {
349 this.tweenBool = false;
350 }
351 }, {
352 key: 'componentWillUnmount',
353 value: function componentWillUnmount() {
354 if (this.autoPlayId) {
355 ticker.clear(this.autoPlayId);
356 this.autoPlayId = 0;
357 }
358 if (window.addEventListener) {
359 window.removeEventListener('touchend', this.onTouchEnd);
360 window.removeEventListener('mouseup', this.onTouchEnd);
361 window.removeEventListener('resize', this.getDomDataSetToState);
362 } else {
363 window.detachEvent('ontouchend', this.onTouchEnd);
364 window.attachEvent('onmouseup', this.onTouchEnd);
365 window.detachEvent('onresize', this.getDomDataSetToState);
366 }
367 }
368 }, {
369 key: 'render',
370 value: function render() {
371 var prefixCls = this.props.prefixCls;
372 var props = _extends({}, this.props);
373 ['type', 'prefixCls', 'component', 'initShow', 'duration', 'delay', 'ease', 'arrow', 'thumb', 'autoPlaySpeed', 'autoPlay', 'thumbFloat', 'sync', 'dragPlay', 'autoPlayEffect'].forEach(function (key) {
374 return delete props[key];
375 });
376 var childrenToRender = this.getRenderChildren(props.children);
377 props.className = (props.className + ' ' + (prefixCls || '')).trim();
378 props.style = _extends({}, props.style);
379 props.onMouseEnter = this.onMouseEnter;
380 props.onMouseLeave = this.onMouseLeave;
381 if (childrenToRender.length > 1 && this.props.dragPlay) {
382 props.onTouchStart = this.onTouchStart;
383 props.onMouseDown = this.onTouchStart;
384 props.onTouchMove = this.onTouchMove;
385 props.onMouseMove = this.onTouchMove;
386 props.onTouchEnd = this.onTouchEnd;
387 props.onMouseUp = this.onTouchEnd;
388 }
389 return React.createElement(this.props.component, props, childrenToRender);
390 }
391 }]);
392
393 return BannerAnim;
394}(Component);
395
396BannerAnim.propTypes = {
397 children: PropTypes.any,
398 style: PropTypes.object,
399 className: PropTypes.string,
400 prefixCls: PropTypes.string,
401 component: PropTypes.any,
402 arrow: PropTypes.bool,
403 thumb: PropTypes.bool,
404 initShow: PropTypes.number,
405 type: PropTypes.any,
406 duration: PropTypes.number,
407 delay: PropTypes.number,
408 ease: PropTypes.string,
409 autoPlay: PropTypes.bool,
410 autoPlaySpeed: PropTypes.number,
411 autoPlayEffect: PropTypes.bool,
412 onChange: PropTypes.func,
413 onMouseEnter: PropTypes.func,
414 onMouseLeave: PropTypes.func,
415 sync: PropTypes.bool,
416 dragPlay: PropTypes.bool
417};
418BannerAnim.defaultProps = {
419 component: 'div',
420 className: 'banner-anim',
421 initShow: 0,
422 duration: 450,
423 delay: 0,
424 ease: 'easeInOutQuad',
425 arrow: true,
426 thumb: true,
427 autoPlaySpeed: 5000,
428 autoPlayEffect: true,
429 dragPlay: true,
430 onChange: function onChange() {},
431 onMouseEnter: function onMouseEnter() {},
432 onMouseLeave: function onMouseLeave() {}
433};
434BannerAnim.isBannerAnim = true;
435export default BannerAnim;
\No newline at end of file