@momo-kits/carousel 0.0.71-beta → 0.0.71-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Carousel.js +242 -263
- package/CarouselV2.js +1363 -0
- package/index.js +3 -4
- package/package.json +15 -14
- package/pagination/NumberPagination.js +43 -0
- package/pagination/Pagination.js +64 -34
- package/pagination/PaginationDot.js +45 -39
- package/pagination/styles.js +6 -6
- package/publish.sh +1 -1
- package/utils/animationsV2.js +381 -0
package/Carousel.js
CHANGED
|
@@ -18,20 +18,10 @@ import {
|
|
|
18
18
|
} from './utils/animation';
|
|
19
19
|
|
|
20
20
|
const IS_IOS = Platform.OS === 'ios';
|
|
21
|
-
|
|
22
|
-
// Native driver for scroll events
|
|
23
|
-
// See: https://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated.html
|
|
24
|
-
const AnimatedFlatList = FlatList ? Animated.createAnimatedComponent(FlatList) : null;
|
|
25
|
-
const AnimatedScrollView = Animated.createAnimatedComponent(ScrollView);
|
|
26
|
-
|
|
27
|
-
// React Native automatically handles RTL layouts; unfortunately, it's buggy with horizontal ScrollView
|
|
28
|
-
// See https://github.com/facebook/react-native/issues/11960
|
|
29
|
-
// NOTE: the following variable is not declared in the constructor
|
|
30
|
-
// otherwise it is undefined at init, which messes with custom indexes
|
|
31
21
|
const IS_RTL = I18nManager.isRTL;
|
|
32
22
|
|
|
33
23
|
export default class Carousel extends PureComponent {
|
|
34
|
-
constructor(props) {
|
|
24
|
+
constructor (props) {
|
|
35
25
|
super(props);
|
|
36
26
|
|
|
37
27
|
this.state = {
|
|
@@ -78,36 +68,29 @@ export default class Carousel extends PureComponent {
|
|
|
78
68
|
// This bool aims at fixing an iOS bug due to scrollTo that triggers onMomentumScrollEnd.
|
|
79
69
|
// onMomentumScrollEnd fires this._snapScroll, thus creating an infinite loop.
|
|
80
70
|
this._ignoreNextMomentum = false;
|
|
81
|
-
this._animated = false;
|
|
82
71
|
|
|
83
72
|
// Warnings
|
|
84
73
|
if (!ViewPropTypes) {
|
|
85
|
-
console.warn(
|
|
86
|
-
It is recommended to use at least version 0.44 of React Native with the plugin`);
|
|
74
|
+
console.warn('react-native-snap-carousel: It is recommended to use at least version 0.44 of React Native with the plugin');
|
|
87
75
|
}
|
|
88
76
|
if (!props.vertical && (!props.sliderWidth || !props.itemWidth)) {
|
|
89
|
-
console.
|
|
90
|
-
for horizontal carousels`);
|
|
77
|
+
console.error('react-native-snap-carousel: You need to specify both `sliderWidth` and `itemWidth` for horizontal carousels');
|
|
91
78
|
}
|
|
92
79
|
if (props.vertical && (!props.sliderHeight || !props.itemHeight)) {
|
|
93
|
-
console.
|
|
94
|
-
for vertical carousels`);
|
|
80
|
+
console.error('react-native-snap-carousel: You need to specify both `sliderHeight` and `itemHeight` for vertical carousels');
|
|
95
81
|
}
|
|
96
82
|
if (props.apparitionDelay && !IS_IOS && !props.useScrollView) {
|
|
97
|
-
console.warn(
|
|
98
|
-
is not recommended since it can lead to rendering issues`);
|
|
83
|
+
console.warn('react-native-snap-carousel: Using `apparitionDelay` on Android is not recommended since it can lead to rendering issues');
|
|
99
84
|
}
|
|
100
85
|
if (props.customAnimationType || props.customAnimationOptions) {
|
|
101
|
-
console.warn(
|
|
102
|
-
customAnimationOptions have been renamed to activeAnimationType and activeAnimationOptions`);
|
|
86
|
+
console.warn('react-native-snap-carousel: Props `customAnimationType` and `customAnimationOptions` have been renamed to `activeAnimationType` and `activeAnimationOptions`');
|
|
103
87
|
}
|
|
104
88
|
if (props.onScrollViewScroll) {
|
|
105
|
-
console.
|
|
106
|
-
Use onScroll instead`);
|
|
89
|
+
console.error('react-native-snap-carousel: Prop `onScrollViewScroll` has been removed. Use `onScroll` instead');
|
|
107
90
|
}
|
|
108
91
|
}
|
|
109
92
|
|
|
110
|
-
componentDidMount() {
|
|
93
|
+
componentDidMount () {
|
|
111
94
|
const { apparitionDelay, autoplay, firstItem } = this.props;
|
|
112
95
|
const _firstItem = this._getFirstItem(firstItem);
|
|
113
96
|
const apparitionCallback = () => {
|
|
@@ -139,39 +122,31 @@ export default class Carousel extends PureComponent {
|
|
|
139
122
|
});
|
|
140
123
|
}
|
|
141
124
|
|
|
142
|
-
// shouldComponentUpdate(nextProps, nextState) {
|
|
143
|
-
//
|
|
144
|
-
// if (shouldOptimizeUpdates === false) {
|
|
145
|
-
// return true;
|
|
146
|
-
// }
|
|
147
|
-
// if (shallowCompare(this.props, nextProps)) {
|
|
125
|
+
// shouldComponentUpdate (nextProps, nextState) {
|
|
126
|
+
// if (this.props.shouldOptimizeUpdates === false) {
|
|
148
127
|
// return true;
|
|
128
|
+
// } else {
|
|
129
|
+
// return shallowCompare(this, nextProps, nextState);
|
|
149
130
|
// }
|
|
150
|
-
// if (shallowCompare(this.state, nextState)) {
|
|
151
|
-
// return true;
|
|
152
|
-
// }
|
|
153
|
-
// return false;
|
|
154
131
|
// }
|
|
155
132
|
|
|
156
|
-
|
|
133
|
+
componentDidUpdate (prevProps) {
|
|
157
134
|
const { interpolators } = this.state;
|
|
158
|
-
const {
|
|
159
|
-
|
|
160
|
-
} = this.props;
|
|
161
|
-
const itemsLength = this._getCustomDataLength(nextProps);
|
|
135
|
+
const { firstItem, itemHeight, itemWidth, scrollEnabled, sliderHeight, sliderWidth } = this.props;
|
|
136
|
+
const itemsLength = this._getCustomDataLength(this.props);
|
|
162
137
|
|
|
163
138
|
if (!itemsLength) {
|
|
164
139
|
return;
|
|
165
140
|
}
|
|
166
141
|
|
|
167
|
-
const nextFirstItem = this._getFirstItem(
|
|
142
|
+
const nextFirstItem = this._getFirstItem(firstItem, this.props);
|
|
168
143
|
let nextActiveItem = this._activeItem || this._activeItem === 0 ? this._activeItem : nextFirstItem;
|
|
169
144
|
|
|
170
|
-
const hasNewSliderWidth =
|
|
171
|
-
const hasNewSliderHeight =
|
|
172
|
-
const hasNewItemWidth =
|
|
173
|
-
const hasNewItemHeight =
|
|
174
|
-
const hasNewScrollEnabled =
|
|
145
|
+
const hasNewSliderWidth = sliderWidth && sliderWidth !== prevProps.sliderWidth;
|
|
146
|
+
const hasNewSliderHeight = sliderHeight && sliderHeight !== prevProps.sliderHeight;
|
|
147
|
+
const hasNewItemWidth = itemWidth && itemWidth !== prevProps.itemWidth;
|
|
148
|
+
const hasNewItemHeight = itemHeight && itemHeight !== prevProps.itemHeight;
|
|
149
|
+
const hasNewScrollEnabled = scrollEnabled !== prevProps.scrollEnabled;
|
|
175
150
|
|
|
176
151
|
// Prevent issues with dynamically removed items
|
|
177
152
|
if (nextActiveItem > itemsLength - 1) {
|
|
@@ -180,15 +155,15 @@ export default class Carousel extends PureComponent {
|
|
|
180
155
|
|
|
181
156
|
// Handle changing scrollEnabled independent of user -> carousel interaction
|
|
182
157
|
if (hasNewScrollEnabled) {
|
|
183
|
-
this._setScrollEnabled(
|
|
158
|
+
this._setScrollEnabled(scrollEnabled);
|
|
184
159
|
}
|
|
185
160
|
|
|
186
|
-
if (interpolators.length !== itemsLength || hasNewSliderWidth
|
|
187
|
-
|
|
161
|
+
if (interpolators.length !== itemsLength || hasNewSliderWidth ||
|
|
162
|
+
hasNewSliderHeight || hasNewItemWidth || hasNewItemHeight) {
|
|
188
163
|
this._activeItem = nextActiveItem;
|
|
189
164
|
this._previousItemsLength = itemsLength;
|
|
190
165
|
|
|
191
|
-
this._initPositionsAndInterpolators(
|
|
166
|
+
this._initPositionsAndInterpolators(this.props);
|
|
192
167
|
|
|
193
168
|
// Handle scroll issue when dynamically removing items (see #133)
|
|
194
169
|
// This also fixes first item's active state on Android
|
|
@@ -206,12 +181,12 @@ export default class Carousel extends PureComponent {
|
|
|
206
181
|
this._snapToItem(nextFirstItem, false, true, false, false);
|
|
207
182
|
}
|
|
208
183
|
|
|
209
|
-
if (
|
|
210
|
-
|
|
184
|
+
if (this.props.onScroll !== prevProps.onScroll) {
|
|
185
|
+
this._setScrollHandler(this.props);
|
|
211
186
|
}
|
|
212
187
|
}
|
|
213
188
|
|
|
214
|
-
componentWillUnmount() {
|
|
189
|
+
componentWillUnmount () {
|
|
215
190
|
this._mounted = false;
|
|
216
191
|
this.stopAutoplay();
|
|
217
192
|
clearTimeout(this._apparitionTimeout);
|
|
@@ -223,101 +198,98 @@ export default class Carousel extends PureComponent {
|
|
|
223
198
|
clearTimeout(this._lockScrollTimeout);
|
|
224
199
|
}
|
|
225
200
|
|
|
226
|
-
get realIndex() {
|
|
201
|
+
get realIndex () {
|
|
227
202
|
return this._activeItem;
|
|
228
203
|
}
|
|
229
204
|
|
|
230
|
-
get currentIndex() {
|
|
205
|
+
get currentIndex () {
|
|
231
206
|
return this._getDataIndex(this._activeItem);
|
|
232
207
|
}
|
|
233
208
|
|
|
234
|
-
get currentScrollPosition() {
|
|
209
|
+
get currentScrollPosition () {
|
|
235
210
|
return this._currentContentOffset;
|
|
236
211
|
}
|
|
237
212
|
|
|
238
213
|
_setScrollHandler(props) {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
214
|
+
// Native driver for scroll events
|
|
215
|
+
const scrollEventConfig = {
|
|
216
|
+
listener: this._onScroll,
|
|
217
|
+
useNativeDriver: true,
|
|
218
|
+
};
|
|
219
|
+
this._scrollPos = new Animated.Value(0);
|
|
220
|
+
const argMapping = props.vertical
|
|
221
|
+
? [{ nativeEvent: { contentOffset: { y: this._scrollPos } } }]
|
|
222
|
+
: [{ nativeEvent: { contentOffset: { x: this._scrollPos } } }];
|
|
223
|
+
|
|
224
|
+
if (props.onScroll && Array.isArray(props.onScroll._argMapping)) {
|
|
225
|
+
// Because of a react-native issue https://github.com/facebook/react-native/issues/13294
|
|
226
|
+
argMapping.pop();
|
|
227
|
+
const [ argMap ] = props.onScroll._argMapping;
|
|
228
|
+
if (argMap && argMap.nativeEvent && argMap.nativeEvent.contentOffset) {
|
|
229
|
+
// Shares the same animated value passed in props
|
|
230
|
+
this._scrollPos =
|
|
231
|
+
argMap.nativeEvent.contentOffset.x ||
|
|
232
|
+
argMap.nativeEvent.contentOffset.y ||
|
|
233
|
+
this._scrollPos;
|
|
234
|
+
}
|
|
235
|
+
argMapping.push(...props.onScroll._argMapping);
|
|
236
|
+
}
|
|
237
|
+
this._onScrollHandler = Animated.event(
|
|
238
|
+
argMapping,
|
|
239
|
+
scrollEventConfig
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
_needsScrollView () {
|
|
268
244
|
const { useScrollView } = this.props;
|
|
269
|
-
return useScrollView || !
|
|
245
|
+
return useScrollView || !Animated.FlatList || this._shouldUseStackLayout() || this._shouldUseTinderLayout();
|
|
270
246
|
}
|
|
271
247
|
|
|
272
|
-
_needsRTLAdaptations() {
|
|
248
|
+
_needsRTLAdaptations () {
|
|
273
249
|
const { vertical } = this.props;
|
|
274
250
|
return IS_RTL && !IS_IOS && !vertical;
|
|
275
251
|
}
|
|
276
252
|
|
|
277
|
-
_canLockScroll() {
|
|
253
|
+
_canLockScroll () {
|
|
278
254
|
const { scrollEnabled, enableMomentum, lockScrollWhileSnapping } = this.props;
|
|
279
255
|
return scrollEnabled && !enableMomentum && lockScrollWhileSnapping;
|
|
280
256
|
}
|
|
281
257
|
|
|
282
|
-
_enableLoop() {
|
|
258
|
+
_enableLoop () {
|
|
283
259
|
const { data, enableSnap, loop } = this.props;
|
|
284
260
|
return enableSnap && loop && data && data.length && data.length > 1;
|
|
285
261
|
}
|
|
286
262
|
|
|
287
|
-
_shouldAnimateSlides(props = this.props) {
|
|
288
|
-
const {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
||
|
|
293
|
-
||
|
|
294
|
-
||
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
_shouldUseCustomAnimation() {
|
|
263
|
+
_shouldAnimateSlides (props = this.props) {
|
|
264
|
+
const { inactiveSlideOpacity, inactiveSlideScale, scrollInterpolator, slideInterpolatedStyle } = props;
|
|
265
|
+
return inactiveSlideOpacity < 1 ||
|
|
266
|
+
inactiveSlideScale < 1 ||
|
|
267
|
+
!!scrollInterpolator ||
|
|
268
|
+
!!slideInterpolatedStyle ||
|
|
269
|
+
this._shouldUseShiftLayout() ||
|
|
270
|
+
this._shouldUseStackLayout() ||
|
|
271
|
+
this._shouldUseTinderLayout();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
_shouldUseCustomAnimation () {
|
|
301
275
|
const { activeAnimationOptions } = this.props;
|
|
302
276
|
return !!activeAnimationOptions && !this._shouldUseStackLayout() && !this._shouldUseTinderLayout();
|
|
303
277
|
}
|
|
304
278
|
|
|
305
|
-
_shouldUseShiftLayout() {
|
|
279
|
+
_shouldUseShiftLayout () {
|
|
306
280
|
const { inactiveSlideShift, layout } = this.props;
|
|
307
281
|
return layout === 'default' && inactiveSlideShift !== 0;
|
|
308
282
|
}
|
|
309
283
|
|
|
310
|
-
_shouldUseStackLayout() {
|
|
311
|
-
|
|
312
|
-
return layout === 'stack';
|
|
284
|
+
_shouldUseStackLayout () {
|
|
285
|
+
return this.props.layout === 'stack';
|
|
313
286
|
}
|
|
314
287
|
|
|
315
|
-
_shouldUseTinderLayout() {
|
|
316
|
-
|
|
317
|
-
return layout === 'tinder';
|
|
288
|
+
_shouldUseTinderLayout () {
|
|
289
|
+
return this.props.layout === 'tinder';
|
|
318
290
|
}
|
|
319
291
|
|
|
320
|
-
_getCustomData(props = this.props) {
|
|
292
|
+
_getCustomData (props = this.props) {
|
|
321
293
|
const { data, loopClonesPerSide } = props;
|
|
322
294
|
const dataLength = data && data.length;
|
|
323
295
|
|
|
@@ -336,7 +308,7 @@ export default class Carousel extends PureComponent {
|
|
|
336
308
|
const dataMultiplier = Math.floor(loopClonesPerSide / dataLength);
|
|
337
309
|
const remainder = loopClonesPerSide % dataLength;
|
|
338
310
|
|
|
339
|
-
for (let i = 0; i < dataMultiplier; i
|
|
311
|
+
for (let i = 0; i < dataMultiplier; i++) {
|
|
340
312
|
previousItems.push(...data);
|
|
341
313
|
nextItems.push(...data);
|
|
342
314
|
}
|
|
@@ -347,10 +319,11 @@ export default class Carousel extends PureComponent {
|
|
|
347
319
|
previousItems = data.slice(-loopClonesPerSide);
|
|
348
320
|
nextItems = data.slice(0, loopClonesPerSide);
|
|
349
321
|
}
|
|
322
|
+
|
|
350
323
|
return previousItems.concat(data, nextItems);
|
|
351
324
|
}
|
|
352
325
|
|
|
353
|
-
_getCustomDataLength(props = this.props) {
|
|
326
|
+
_getCustomDataLength (props = this.props) {
|
|
354
327
|
const { data, loopClonesPerSide } = props;
|
|
355
328
|
const dataLength = data && data.length;
|
|
356
329
|
|
|
@@ -361,7 +334,7 @@ export default class Carousel extends PureComponent {
|
|
|
361
334
|
return this._enableLoop() ? dataLength + (2 * loopClonesPerSide) : dataLength;
|
|
362
335
|
}
|
|
363
336
|
|
|
364
|
-
_getCustomIndex(index, props = this.props) {
|
|
337
|
+
_getCustomIndex (index, props = this.props) {
|
|
365
338
|
const itemsLength = this._getCustomDataLength(props);
|
|
366
339
|
|
|
367
340
|
if (!itemsLength || (!index && index !== 0)) {
|
|
@@ -371,7 +344,7 @@ export default class Carousel extends PureComponent {
|
|
|
371
344
|
return this._needsRTLAdaptations() ? itemsLength - index - 1 : index;
|
|
372
345
|
}
|
|
373
346
|
|
|
374
|
-
_getDataIndex(index) {
|
|
347
|
+
_getDataIndex (index) {
|
|
375
348
|
const { data, loopClonesPerSide } = this.props;
|
|
376
349
|
const dataLength = data && data.length;
|
|
377
350
|
|
|
@@ -380,10 +353,10 @@ export default class Carousel extends PureComponent {
|
|
|
380
353
|
}
|
|
381
354
|
|
|
382
355
|
if (index >= dataLength + loopClonesPerSide) {
|
|
383
|
-
return loopClonesPerSide > dataLength
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
} if (index < loopClonesPerSide) {
|
|
356
|
+
return loopClonesPerSide > dataLength ?
|
|
357
|
+
(index - loopClonesPerSide) % dataLength :
|
|
358
|
+
index - dataLength - loopClonesPerSide;
|
|
359
|
+
} else if (index < loopClonesPerSide) {
|
|
387
360
|
// TODO: is there a simpler way of determining the interpolated index?
|
|
388
361
|
if (loopClonesPerSide > dataLength) {
|
|
389
362
|
const baseDataIndexes = [];
|
|
@@ -391,29 +364,31 @@ export default class Carousel extends PureComponent {
|
|
|
391
364
|
const dataMultiplier = Math.floor(loopClonesPerSide / dataLength);
|
|
392
365
|
const remainder = loopClonesPerSide % dataLength;
|
|
393
366
|
|
|
394
|
-
for (let i = 0; i < dataLength; i
|
|
367
|
+
for (let i = 0; i < dataLength; i++) {
|
|
395
368
|
baseDataIndexes.push(i);
|
|
396
369
|
}
|
|
397
370
|
|
|
398
|
-
for (let j = 0; j < dataMultiplier; j
|
|
371
|
+
for (let j = 0; j < dataMultiplier; j++) {
|
|
399
372
|
dataIndexes.push(...baseDataIndexes);
|
|
400
373
|
}
|
|
401
374
|
|
|
402
375
|
dataIndexes.unshift(...baseDataIndexes.slice(-remainder));
|
|
403
376
|
return dataIndexes[index];
|
|
377
|
+
} else {
|
|
378
|
+
return index + dataLength - loopClonesPerSide;
|
|
404
379
|
}
|
|
405
|
-
|
|
380
|
+
} else {
|
|
381
|
+
return index - loopClonesPerSide;
|
|
406
382
|
}
|
|
407
|
-
return index - loopClonesPerSide;
|
|
408
383
|
}
|
|
409
384
|
|
|
410
385
|
// Used with `snapToItem()` and 'PaginationDot'
|
|
411
|
-
_getPositionIndex(index) {
|
|
386
|
+
_getPositionIndex (index) {
|
|
412
387
|
const { loop, loopClonesPerSide } = this.props;
|
|
413
388
|
return loop ? index + loopClonesPerSide : index;
|
|
414
389
|
}
|
|
415
390
|
|
|
416
|
-
_getFirstItem(index, props = this.props) {
|
|
391
|
+
_getFirstItem (index, props = this.props) {
|
|
417
392
|
const { loopClonesPerSide } = props;
|
|
418
393
|
const itemsLength = this._getCustomDataLength(props);
|
|
419
394
|
|
|
@@ -424,10 +399,10 @@ export default class Carousel extends PureComponent {
|
|
|
424
399
|
return this._enableLoop() ? index + loopClonesPerSide : index;
|
|
425
400
|
}
|
|
426
401
|
|
|
427
|
-
_getWrappedRef() {
|
|
402
|
+
_getWrappedRef () {
|
|
428
403
|
if (this._carouselRef && (
|
|
429
|
-
(this._needsScrollView() && this._carouselRef.scrollTo)
|
|
430
|
-
|
|
404
|
+
(this._needsScrollView() && this._carouselRef.scrollTo) ||
|
|
405
|
+
(!this._needsScrollView() && this._carouselRef.scrollToOffset)
|
|
431
406
|
)) {
|
|
432
407
|
return this._carouselRef;
|
|
433
408
|
}
|
|
@@ -436,11 +411,11 @@ export default class Carousel extends PureComponent {
|
|
|
436
411
|
return this._carouselRef && this._carouselRef.getNode && this._carouselRef.getNode();
|
|
437
412
|
}
|
|
438
413
|
|
|
439
|
-
_getScrollEnabled() {
|
|
414
|
+
_getScrollEnabled () {
|
|
440
415
|
return this._scrollEnabled;
|
|
441
416
|
}
|
|
442
417
|
|
|
443
|
-
_setScrollEnabled(scrollEnabled = true) {
|
|
418
|
+
_setScrollEnabled (scrollEnabled = true) {
|
|
444
419
|
const wrappedRef = this._getWrappedRef();
|
|
445
420
|
|
|
446
421
|
if (!wrappedRef || !wrappedRef.setNativeProps) {
|
|
@@ -453,56 +428,54 @@ export default class Carousel extends PureComponent {
|
|
|
453
428
|
this._scrollEnabled = scrollEnabled;
|
|
454
429
|
}
|
|
455
430
|
|
|
456
|
-
_getKeyExtractor(item, index) {
|
|
431
|
+
_getKeyExtractor (item, index) {
|
|
457
432
|
return this._needsScrollView() ? `scrollview-item-${index}` : `flatlist-item-${index}`;
|
|
458
433
|
}
|
|
459
434
|
|
|
460
|
-
_getScrollOffset(event) {
|
|
435
|
+
_getScrollOffset (event) {
|
|
461
436
|
const { vertical } = this.props;
|
|
462
|
-
return (event && event.nativeEvent && event.nativeEvent.contentOffset
|
|
463
|
-
|
|
437
|
+
return (event && event.nativeEvent && event.nativeEvent.contentOffset &&
|
|
438
|
+
event.nativeEvent.contentOffset[vertical ? 'y' : 'x']) || 0;
|
|
464
439
|
}
|
|
465
440
|
|
|
466
|
-
_getContainerInnerMargin(opposite = false) {
|
|
467
|
-
const {
|
|
468
|
-
sliderWidth, sliderHeight, itemWidth, itemHeight, vertical, activeSlideAlignment
|
|
469
|
-
} = this.props;
|
|
441
|
+
_getContainerInnerMargin (opposite = false) {
|
|
442
|
+
const { sliderWidth, sliderHeight, itemWidth, itemHeight, vertical, activeSlideAlignment } = this.props;
|
|
470
443
|
|
|
471
|
-
if ((activeSlideAlignment === 'start' && !opposite)
|
|
472
|
-
|
|
444
|
+
if ((activeSlideAlignment === 'start' && !opposite) ||
|
|
445
|
+
(activeSlideAlignment === 'end' && opposite)) {
|
|
473
446
|
return 0;
|
|
474
|
-
} if ((activeSlideAlignment === 'end' && !opposite)
|
|
475
|
-
|
|
447
|
+
} else if ((activeSlideAlignment === 'end' && !opposite) ||
|
|
448
|
+
(activeSlideAlignment === 'start' && opposite)) {
|
|
476
449
|
return vertical ? sliderHeight - itemHeight : sliderWidth - itemWidth;
|
|
450
|
+
} else {
|
|
451
|
+
return vertical ? (sliderHeight - itemHeight) / 2 : (sliderWidth - itemWidth) / 2;
|
|
477
452
|
}
|
|
478
|
-
return vertical ? (sliderHeight - itemHeight) / 2 : (sliderWidth - itemWidth) / 2;
|
|
479
453
|
}
|
|
480
454
|
|
|
481
|
-
_getViewportOffset() {
|
|
482
|
-
const {
|
|
483
|
-
sliderWidth, sliderHeight, itemWidth, itemHeight, vertical, activeSlideAlignment
|
|
484
|
-
} = this.props;
|
|
455
|
+
_getViewportOffset () {
|
|
456
|
+
const { sliderWidth, sliderHeight, itemWidth, itemHeight, vertical, activeSlideAlignment } = this.props;
|
|
485
457
|
|
|
486
458
|
if (activeSlideAlignment === 'start') {
|
|
487
459
|
return vertical ? itemHeight / 2 : itemWidth / 2;
|
|
488
|
-
} if (activeSlideAlignment === 'end') {
|
|
489
|
-
return vertical
|
|
490
|
-
|
|
491
|
-
|
|
460
|
+
} else if (activeSlideAlignment === 'end') {
|
|
461
|
+
return vertical ?
|
|
462
|
+
sliderHeight - (itemHeight / 2) :
|
|
463
|
+
sliderWidth - (itemWidth / 2);
|
|
464
|
+
} else {
|
|
465
|
+
return vertical ? sliderHeight / 2 : sliderWidth / 2;
|
|
492
466
|
}
|
|
493
|
-
return vertical ? sliderHeight / 2 : sliderWidth / 2;
|
|
494
467
|
}
|
|
495
468
|
|
|
496
|
-
_getCenter(offset) {
|
|
469
|
+
_getCenter (offset) {
|
|
497
470
|
return offset + this._getViewportOffset() - this._getContainerInnerMargin();
|
|
498
471
|
}
|
|
499
472
|
|
|
500
|
-
_getActiveItem(offset) {
|
|
473
|
+
_getActiveItem (offset) {
|
|
501
474
|
const { activeSlideOffset, swipeThreshold } = this.props;
|
|
502
475
|
const center = this._getCenter(offset);
|
|
503
476
|
const centerOffset = activeSlideOffset || swipeThreshold;
|
|
504
477
|
|
|
505
|
-
for (let i = 0; i < this._positions.length; i
|
|
478
|
+
for (let i = 0; i < this._positions.length; i++) {
|
|
506
479
|
const { start, end } = this._positions[i];
|
|
507
480
|
if (center + centerOffset >= start && center - centerOffset <= end) {
|
|
508
481
|
return i;
|
|
@@ -517,17 +490,15 @@ export default class Carousel extends PureComponent {
|
|
|
517
490
|
return 0;
|
|
518
491
|
}
|
|
519
492
|
|
|
520
|
-
_initPositionsAndInterpolators(props = this.props) {
|
|
521
|
-
const {
|
|
522
|
-
data, itemWidth, itemHeight, scrollInterpolator, vertical
|
|
523
|
-
} = props;
|
|
493
|
+
_initPositionsAndInterpolators (props = this.props) {
|
|
494
|
+
const { data, itemWidth, itemHeight, scrollInterpolator, vertical } = props;
|
|
524
495
|
const sizeRef = vertical ? itemHeight : itemWidth;
|
|
525
496
|
|
|
526
497
|
if (!data || !data.length) {
|
|
527
498
|
return;
|
|
528
499
|
}
|
|
529
500
|
|
|
530
|
-
|
|
501
|
+
let interpolators = [];
|
|
531
502
|
this._positions = [];
|
|
532
503
|
|
|
533
504
|
this._getCustomData(props).forEach((itemData, index) => {
|
|
@@ -554,7 +525,7 @@ export default class Carousel extends PureComponent {
|
|
|
554
525
|
interpolator = tinderScrollInterpolator(_index, props);
|
|
555
526
|
}
|
|
556
527
|
|
|
557
|
-
if (!interpolator || !interpolator
|
|
528
|
+
if (!interpolator || !interpolator.inputRange || !interpolator.outputRange) {
|
|
558
529
|
interpolator = defaultScrollInterpolator(_index, props);
|
|
559
530
|
}
|
|
560
531
|
|
|
@@ -566,10 +537,11 @@ export default class Carousel extends PureComponent {
|
|
|
566
537
|
|
|
567
538
|
interpolators.push(animatedValue);
|
|
568
539
|
});
|
|
540
|
+
|
|
569
541
|
this.setState({ interpolators });
|
|
570
542
|
}
|
|
571
543
|
|
|
572
|
-
_getSlideAnimation(index, toValue) {
|
|
544
|
+
_getSlideAnimation (index, toValue) {
|
|
573
545
|
const { interpolators } = this.state;
|
|
574
546
|
const { activeAnimationType, activeAnimationOptions } = this.props;
|
|
575
547
|
|
|
@@ -583,11 +555,11 @@ export default class Carousel extends PureComponent {
|
|
|
583
555
|
isInteraction: false,
|
|
584
556
|
useNativeDriver: true,
|
|
585
557
|
...activeAnimationOptions,
|
|
586
|
-
toValue
|
|
558
|
+
toValue: toValue
|
|
587
559
|
};
|
|
588
560
|
|
|
589
561
|
return Animated.parallel([
|
|
590
|
-
Animated
|
|
562
|
+
Animated['timing'](
|
|
591
563
|
animatedValue,
|
|
592
564
|
{ ...animationCommonOptions, easing: Easing.linear }
|
|
593
565
|
),
|
|
@@ -598,18 +570,18 @@ export default class Carousel extends PureComponent {
|
|
|
598
570
|
]);
|
|
599
571
|
}
|
|
600
572
|
|
|
601
|
-
_playCustomSlideAnimation(current, next) {
|
|
573
|
+
_playCustomSlideAnimation (current, next) {
|
|
602
574
|
const { interpolators } = this.state;
|
|
603
575
|
const itemsLength = this._getCustomDataLength();
|
|
604
576
|
const _currentIndex = this._getCustomIndex(current);
|
|
605
577
|
const _currentDataIndex = this._getDataIndex(_currentIndex);
|
|
606
578
|
const _nextIndex = this._getCustomIndex(next);
|
|
607
579
|
const _nextDataIndex = this._getDataIndex(_nextIndex);
|
|
608
|
-
|
|
580
|
+
let animations = [];
|
|
609
581
|
|
|
610
582
|
// Keep animations in sync when looping
|
|
611
583
|
if (this._enableLoop()) {
|
|
612
|
-
for (let i = 0; i < itemsLength; i
|
|
584
|
+
for (let i = 0; i < itemsLength; i++) {
|
|
613
585
|
if (this._getDataIndex(i) === _currentDataIndex && interpolators[i]) {
|
|
614
586
|
animations.push(this._getSlideAnimation(i, 0));
|
|
615
587
|
} else if (this._getDataIndex(i) === _nextDataIndex && interpolators[i]) {
|
|
@@ -628,7 +600,7 @@ export default class Carousel extends PureComponent {
|
|
|
628
600
|
Animated.parallel(animations, { stopTogether: false }).start();
|
|
629
601
|
}
|
|
630
602
|
|
|
631
|
-
_hackActiveSlideAnimation(index, goTo, force = false) {
|
|
603
|
+
_hackActiveSlideAnimation (index, goTo, force = false) {
|
|
632
604
|
const { data } = this.props;
|
|
633
605
|
|
|
634
606
|
if (!this._mounted || !this._carouselRef || !this._positions[index] || (!force && this._enableLoop())) {
|
|
@@ -652,7 +624,7 @@ export default class Carousel extends PureComponent {
|
|
|
652
624
|
}, 50); // works randomly when set to '0'
|
|
653
625
|
}
|
|
654
626
|
|
|
655
|
-
_lockScroll() {
|
|
627
|
+
_lockScroll () {
|
|
656
628
|
const { lockScrollTimeoutDuration } = this.props;
|
|
657
629
|
clearTimeout(this._lockScrollTimeout);
|
|
658
630
|
this._lockScrollTimeout = setTimeout(() => {
|
|
@@ -661,17 +633,17 @@ export default class Carousel extends PureComponent {
|
|
|
661
633
|
this._setScrollEnabled(false);
|
|
662
634
|
}
|
|
663
635
|
|
|
664
|
-
_releaseScroll() {
|
|
636
|
+
_releaseScroll () {
|
|
665
637
|
clearTimeout(this._lockScrollTimeout);
|
|
666
638
|
this._setScrollEnabled(true);
|
|
667
639
|
}
|
|
668
640
|
|
|
669
|
-
_repositionScroll(index) {
|
|
641
|
+
_repositionScroll (index) {
|
|
670
642
|
const { data, loopClonesPerSide } = this.props;
|
|
671
643
|
const dataLength = data && data.length;
|
|
672
644
|
|
|
673
|
-
if (!this._enableLoop() || !dataLength
|
|
674
|
-
|
|
645
|
+
if (!this._enableLoop() || !dataLength ||
|
|
646
|
+
(index >= loopClonesPerSide && index < dataLength + loopClonesPerSide)) {
|
|
675
647
|
return;
|
|
676
648
|
}
|
|
677
649
|
|
|
@@ -682,10 +654,11 @@ export default class Carousel extends PureComponent {
|
|
|
682
654
|
} else if (index < loopClonesPerSide) {
|
|
683
655
|
repositionTo = index + dataLength;
|
|
684
656
|
}
|
|
657
|
+
|
|
685
658
|
this._snapToItem(repositionTo, false, false, false, false);
|
|
686
659
|
}
|
|
687
660
|
|
|
688
|
-
_scrollTo(offset, animated = true) {
|
|
661
|
+
_scrollTo (offset, animated = true) {
|
|
689
662
|
const { vertical } = this.props;
|
|
690
663
|
const wrappedRef = this._getWrappedRef();
|
|
691
664
|
|
|
@@ -704,25 +677,22 @@ export default class Carousel extends PureComponent {
|
|
|
704
677
|
animated
|
|
705
678
|
};
|
|
706
679
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
}
|
|
713
|
-
}, (!animated && this._animated) ? 200 : 0);
|
|
714
|
-
|
|
715
|
-
this._animated = animated;
|
|
680
|
+
if (this._needsScrollView()) {
|
|
681
|
+
wrappedRef.scrollTo(options);
|
|
682
|
+
} else {
|
|
683
|
+
wrappedRef.scrollToOffset(options);
|
|
684
|
+
}
|
|
716
685
|
}
|
|
717
686
|
|
|
718
|
-
_onScroll(event) {
|
|
687
|
+
_onScroll (event) {
|
|
719
688
|
const { callbackOffsetMargin, enableMomentum, onScroll } = this.props;
|
|
720
689
|
|
|
721
690
|
const scrollOffset = event ? this._getScrollOffset(event) : this._currentContentOffset;
|
|
722
691
|
const nextActiveItem = this._getActiveItem(scrollOffset);
|
|
723
692
|
const itemReached = nextActiveItem === this._itemToSnapTo;
|
|
724
|
-
const scrollConditions =
|
|
725
|
-
|
|
693
|
+
const scrollConditions =
|
|
694
|
+
scrollOffset >= this._scrollOffsetRef - callbackOffsetMargin &&
|
|
695
|
+
scrollOffset <= this._scrollOffsetRef + callbackOffsetMargin;
|
|
726
696
|
|
|
727
697
|
this._currentContentOffset = scrollOffset;
|
|
728
698
|
this._onScrollTriggered = true;
|
|
@@ -765,17 +735,18 @@ export default class Carousel extends PureComponent {
|
|
|
765
735
|
}
|
|
766
736
|
}
|
|
767
737
|
}
|
|
768
|
-
|
|
769
|
-
|
|
738
|
+
|
|
739
|
+
if (nextActiveItem === this._itemToSnapTo &&
|
|
740
|
+
scrollOffset === this._scrollOffsetRef) {
|
|
770
741
|
this._repositionScroll(nextActiveItem);
|
|
771
742
|
}
|
|
772
743
|
|
|
773
|
-
if (typeof onScroll ===
|
|
744
|
+
if (typeof onScroll === "function" && event) {
|
|
774
745
|
onScroll(event);
|
|
775
746
|
}
|
|
776
747
|
}
|
|
777
748
|
|
|
778
|
-
_onStartShouldSetResponderCapture(event) {
|
|
749
|
+
_onStartShouldSetResponderCapture (event) {
|
|
779
750
|
const { onStartShouldSetResponderCapture } = this.props;
|
|
780
751
|
|
|
781
752
|
if (onStartShouldSetResponderCapture) {
|
|
@@ -785,34 +756,34 @@ export default class Carousel extends PureComponent {
|
|
|
785
756
|
return this._getScrollEnabled();
|
|
786
757
|
}
|
|
787
758
|
|
|
788
|
-
_onTouchStart() {
|
|
789
|
-
const { onTouchStart } = this.props
|
|
759
|
+
_onTouchStart () {
|
|
760
|
+
const { onTouchStart } = this.props
|
|
790
761
|
|
|
791
762
|
// `onTouchStart` is fired even when `scrollEnabled` is set to `false`
|
|
792
763
|
if (this._getScrollEnabled() !== false && this._autoplaying) {
|
|
793
|
-
this.
|
|
764
|
+
this.pauseAutoPlay();
|
|
794
765
|
}
|
|
795
766
|
|
|
796
767
|
if (onTouchStart) {
|
|
797
|
-
onTouchStart()
|
|
768
|
+
onTouchStart()
|
|
798
769
|
}
|
|
799
770
|
}
|
|
800
771
|
|
|
801
|
-
_onTouchEnd() {
|
|
802
|
-
const { onTouchEnd
|
|
772
|
+
_onTouchEnd () {
|
|
773
|
+
const { onTouchEnd } = this.props
|
|
803
774
|
|
|
804
|
-
if (this._getScrollEnabled() !== false &&
|
|
775
|
+
if (this._getScrollEnabled() !== false && this._autoplay && !this._autoplaying) {
|
|
805
776
|
// This event is buggy on Android, so a fallback is provided in _onScrollEnd()
|
|
806
777
|
this.startAutoplay();
|
|
807
778
|
}
|
|
808
779
|
|
|
809
780
|
if (onTouchEnd) {
|
|
810
|
-
onTouchEnd()
|
|
781
|
+
onTouchEnd()
|
|
811
782
|
}
|
|
812
783
|
}
|
|
813
784
|
|
|
814
785
|
// Used when `enableSnap` is ENABLED
|
|
815
|
-
_onScrollBeginDrag(event) {
|
|
786
|
+
_onScrollBeginDrag (event) {
|
|
816
787
|
const { onScrollBeginDrag } = this.props;
|
|
817
788
|
|
|
818
789
|
if (!this._getScrollEnabled()) {
|
|
@@ -830,11 +801,11 @@ export default class Carousel extends PureComponent {
|
|
|
830
801
|
}
|
|
831
802
|
|
|
832
803
|
// Used when `enableMomentum` is DISABLED
|
|
833
|
-
_onScrollEndDrag(event) {
|
|
804
|
+
_onScrollEndDrag (event) {
|
|
834
805
|
const { onScrollEndDrag } = this.props;
|
|
835
806
|
|
|
836
807
|
if (this._carouselRef) {
|
|
837
|
-
|
|
808
|
+
this._onScrollEnd && this._onScrollEnd();
|
|
838
809
|
}
|
|
839
810
|
|
|
840
811
|
if (onScrollEndDrag) {
|
|
@@ -843,11 +814,11 @@ export default class Carousel extends PureComponent {
|
|
|
843
814
|
}
|
|
844
815
|
|
|
845
816
|
// Used when `enableMomentum` is ENABLED
|
|
846
|
-
_onMomentumScrollEnd(event) {
|
|
817
|
+
_onMomentumScrollEnd (event) {
|
|
847
818
|
const { onMomentumScrollEnd } = this.props;
|
|
848
819
|
|
|
849
820
|
if (this._carouselRef) {
|
|
850
|
-
|
|
821
|
+
this._onScrollEnd && this._onScrollEnd();
|
|
851
822
|
}
|
|
852
823
|
|
|
853
824
|
if (onMomentumScrollEnd) {
|
|
@@ -855,8 +826,8 @@ export default class Carousel extends PureComponent {
|
|
|
855
826
|
}
|
|
856
827
|
}
|
|
857
828
|
|
|
858
|
-
_onScrollEnd() {
|
|
859
|
-
const {
|
|
829
|
+
_onScrollEnd (event) {
|
|
830
|
+
const { autoplayDelay, enableSnap } = this.props;
|
|
860
831
|
|
|
861
832
|
if (this._ignoreNextMomentum) {
|
|
862
833
|
// iOS fix
|
|
@@ -864,6 +835,10 @@ export default class Carousel extends PureComponent {
|
|
|
864
835
|
return;
|
|
865
836
|
}
|
|
866
837
|
|
|
838
|
+
if (this._currentContentOffset === this._scrollEndOffset) {
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
|
|
867
842
|
this._scrollEndOffset = this._currentContentOffset;
|
|
868
843
|
this._scrollEndActive = this._getActiveItem(this._scrollEndOffset);
|
|
869
844
|
|
|
@@ -873,7 +848,7 @@ export default class Carousel extends PureComponent {
|
|
|
873
848
|
|
|
874
849
|
// The touchEnd event is buggy on Android, so this will serve as a fallback whenever needed
|
|
875
850
|
// https://github.com/facebook/react-native/issues/9439
|
|
876
|
-
if (
|
|
851
|
+
if (this._autoplay && !this._autoplaying) {
|
|
877
852
|
clearTimeout(this._enableAutoplayTimeout);
|
|
878
853
|
this._enableAutoplayTimeout = setTimeout(() => {
|
|
879
854
|
this.startAutoplay();
|
|
@@ -884,7 +859,7 @@ export default class Carousel extends PureComponent {
|
|
|
884
859
|
// Due to a bug, this event is only fired on iOS
|
|
885
860
|
// https://github.com/facebook/react-native/issues/6791
|
|
886
861
|
// it's fine since we're only fixing an iOS bug in it, so ...
|
|
887
|
-
_onTouchRelease() {
|
|
862
|
+
_onTouchRelease (event) {
|
|
888
863
|
const { enableMomentum } = this.props;
|
|
889
864
|
|
|
890
865
|
if (enableMomentum && IS_IOS) {
|
|
@@ -895,7 +870,7 @@ export default class Carousel extends PureComponent {
|
|
|
895
870
|
}
|
|
896
871
|
}
|
|
897
872
|
|
|
898
|
-
_onLayout(event) {
|
|
873
|
+
_onLayout (event) {
|
|
899
874
|
const { onLayout } = this.props;
|
|
900
875
|
|
|
901
876
|
// Prevent unneeded actions during the first 'onLayout' (triggered on init)
|
|
@@ -911,7 +886,7 @@ export default class Carousel extends PureComponent {
|
|
|
911
886
|
}
|
|
912
887
|
}
|
|
913
888
|
|
|
914
|
-
_snapScroll(delta) {
|
|
889
|
+
_snapScroll (delta) {
|
|
915
890
|
const { swipeThreshold } = this.props;
|
|
916
891
|
|
|
917
892
|
// When using momentum and releasing the touch with
|
|
@@ -944,7 +919,7 @@ export default class Carousel extends PureComponent {
|
|
|
944
919
|
}
|
|
945
920
|
}
|
|
946
921
|
|
|
947
|
-
_snapToItem(index, animated = true, fireCallback = true, initial = false, lockScroll = true) {
|
|
922
|
+
_snapToItem (index, animated = true, fireCallback = true, initial = false, lockScroll = true) {
|
|
948
923
|
const { enableMomentum, onSnapToItem, onBeforeSnapToItem } = this.props;
|
|
949
924
|
const itemsLength = this._getCustomDataLength();
|
|
950
925
|
const wrappedRef = this._getWrappedRef();
|
|
@@ -988,9 +963,11 @@ export default class Carousel extends PureComponent {
|
|
|
988
963
|
|
|
989
964
|
this._scrollTo(this._scrollOffsetRef, animated);
|
|
990
965
|
|
|
966
|
+
this._scrollEndOffset = this._currentContentOffset;
|
|
967
|
+
|
|
991
968
|
if (enableMomentum) {
|
|
992
969
|
// iOS fix, check the note in the constructor
|
|
993
|
-
if (
|
|
970
|
+
if (!initial) {
|
|
994
971
|
this._ignoreNextMomentum = true;
|
|
995
972
|
}
|
|
996
973
|
|
|
@@ -1011,7 +988,7 @@ export default class Carousel extends PureComponent {
|
|
|
1011
988
|
}
|
|
1012
989
|
}
|
|
1013
990
|
|
|
1014
|
-
_onBeforeSnap(index) {
|
|
991
|
+
_onBeforeSnap (index) {
|
|
1015
992
|
const { onBeforeSnapToItem } = this.props;
|
|
1016
993
|
|
|
1017
994
|
if (!this._carouselRef) {
|
|
@@ -1019,10 +996,10 @@ export default class Carousel extends PureComponent {
|
|
|
1019
996
|
}
|
|
1020
997
|
|
|
1021
998
|
this._canFireBeforeCallback = false;
|
|
1022
|
-
|
|
999
|
+
onBeforeSnapToItem && onBeforeSnapToItem(index);
|
|
1023
1000
|
}
|
|
1024
1001
|
|
|
1025
|
-
_onSnap(index) {
|
|
1002
|
+
_onSnap (index) {
|
|
1026
1003
|
const { onSnapToItem } = this.props;
|
|
1027
1004
|
|
|
1028
1005
|
if (!this._carouselRef) {
|
|
@@ -1030,11 +1007,12 @@ export default class Carousel extends PureComponent {
|
|
|
1030
1007
|
}
|
|
1031
1008
|
|
|
1032
1009
|
this._canFireCallback = false;
|
|
1033
|
-
|
|
1010
|
+
onSnapToItem && onSnapToItem(index);
|
|
1034
1011
|
}
|
|
1035
1012
|
|
|
1036
|
-
startAutoplay() {
|
|
1013
|
+
startAutoplay () {
|
|
1037
1014
|
const { autoplayInterval, autoplayDelay } = this.props;
|
|
1015
|
+
this._autoplay = true;
|
|
1038
1016
|
|
|
1039
1017
|
if (this._autoplaying) {
|
|
1040
1018
|
return;
|
|
@@ -1051,12 +1029,19 @@ export default class Carousel extends PureComponent {
|
|
|
1051
1029
|
}, autoplayDelay);
|
|
1052
1030
|
}
|
|
1053
1031
|
|
|
1054
|
-
|
|
1032
|
+
pauseAutoPlay () {
|
|
1055
1033
|
this._autoplaying = false;
|
|
1034
|
+
clearTimeout(this._autoplayTimeout);
|
|
1035
|
+
clearTimeout(this._enableAutoplayTimeout);
|
|
1056
1036
|
clearInterval(this._autoplayInterval);
|
|
1057
1037
|
}
|
|
1058
1038
|
|
|
1059
|
-
|
|
1039
|
+
stopAutoplay () {
|
|
1040
|
+
this._autoplay = false;
|
|
1041
|
+
this.pauseAutoPlay();
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
snapToItem (index, animated = true, fireCallback = true) {
|
|
1060
1045
|
if (!index || index < 0) {
|
|
1061
1046
|
index = 0;
|
|
1062
1047
|
}
|
|
@@ -1070,7 +1055,7 @@ export default class Carousel extends PureComponent {
|
|
|
1070
1055
|
this._snapToItem(positionIndex, animated, fireCallback);
|
|
1071
1056
|
}
|
|
1072
1057
|
|
|
1073
|
-
snapToNext(animated = true, fireCallback = true) {
|
|
1058
|
+
snapToNext (animated = true, fireCallback = true) {
|
|
1074
1059
|
const itemsLength = this._getCustomDataLength();
|
|
1075
1060
|
|
|
1076
1061
|
let newIndex = this._activeItem + 1;
|
|
@@ -1083,7 +1068,7 @@ export default class Carousel extends PureComponent {
|
|
|
1083
1068
|
this._snapToItem(newIndex, animated, fireCallback);
|
|
1084
1069
|
}
|
|
1085
1070
|
|
|
1086
|
-
snapToPrev(animated = true, fireCallback = true) {
|
|
1071
|
+
snapToPrev (animated = true, fireCallback = true) {
|
|
1087
1072
|
const itemsLength = this._getCustomDataLength();
|
|
1088
1073
|
|
|
1089
1074
|
let newIndex = this._activeItem - 1;
|
|
@@ -1097,7 +1082,7 @@ export default class Carousel extends PureComponent {
|
|
|
1097
1082
|
}
|
|
1098
1083
|
|
|
1099
1084
|
// https://github.com/facebook/react-native/issues/1831#issuecomment-231069668
|
|
1100
|
-
triggerRenderingHack(offset) {
|
|
1085
|
+
triggerRenderingHack (offset) {
|
|
1101
1086
|
// Avoid messing with user scroll
|
|
1102
1087
|
if (Date.now() - this._lastScrollDate < 500) {
|
|
1103
1088
|
return;
|
|
@@ -1112,22 +1097,23 @@ export default class Carousel extends PureComponent {
|
|
|
1112
1097
|
this._scrollTo(scrollPosition + scrollOffset, false);
|
|
1113
1098
|
}
|
|
1114
1099
|
|
|
1115
|
-
_getSlideInterpolatedStyle(index, animatedValue) {
|
|
1100
|
+
_getSlideInterpolatedStyle (index, animatedValue) {
|
|
1116
1101
|
const { layoutCardOffset, slideInterpolatedStyle } = this.props;
|
|
1117
1102
|
|
|
1118
1103
|
if (slideInterpolatedStyle) {
|
|
1119
1104
|
return slideInterpolatedStyle(index, animatedValue, this.props);
|
|
1120
|
-
} if (this._shouldUseTinderLayout()) {
|
|
1105
|
+
} else if (this._shouldUseTinderLayout()) {
|
|
1121
1106
|
return tinderAnimatedStyles(index, animatedValue, this.props, layoutCardOffset);
|
|
1122
|
-
} if (this._shouldUseStackLayout()) {
|
|
1107
|
+
} else if (this._shouldUseStackLayout()) {
|
|
1123
1108
|
return stackAnimatedStyles(index, animatedValue, this.props, layoutCardOffset);
|
|
1124
|
-
} if (this._shouldUseShiftLayout()) {
|
|
1109
|
+
} else if (this._shouldUseShiftLayout()) {
|
|
1125
1110
|
return shiftAnimatedStyles(index, animatedValue, this.props);
|
|
1111
|
+
} else {
|
|
1112
|
+
return defaultAnimatedStyles(index, animatedValue, this.props);
|
|
1126
1113
|
}
|
|
1127
|
-
return defaultAnimatedStyles(index, animatedValue, this.props);
|
|
1128
1114
|
}
|
|
1129
1115
|
|
|
1130
|
-
_renderItem({ item, index }) {
|
|
1116
|
+
_renderItem ({ item, index }) {
|
|
1131
1117
|
const { interpolators } = this.state;
|
|
1132
1118
|
const {
|
|
1133
1119
|
hasParallaxImages,
|
|
@@ -1138,8 +1124,7 @@ export default class Carousel extends PureComponent {
|
|
|
1138
1124
|
sliderHeight,
|
|
1139
1125
|
sliderWidth,
|
|
1140
1126
|
slideStyle,
|
|
1141
|
-
vertical
|
|
1142
|
-
isCustomScrollWidth
|
|
1127
|
+
vertical
|
|
1143
1128
|
} = this.props;
|
|
1144
1129
|
|
|
1145
1130
|
const animatedValue = interpolators && interpolators[index];
|
|
@@ -1149,7 +1134,7 @@ export default class Carousel extends PureComponent {
|
|
|
1149
1134
|
}
|
|
1150
1135
|
|
|
1151
1136
|
const animate = this._shouldAnimateSlides();
|
|
1152
|
-
const
|
|
1137
|
+
const Component = animate ? Animated.View : View;
|
|
1153
1138
|
const animatedStyle = animate ? this._getSlideInterpolatedStyle(index, animatedValue) : {};
|
|
1154
1139
|
|
|
1155
1140
|
const parallaxProps = hasParallaxImages ? {
|
|
@@ -1162,24 +1147,19 @@ export default class Carousel extends PureComponent {
|
|
|
1162
1147
|
itemHeight
|
|
1163
1148
|
} : undefined;
|
|
1164
1149
|
|
|
1150
|
+
const mainDimension = vertical ? { height: itemHeight } : { width: itemWidth };
|
|
1165
1151
|
const specificProps = this._needsScrollView() ? {
|
|
1166
1152
|
key: keyExtractor ? keyExtractor(item, index) : this._getKeyExtractor(item, index)
|
|
1167
1153
|
} : {};
|
|
1168
|
-
|
|
1154
|
+
|
|
1169
1155
|
return (
|
|
1170
|
-
<
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
{...specificProps}
|
|
1174
|
-
>
|
|
1175
|
-
{renderItem({
|
|
1176
|
-
item, index, realIndex: this._getDataIndex(index), activeIndex: this._getDataIndex(this._activeItem)
|
|
1177
|
-
}, parallaxProps)}
|
|
1178
|
-
</ComponentView>
|
|
1156
|
+
<Component style={[mainDimension, slideStyle, animatedStyle]} pointerEvents={'box-none'} {...specificProps}>
|
|
1157
|
+
{ renderItem({ item, index, realIndex: this._getDataIndex(index), activeIndex: this._getDataIndex(this._activeItem) }, parallaxProps) }
|
|
1158
|
+
</Component>
|
|
1179
1159
|
);
|
|
1180
1160
|
}
|
|
1181
1161
|
|
|
1182
|
-
_getComponentOverridableProps() {
|
|
1162
|
+
_getComponentOverridableProps () {
|
|
1183
1163
|
const {
|
|
1184
1164
|
enableMomentum,
|
|
1185
1165
|
itemWidth,
|
|
@@ -1190,18 +1170,18 @@ export default class Carousel extends PureComponent {
|
|
|
1190
1170
|
vertical
|
|
1191
1171
|
} = this.props;
|
|
1192
1172
|
|
|
1193
|
-
const visibleItems = Math.ceil(vertical
|
|
1194
|
-
|
|
1195
|
-
|
|
1173
|
+
const visibleItems = Math.ceil(vertical ?
|
|
1174
|
+
sliderHeight / itemHeight :
|
|
1175
|
+
sliderWidth / itemWidth) + 1;
|
|
1196
1176
|
const initialNumPerSide = this._enableLoop() ? loopClonesPerSide : 2;
|
|
1197
1177
|
const initialNumToRender = visibleItems + (initialNumPerSide * 2);
|
|
1198
1178
|
const maxToRenderPerBatch = 1 + (initialNumToRender * 2);
|
|
1199
1179
|
const windowSize = maxToRenderPerBatch;
|
|
1200
1180
|
|
|
1201
1181
|
const specificProps = !this._needsScrollView() ? {
|
|
1202
|
-
initialNumToRender,
|
|
1203
|
-
maxToRenderPerBatch,
|
|
1204
|
-
windowSize
|
|
1182
|
+
initialNumToRender: initialNumToRender,
|
|
1183
|
+
maxToRenderPerBatch: maxToRenderPerBatch,
|
|
1184
|
+
windowSize: windowSize
|
|
1205
1185
|
// updateCellsBatchingPeriod
|
|
1206
1186
|
} : {};
|
|
1207
1187
|
|
|
@@ -1216,12 +1196,12 @@ export default class Carousel extends PureComponent {
|
|
|
1216
1196
|
scrollsToTop: false,
|
|
1217
1197
|
removeClippedSubviews: !this._needsScrollView(),
|
|
1218
1198
|
inverted: this._needsRTLAdaptations(),
|
|
1219
|
-
|
|
1199
|
+
renderToHardwareTextureAndroid: true,
|
|
1220
1200
|
...specificProps
|
|
1221
1201
|
};
|
|
1222
1202
|
}
|
|
1223
1203
|
|
|
1224
|
-
_getComponentStaticProps() {
|
|
1204
|
+
_getComponentStaticProps () {
|
|
1225
1205
|
const { hideCarousel } = this.state;
|
|
1226
1206
|
const {
|
|
1227
1207
|
containerCustomStyle,
|
|
@@ -1236,11 +1216,11 @@ export default class Carousel extends PureComponent {
|
|
|
1236
1216
|
const containerStyle = [
|
|
1237
1217
|
containerCustomStyle || style || {},
|
|
1238
1218
|
hideCarousel ? { opacity: 0 } : {},
|
|
1239
|
-
vertical
|
|
1240
|
-
|
|
1219
|
+
vertical ?
|
|
1220
|
+
{ height: sliderHeight, flexDirection: 'column' } :
|
|
1241
1221
|
// LTR hack; see https://github.com/facebook/react-native/issues/11960
|
|
1242
1222
|
// and https://github.com/facebook/react-native/issues/13100#issuecomment-328986423
|
|
1243
|
-
|
|
1223
|
+
{ width: sliderWidth, flexDirection: this._needsRTLAdaptations() ? 'row-reverse' : 'row' }
|
|
1244
1224
|
];
|
|
1245
1225
|
const contentContainerStyle = [
|
|
1246
1226
|
vertical ? {
|
|
@@ -1257,15 +1237,14 @@ export default class Carousel extends PureComponent {
|
|
|
1257
1237
|
// extraData: this.state,
|
|
1258
1238
|
renderItem: this._renderItem,
|
|
1259
1239
|
numColumns: 1,
|
|
1260
|
-
getItemLayout: undefined, // see #193
|
|
1261
|
-
initialScrollIndex: undefined, // see #193
|
|
1262
1240
|
keyExtractor: keyExtractor || this._getKeyExtractor
|
|
1263
1241
|
} : {};
|
|
1242
|
+
|
|
1264
1243
|
return {
|
|
1265
|
-
ref:
|
|
1244
|
+
ref: c => this._carouselRef = c,
|
|
1266
1245
|
data: this._getCustomData(),
|
|
1267
1246
|
style: containerStyle,
|
|
1268
|
-
contentContainerStyle,
|
|
1247
|
+
contentContainerStyle: contentContainerStyle,
|
|
1269
1248
|
horizontal: !vertical,
|
|
1270
1249
|
scrollEventThrottle: 1,
|
|
1271
1250
|
onScroll: this._onScrollHandler,
|
|
@@ -1281,7 +1260,7 @@ export default class Carousel extends PureComponent {
|
|
|
1281
1260
|
};
|
|
1282
1261
|
}
|
|
1283
1262
|
|
|
1284
|
-
render() {
|
|
1263
|
+
render () {
|
|
1285
1264
|
const { data, renderItem, useScrollView } = this.props;
|
|
1286
1265
|
|
|
1287
1266
|
if (!data || !renderItem) {
|
|
@@ -1294,18 +1273,18 @@ export default class Carousel extends PureComponent {
|
|
|
1294
1273
|
...this._getComponentStaticProps()
|
|
1295
1274
|
};
|
|
1296
1275
|
|
|
1297
|
-
const ScrollViewComponent = typeof useScrollView === 'function' ? useScrollView :
|
|
1276
|
+
const ScrollViewComponent = typeof useScrollView === 'function' ? useScrollView : Animated.ScrollView
|
|
1298
1277
|
|
|
1299
1278
|
return this._needsScrollView() ? (
|
|
1300
1279
|
<ScrollViewComponent {...props}>
|
|
1301
1280
|
{
|
|
1302
|
-
this._getCustomData().map((item, index) =>
|
|
1303
|
-
item, index, realIndex: this._getDataIndex(index), activeIndex: this._getDataIndex(this._activeItem)
|
|
1304
|
-
})
|
|
1281
|
+
this._getCustomData().map((item, index) => {
|
|
1282
|
+
return this._renderItem({ item, index, realIndex: this._getDataIndex(index), activeIndex: this._getDataIndex(this._activeItem) });
|
|
1283
|
+
})
|
|
1305
1284
|
}
|
|
1306
1285
|
</ScrollViewComponent>
|
|
1307
1286
|
) : (
|
|
1308
|
-
<
|
|
1287
|
+
<Animated.FlatList {...props} />
|
|
1309
1288
|
);
|
|
1310
1289
|
}
|
|
1311
1290
|
}
|
|
@@ -1383,7 +1362,7 @@ Carousel.defaultProps = {
|
|
|
1383
1362
|
slideStyle: {},
|
|
1384
1363
|
shouldOptimizeUpdates: true,
|
|
1385
1364
|
swipeThreshold: 20,
|
|
1386
|
-
useScrollView: !
|
|
1365
|
+
useScrollView: !Animated.FlatList,
|
|
1387
1366
|
vertical: false,
|
|
1388
1367
|
showsPagination: true,
|
|
1389
1368
|
isCustomScrollWidth: false,
|