Skip to content

Commit 838b24c

Browse files
author
yuji
committed
Merge branch 'redesign-loop'
2 parents e7be14d + 9cb91c5 commit 838b24c

File tree

4 files changed

+269
-163
lines changed

4 files changed

+269
-163
lines changed

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ The best Swiper component for React Native.
1414

1515
- [ ] Check typo
1616

17-
- [ ] Optimal performance when `<Image />` re-render
18-
1917
- [x] Infinite loop
2018

2119
- [x] Direction control

dist/index.js

Lines changed: 87 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,18 @@ Object.defineProperty(exports, '__esModule', {
1111
/*
1212
react-native-swiper
1313
14-
feaure:
15-
[x] loop
16-
[x] dir
17-
[x] custom style
18-
[x] title
19-
[x] multiple instances
20-
[x] custom size
21-
[x] control buttons
22-
[x] autoplay
23-
[ ] more switch effect
24-
25-
params(props):
26-
- dir "x" || "y" @default: "x"
27-
28-
-dot Optionally provide the dot object show in pagination
14+
@author leecade<[email protected]>
2915
*/
3016

3117
var _React$StyleSheet$Text$View$ScrollView$TouchableOpacity = require('react-native');
3218

3319
var _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2 = _interopRequireWildcard(_React$StyleSheet$Text$View$ScrollView$TouchableOpacity);
3420

35-
// Using bare setTimeout, setInterval, setImmediate and requestAnimationFrame calls is very dangerous because if you forget to cancel the request before the component is unmounted, you risk the callback throwing an exception.
21+
// Using bare setTimeout, setInterval, setImmediate
22+
// and requestAnimationFrame calls is very dangerous
23+
// because if you forget to cancel the request before
24+
// the component is unmounted, you risk the callback
25+
// throwing an exception.
3626

3727
var _TimerMixin = require('react-timer-mixin');
3828

@@ -173,15 +163,27 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
173163
*/
174164
getInitialState: function getInitialState() {
175165
var props = this.props;
176-
var length = props.children ? props.children.length || 1 : 0;
177-
return {
178-
index: length > 1 ? props.index : 0,
179-
total: length,
180-
dir: props.horizontal == false ? 'y' : 'x',
181-
width: props.width || width,
182-
height: props.height || height,
166+
167+
var initState = {
183168
isScrolling: false,
184169
autoplayEnd: false };
170+
171+
initState.total = props.children ? props.children.length || 1 : 0;
172+
173+
initState.index = initState.total > 1 ? Math.min(props.index, initState.total - 1) : 0;
174+
175+
// Default: horizontal
176+
initState.dir = props.horizontal == false ? 'y' : 'x';
177+
initState.width = props.width || width;
178+
initState.height = props.height || height;
179+
initState.offset = {};
180+
181+
if (initState.total > 1) {
182+
var setup = props.loop ? 1 : initState.index;
183+
initState.offset[initState.dir] = initState.dir == 'y' ? initState.height * setup : initState.width * setup;
184+
}
185+
186+
return initState;
185187
},
186188

187189
/**
@@ -190,14 +192,20 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
190192
*/
191193
autoplayTimer: null,
192194

193-
componentDidMount: function componentDidMount() {},
195+
componentDidMount: function componentDidMount() {
196+
this.autoplay();
197+
},
194198

199+
/**
200+
* Automatic rolling
201+
*/
195202
autoplay: function autoplay() {
196203
var _this = this;
197204

198205
if (!this.props.autoplay || this.state.isScrolling || this.state.autoplayEnd) {
199206
return;
200207
}clearTimeout(this.autoplayTimer);
208+
201209
this.autoplayTimer = this.setTimeout(function () {
202210
if (!_this.props.loop && (_this.props.autoplayDirection ? _this.state.index == _this.state.total - 1 : _this.state.index == 0)) return _this.setState({
203211
autoplayEnd: true
@@ -206,22 +214,39 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
206214
}, this.props.autoplayTimeout * 1000);
207215
},
208216

217+
/**
218+
* Scroll begin handle
219+
* @param {object} e native event
220+
*/
221+
onScrollBegin: function onScrollBegin(e) {
222+
// update scroll state
223+
this.setState({
224+
isScrolling: true
225+
});
226+
227+
this.props.onScrollBeginDrag && this.props.onScrollBeginDrag.call(this, e);
228+
},
229+
209230
/**
210231
* Scroll end handle
211232
* @param {object} e native event
212233
*/
213234
onScrollEnd: function onScrollEnd(e) {
235+
var _this2 = this;
214236

215237
// update scroll state
216238
this.setState({
217239
isScrolling: false
218240
});
219241

220-
var offset = e.nativeEvent.contentOffset;
221-
this.updateIndex(offset, this.state.dir);
242+
this.updateIndex(e.nativeEvent.contentOffset, this.state.dir);
243+
244+
this.setTimeout(function () {
245+
_this2.autoplay();
246+
});
222247

223248
// if `onMomentumScrollEnd` registered will be called here
224-
this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd.call(this);
249+
this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd.call(this, e);
225250
},
226251

227252
/**
@@ -230,17 +255,31 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
230255
* @param {string} dir 'x' || 'y'
231256
*/
232257
updateIndex: function updateIndex(offset, dir) {
233-
offset = offset[dir];
258+
234259
var state = this.state;
235260
var index = state.index;
236-
var diff = dir == 'x' ? state.width : state.height;
261+
var diff = offset[dir] - state.offset[dir];
262+
var step = dir == 'x' ? state.width : state.height;
263+
264+
// Do nothing if offset no change.
265+
if (!diff) {
266+
return;
267+
} // Note: if touch very very quickly and continuous,
268+
// the variation of `index` more than 1.
269+
index = index + diff / step;
237270
if (this.props.loop) {
238-
if (offset > diff) index++;else if (offset < diff) index--;
239-
if (index == -1) index = state.total - 1;else if (index == state.total) index = 0;
240-
} else index = Math.floor((offset - diff / 2) / diff) + 1;
271+
if (index <= -1) {
272+
index = state.total - 1;
273+
offset[dir] = step * state.total;
274+
} else if (index >= state.total) {
275+
index = 0;
276+
offset[dir] = step;
277+
}
278+
}
279+
241280
this.setState({
242-
index: index
243-
});
281+
index: index,
282+
offset: offset });
244283
},
245284

246285
/**
@@ -251,7 +290,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
251290
if (this.state.isScrolling) {
252291
return;
253292
}var state = this.state;
254-
var diff = (this.props.loop ? 1 : this.state.index) + index;
293+
var diff = (this.props.loop ? 1 : 0) + index + this.state.index;
255294
var x = 0;
256295
var y = 0;
257296
if (state.dir == 'x') x = diff * state.width;
@@ -312,7 +351,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
312351
},
313352

314353
renderButtons: function renderButtons() {
315-
var _this2 = this;
354+
var _this3 = this;
316355

317356
var nextButton = this.props.nextButton || _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['default'].createElement(
318357
_React$StyleSheet$Text$View$ScrollView$TouchableOpacity.Text,
@@ -332,7 +371,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
332371
_React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['default'].createElement(
333372
_React$StyleSheet$Text$View$ScrollView$TouchableOpacity.TouchableOpacity,
334373
{ onPress: function () {
335-
return !(!_this2.props.loop && _this2.state.index == 0) && _this2.scrollTo.call(_this2, -1);
374+
return !(!_this3.props.loop && _this3.state.index == 0) && _this3.scrollTo.call(_this3, -1);
336375
} },
337376
_React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['default'].createElement(
338377
_React$StyleSheet$Text$View$ScrollView$TouchableOpacity.View,
@@ -343,7 +382,7 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
343382
_React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['default'].createElement(
344383
_React$StyleSheet$Text$View$ScrollView$TouchableOpacity.TouchableOpacity,
345384
{ onPress: function () {
346-
return !(!_this2.props.loop && _this2.state.index == _this2.state.total - 1) && _this2.scrollTo.call(_this2, 1);
385+
return !(!_this3.props.loop && _this3.state.index == _this3.state.total - 1) && _this3.scrollTo.call(_this3, 1);
347386
} },
348387
_React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['default'].createElement(
349388
_React$StyleSheet$Text$View$ScrollView$TouchableOpacity.View,
@@ -366,38 +405,34 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
366405
var total = state.total;
367406
var loop = props.loop;
368407
var dir = state.dir;
369-
var initOffset = {};
370408
var key = 0;
371409

372410
var pages = [];
373411
var pageStyle = [{ width: state.width, height: state.height }, styles.slide];
374412

375413
// For make infinite at least total > 1
376414
if (total > 1) {
415+
416+
// Re-design a loop model for avoid img flickering
417+
pages = Object.keys(children);
377418
if (loop) {
378-
pages.push(index == 0 ? total - 1 : index - 1);
379-
pages.push(index);
380-
pages.push(index == total - 1 ? 0 : index + 1);
381-
key = index;
382-
} else pages = Object.keys(children);
419+
pages.unshift(total - 1);
420+
pages.push(0);
421+
}
422+
383423
pages = pages.map(function (page, i) {
384424
return _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['default'].createElement(
385425
_React$StyleSheet$Text$View$ScrollView$TouchableOpacity.View,
386426
{ style: pageStyle, key: i },
387427
children[page]
388428
);
389429
});
390-
391-
var setup = loop ? 1 : index;
392-
initOffset[dir] = dir == 'y' ? state.height * setup : state.width * setup;
393430
} else pages = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['default'].createElement(
394431
_React$StyleSheet$Text$View$ScrollView$TouchableOpacity.View,
395432
{ style: pageStyle },
396433
children
397434
);
398435

399-
this.autoplay();
400-
401436
return _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['default'].createElement(
402437
_React$StyleSheet$Text$View$ScrollView$TouchableOpacity.View,
403438
{ style: [styles.container, {
@@ -409,9 +444,9 @@ exports['default'] = _React$StyleSheet$Text$View$ScrollView$TouchableOpacity2['d
409444
_extends({ ref: 'scrollView'
410445
}, props, {
411446
contentContainerStyle: [styles.wrapper, props.style],
412-
contentOffset: initOffset,
413-
onMomentumScrollEnd: this.onScrollEnd,
414-
key: key }),
447+
contentOffset: state.offset,
448+
onScrollBeginDrag: this.onScrollBegin,
449+
onMomentumScrollEnd: this.onScrollEnd }),
415450
pages
416451
),
417452
props.showsPagination && (props.renderPagination ? this.props.renderPagination.call(this, state.index, state.total) : this.renderPagination()),

0 commit comments

Comments
 (0)