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