@momo-kits/carousel 0.0.41-beta → 0.0.41-beta.9
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 +240 -250
- package/CarouselV2.js +1368 -0
- package/index.js +2 -1
- package/package.json +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 = {
|
|
@@ -81,32 +71,26 @@ export default class Carousel extends PureComponent {
|
|
|
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,17 +399,23 @@ export default class Carousel extends PureComponent {
|
|
|
423
399
|
return this._enableLoop() ? index + loopClonesPerSide : index;
|
|
424
400
|
}
|
|
425
401
|
|
|
426
|
-
_getWrappedRef() {
|
|
402
|
+
_getWrappedRef () {
|
|
403
|
+
if (this._carouselRef && (
|
|
404
|
+
(this._needsScrollView() && this._carouselRef.scrollTo) ||
|
|
405
|
+
(!this._needsScrollView() && this._carouselRef.scrollToOffset)
|
|
406
|
+
)) {
|
|
407
|
+
return this._carouselRef;
|
|
408
|
+
}
|
|
427
409
|
// https://github.com/facebook/react-native/issues/10635
|
|
428
410
|
// https://stackoverflow.com/a/48786374/8412141
|
|
429
411
|
return this._carouselRef && this._carouselRef.getNode && this._carouselRef.getNode();
|
|
430
412
|
}
|
|
431
413
|
|
|
432
|
-
_getScrollEnabled() {
|
|
414
|
+
_getScrollEnabled () {
|
|
433
415
|
return this._scrollEnabled;
|
|
434
416
|
}
|
|
435
417
|
|
|
436
|
-
_setScrollEnabled(scrollEnabled = true) {
|
|
418
|
+
_setScrollEnabled (scrollEnabled = true) {
|
|
437
419
|
const wrappedRef = this._getWrappedRef();
|
|
438
420
|
|
|
439
421
|
if (!wrappedRef || !wrappedRef.setNativeProps) {
|
|
@@ -446,56 +428,54 @@ export default class Carousel extends PureComponent {
|
|
|
446
428
|
this._scrollEnabled = scrollEnabled;
|
|
447
429
|
}
|
|
448
430
|
|
|
449
|
-
_getKeyExtractor(item, index) {
|
|
431
|
+
_getKeyExtractor (item, index) {
|
|
450
432
|
return this._needsScrollView() ? `scrollview-item-${index}` : `flatlist-item-${index}`;
|
|
451
433
|
}
|
|
452
434
|
|
|
453
|
-
_getScrollOffset(event) {
|
|
435
|
+
_getScrollOffset (event) {
|
|
454
436
|
const { vertical } = this.props;
|
|
455
|
-
return (event && event.nativeEvent && event.nativeEvent.contentOffset
|
|
456
|
-
|
|
437
|
+
return (event && event.nativeEvent && event.nativeEvent.contentOffset &&
|
|
438
|
+
event.nativeEvent.contentOffset[vertical ? 'y' : 'x']) || 0;
|
|
457
439
|
}
|
|
458
440
|
|
|
459
|
-
_getContainerInnerMargin(opposite = false) {
|
|
460
|
-
const {
|
|
461
|
-
sliderWidth, sliderHeight, itemWidth, itemHeight, vertical, activeSlideAlignment
|
|
462
|
-
} = this.props;
|
|
441
|
+
_getContainerInnerMargin (opposite = false) {
|
|
442
|
+
const { sliderWidth, sliderHeight, itemWidth, itemHeight, vertical, activeSlideAlignment } = this.props;
|
|
463
443
|
|
|
464
|
-
if ((activeSlideAlignment === 'start' && !opposite)
|
|
465
|
-
|
|
444
|
+
if ((activeSlideAlignment === 'start' && !opposite) ||
|
|
445
|
+
(activeSlideAlignment === 'end' && opposite)) {
|
|
466
446
|
return 0;
|
|
467
|
-
} if ((activeSlideAlignment === 'end' && !opposite)
|
|
468
|
-
|
|
447
|
+
} else if ((activeSlideAlignment === 'end' && !opposite) ||
|
|
448
|
+
(activeSlideAlignment === 'start' && opposite)) {
|
|
469
449
|
return vertical ? sliderHeight - itemHeight : sliderWidth - itemWidth;
|
|
450
|
+
} else {
|
|
451
|
+
return vertical ? (sliderHeight - itemHeight) / 2 : (sliderWidth - itemWidth) / 2;
|
|
470
452
|
}
|
|
471
|
-
return vertical ? (sliderHeight - itemHeight) / 2 : (sliderWidth - itemWidth) / 2;
|
|
472
453
|
}
|
|
473
454
|
|
|
474
|
-
_getViewportOffset() {
|
|
475
|
-
const {
|
|
476
|
-
sliderWidth, sliderHeight, itemWidth, itemHeight, vertical, activeSlideAlignment
|
|
477
|
-
} = this.props;
|
|
455
|
+
_getViewportOffset () {
|
|
456
|
+
const { sliderWidth, sliderHeight, itemWidth, itemHeight, vertical, activeSlideAlignment } = this.props;
|
|
478
457
|
|
|
479
458
|
if (activeSlideAlignment === 'start') {
|
|
480
459
|
return vertical ? itemHeight / 2 : itemWidth / 2;
|
|
481
|
-
} if (activeSlideAlignment === 'end') {
|
|
482
|
-
return vertical
|
|
483
|
-
|
|
484
|
-
|
|
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;
|
|
485
466
|
}
|
|
486
|
-
return vertical ? sliderHeight / 2 : sliderWidth / 2;
|
|
487
467
|
}
|
|
488
468
|
|
|
489
|
-
_getCenter(offset) {
|
|
469
|
+
_getCenter (offset) {
|
|
490
470
|
return offset + this._getViewportOffset() - this._getContainerInnerMargin();
|
|
491
471
|
}
|
|
492
472
|
|
|
493
|
-
_getActiveItem(offset) {
|
|
473
|
+
_getActiveItem (offset) {
|
|
494
474
|
const { activeSlideOffset, swipeThreshold } = this.props;
|
|
495
475
|
const center = this._getCenter(offset);
|
|
496
476
|
const centerOffset = activeSlideOffset || swipeThreshold;
|
|
497
477
|
|
|
498
|
-
for (let i = 0; i < this._positions.length; i
|
|
478
|
+
for (let i = 0; i < this._positions.length; i++) {
|
|
499
479
|
const { start, end } = this._positions[i];
|
|
500
480
|
if (center + centerOffset >= start && center - centerOffset <= end) {
|
|
501
481
|
return i;
|
|
@@ -510,17 +490,15 @@ export default class Carousel extends PureComponent {
|
|
|
510
490
|
return 0;
|
|
511
491
|
}
|
|
512
492
|
|
|
513
|
-
_initPositionsAndInterpolators(props = this.props) {
|
|
514
|
-
const {
|
|
515
|
-
data, itemWidth, itemHeight, scrollInterpolator, vertical
|
|
516
|
-
} = props;
|
|
493
|
+
_initPositionsAndInterpolators (props = this.props) {
|
|
494
|
+
const { data, itemWidth, itemHeight, scrollInterpolator, vertical } = props;
|
|
517
495
|
const sizeRef = vertical ? itemHeight : itemWidth;
|
|
518
496
|
|
|
519
497
|
if (!data || !data.length) {
|
|
520
498
|
return;
|
|
521
499
|
}
|
|
522
500
|
|
|
523
|
-
|
|
501
|
+
let interpolators = [];
|
|
524
502
|
this._positions = [];
|
|
525
503
|
|
|
526
504
|
this._getCustomData(props).forEach((itemData, index) => {
|
|
@@ -559,10 +537,11 @@ export default class Carousel extends PureComponent {
|
|
|
559
537
|
|
|
560
538
|
interpolators.push(animatedValue);
|
|
561
539
|
});
|
|
540
|
+
|
|
562
541
|
this.setState({ interpolators });
|
|
563
542
|
}
|
|
564
543
|
|
|
565
|
-
_getSlideAnimation(index, toValue) {
|
|
544
|
+
_getSlideAnimation (index, toValue) {
|
|
566
545
|
const { interpolators } = this.state;
|
|
567
546
|
const { activeAnimationType, activeAnimationOptions } = this.props;
|
|
568
547
|
|
|
@@ -576,11 +555,11 @@ export default class Carousel extends PureComponent {
|
|
|
576
555
|
isInteraction: false,
|
|
577
556
|
useNativeDriver: true,
|
|
578
557
|
...activeAnimationOptions,
|
|
579
|
-
toValue
|
|
558
|
+
toValue: toValue
|
|
580
559
|
};
|
|
581
560
|
|
|
582
561
|
return Animated.parallel([
|
|
583
|
-
Animated
|
|
562
|
+
Animated['timing'](
|
|
584
563
|
animatedValue,
|
|
585
564
|
{ ...animationCommonOptions, easing: Easing.linear }
|
|
586
565
|
),
|
|
@@ -591,18 +570,18 @@ export default class Carousel extends PureComponent {
|
|
|
591
570
|
]);
|
|
592
571
|
}
|
|
593
572
|
|
|
594
|
-
_playCustomSlideAnimation(current, next) {
|
|
573
|
+
_playCustomSlideAnimation (current, next) {
|
|
595
574
|
const { interpolators } = this.state;
|
|
596
575
|
const itemsLength = this._getCustomDataLength();
|
|
597
576
|
const _currentIndex = this._getCustomIndex(current);
|
|
598
577
|
const _currentDataIndex = this._getDataIndex(_currentIndex);
|
|
599
578
|
const _nextIndex = this._getCustomIndex(next);
|
|
600
579
|
const _nextDataIndex = this._getDataIndex(_nextIndex);
|
|
601
|
-
|
|
580
|
+
let animations = [];
|
|
602
581
|
|
|
603
582
|
// Keep animations in sync when looping
|
|
604
583
|
if (this._enableLoop()) {
|
|
605
|
-
for (let i = 0; i < itemsLength; i
|
|
584
|
+
for (let i = 0; i < itemsLength; i++) {
|
|
606
585
|
if (this._getDataIndex(i) === _currentDataIndex && interpolators[i]) {
|
|
607
586
|
animations.push(this._getSlideAnimation(i, 0));
|
|
608
587
|
} else if (this._getDataIndex(i) === _nextDataIndex && interpolators[i]) {
|
|
@@ -621,7 +600,7 @@ export default class Carousel extends PureComponent {
|
|
|
621
600
|
Animated.parallel(animations, { stopTogether: false }).start();
|
|
622
601
|
}
|
|
623
602
|
|
|
624
|
-
_hackActiveSlideAnimation(index, goTo, force = false) {
|
|
603
|
+
_hackActiveSlideAnimation (index, goTo, force = false) {
|
|
625
604
|
const { data } = this.props;
|
|
626
605
|
|
|
627
606
|
if (!this._mounted || !this._carouselRef || !this._positions[index] || (!force && this._enableLoop())) {
|
|
@@ -645,7 +624,7 @@ export default class Carousel extends PureComponent {
|
|
|
645
624
|
}, 50); // works randomly when set to '0'
|
|
646
625
|
}
|
|
647
626
|
|
|
648
|
-
_lockScroll() {
|
|
627
|
+
_lockScroll () {
|
|
649
628
|
const { lockScrollTimeoutDuration } = this.props;
|
|
650
629
|
clearTimeout(this._lockScrollTimeout);
|
|
651
630
|
this._lockScrollTimeout = setTimeout(() => {
|
|
@@ -654,17 +633,17 @@ export default class Carousel extends PureComponent {
|
|
|
654
633
|
this._setScrollEnabled(false);
|
|
655
634
|
}
|
|
656
635
|
|
|
657
|
-
_releaseScroll() {
|
|
636
|
+
_releaseScroll () {
|
|
658
637
|
clearTimeout(this._lockScrollTimeout);
|
|
659
638
|
this._setScrollEnabled(true);
|
|
660
639
|
}
|
|
661
640
|
|
|
662
|
-
_repositionScroll(index) {
|
|
641
|
+
_repositionScroll (index) {
|
|
663
642
|
const { data, loopClonesPerSide } = this.props;
|
|
664
643
|
const dataLength = data && data.length;
|
|
665
644
|
|
|
666
|
-
if (!this._enableLoop() || !dataLength
|
|
667
|
-
|
|
645
|
+
if (!this._enableLoop() || !dataLength ||
|
|
646
|
+
(index >= loopClonesPerSide && index < dataLength + loopClonesPerSide)) {
|
|
668
647
|
return;
|
|
669
648
|
}
|
|
670
649
|
|
|
@@ -675,10 +654,11 @@ export default class Carousel extends PureComponent {
|
|
|
675
654
|
} else if (index < loopClonesPerSide) {
|
|
676
655
|
repositionTo = index + dataLength;
|
|
677
656
|
}
|
|
657
|
+
|
|
678
658
|
this._snapToItem(repositionTo, false, false, false, false);
|
|
679
659
|
}
|
|
680
660
|
|
|
681
|
-
_scrollTo(offset, animated = true) {
|
|
661
|
+
_scrollTo (offset, animated = true) {
|
|
682
662
|
const { vertical } = this.props;
|
|
683
663
|
const wrappedRef = this._getWrappedRef();
|
|
684
664
|
|
|
@@ -704,14 +684,15 @@ export default class Carousel extends PureComponent {
|
|
|
704
684
|
}
|
|
705
685
|
}
|
|
706
686
|
|
|
707
|
-
_onScroll(event) {
|
|
687
|
+
_onScroll (event) {
|
|
708
688
|
const { callbackOffsetMargin, enableMomentum, onScroll } = this.props;
|
|
709
689
|
|
|
710
690
|
const scrollOffset = event ? this._getScrollOffset(event) : this._currentContentOffset;
|
|
711
691
|
const nextActiveItem = this._getActiveItem(scrollOffset);
|
|
712
692
|
const itemReached = nextActiveItem === this._itemToSnapTo;
|
|
713
|
-
const scrollConditions =
|
|
714
|
-
|
|
693
|
+
const scrollConditions =
|
|
694
|
+
scrollOffset >= this._scrollOffsetRef - callbackOffsetMargin &&
|
|
695
|
+
scrollOffset <= this._scrollOffsetRef + callbackOffsetMargin;
|
|
715
696
|
|
|
716
697
|
this._currentContentOffset = scrollOffset;
|
|
717
698
|
this._onScrollTriggered = true;
|
|
@@ -754,17 +735,18 @@ export default class Carousel extends PureComponent {
|
|
|
754
735
|
}
|
|
755
736
|
}
|
|
756
737
|
}
|
|
757
|
-
|
|
758
|
-
|
|
738
|
+
|
|
739
|
+
if (nextActiveItem === this._itemToSnapTo &&
|
|
740
|
+
scrollOffset === this._scrollOffsetRef) {
|
|
759
741
|
this._repositionScroll(nextActiveItem);
|
|
760
742
|
}
|
|
761
743
|
|
|
762
|
-
if (typeof onScroll ===
|
|
744
|
+
if (typeof onScroll === "function" && event) {
|
|
763
745
|
onScroll(event);
|
|
764
746
|
}
|
|
765
747
|
}
|
|
766
748
|
|
|
767
|
-
_onStartShouldSetResponderCapture(event) {
|
|
749
|
+
_onStartShouldSetResponderCapture (event) {
|
|
768
750
|
const { onStartShouldSetResponderCapture } = this.props;
|
|
769
751
|
|
|
770
752
|
if (onStartShouldSetResponderCapture) {
|
|
@@ -774,34 +756,34 @@ export default class Carousel extends PureComponent {
|
|
|
774
756
|
return this._getScrollEnabled();
|
|
775
757
|
}
|
|
776
758
|
|
|
777
|
-
_onTouchStart() {
|
|
778
|
-
const { onTouchStart } = this.props
|
|
759
|
+
_onTouchStart () {
|
|
760
|
+
const { onTouchStart } = this.props
|
|
779
761
|
|
|
780
762
|
// `onTouchStart` is fired even when `scrollEnabled` is set to `false`
|
|
781
763
|
if (this._getScrollEnabled() !== false && this._autoplaying) {
|
|
782
|
-
this.
|
|
764
|
+
this.pauseAutoPlay();
|
|
783
765
|
}
|
|
784
766
|
|
|
785
767
|
if (onTouchStart) {
|
|
786
|
-
onTouchStart()
|
|
768
|
+
onTouchStart()
|
|
787
769
|
}
|
|
788
770
|
}
|
|
789
771
|
|
|
790
|
-
_onTouchEnd() {
|
|
791
|
-
const { onTouchEnd
|
|
772
|
+
_onTouchEnd () {
|
|
773
|
+
const { onTouchEnd } = this.props
|
|
792
774
|
|
|
793
|
-
if (this._getScrollEnabled() !== false &&
|
|
775
|
+
if (this._getScrollEnabled() !== false && this._autoplay && !this._autoplaying) {
|
|
794
776
|
// This event is buggy on Android, so a fallback is provided in _onScrollEnd()
|
|
795
777
|
this.startAutoplay();
|
|
796
778
|
}
|
|
797
779
|
|
|
798
780
|
if (onTouchEnd) {
|
|
799
|
-
onTouchEnd()
|
|
781
|
+
onTouchEnd()
|
|
800
782
|
}
|
|
801
783
|
}
|
|
802
784
|
|
|
803
785
|
// Used when `enableSnap` is ENABLED
|
|
804
|
-
_onScrollBeginDrag(event) {
|
|
786
|
+
_onScrollBeginDrag (event) {
|
|
805
787
|
const { onScrollBeginDrag } = this.props;
|
|
806
788
|
|
|
807
789
|
if (!this._getScrollEnabled()) {
|
|
@@ -819,11 +801,11 @@ export default class Carousel extends PureComponent {
|
|
|
819
801
|
}
|
|
820
802
|
|
|
821
803
|
// Used when `enableMomentum` is DISABLED
|
|
822
|
-
_onScrollEndDrag(event) {
|
|
804
|
+
_onScrollEndDrag (event) {
|
|
823
805
|
const { onScrollEndDrag } = this.props;
|
|
824
806
|
|
|
825
807
|
if (this._carouselRef) {
|
|
826
|
-
|
|
808
|
+
this._onScrollEnd && this._onScrollEnd();
|
|
827
809
|
}
|
|
828
810
|
|
|
829
811
|
if (onScrollEndDrag) {
|
|
@@ -832,11 +814,11 @@ export default class Carousel extends PureComponent {
|
|
|
832
814
|
}
|
|
833
815
|
|
|
834
816
|
// Used when `enableMomentum` is ENABLED
|
|
835
|
-
_onMomentumScrollEnd(event) {
|
|
817
|
+
_onMomentumScrollEnd (event) {
|
|
836
818
|
const { onMomentumScrollEnd } = this.props;
|
|
837
819
|
|
|
838
820
|
if (this._carouselRef) {
|
|
839
|
-
|
|
821
|
+
this._onScrollEnd && this._onScrollEnd();
|
|
840
822
|
}
|
|
841
823
|
|
|
842
824
|
if (onMomentumScrollEnd) {
|
|
@@ -844,8 +826,8 @@ export default class Carousel extends PureComponent {
|
|
|
844
826
|
}
|
|
845
827
|
}
|
|
846
828
|
|
|
847
|
-
_onScrollEnd() {
|
|
848
|
-
const {
|
|
829
|
+
_onScrollEnd (event) {
|
|
830
|
+
const { autoplayDelay, enableSnap } = this.props;
|
|
849
831
|
|
|
850
832
|
if (this._ignoreNextMomentum) {
|
|
851
833
|
// iOS fix
|
|
@@ -853,6 +835,10 @@ export default class Carousel extends PureComponent {
|
|
|
853
835
|
return;
|
|
854
836
|
}
|
|
855
837
|
|
|
838
|
+
if (this._currentContentOffset === this._scrollEndOffset) {
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
|
|
856
842
|
this._scrollEndOffset = this._currentContentOffset;
|
|
857
843
|
this._scrollEndActive = this._getActiveItem(this._scrollEndOffset);
|
|
858
844
|
|
|
@@ -862,7 +848,7 @@ export default class Carousel extends PureComponent {
|
|
|
862
848
|
|
|
863
849
|
// The touchEnd event is buggy on Android, so this will serve as a fallback whenever needed
|
|
864
850
|
// https://github.com/facebook/react-native/issues/9439
|
|
865
|
-
if (
|
|
851
|
+
if (this._autoplay && !this._autoplaying) {
|
|
866
852
|
clearTimeout(this._enableAutoplayTimeout);
|
|
867
853
|
this._enableAutoplayTimeout = setTimeout(() => {
|
|
868
854
|
this.startAutoplay();
|
|
@@ -873,7 +859,7 @@ export default class Carousel extends PureComponent {
|
|
|
873
859
|
// Due to a bug, this event is only fired on iOS
|
|
874
860
|
// https://github.com/facebook/react-native/issues/6791
|
|
875
861
|
// it's fine since we're only fixing an iOS bug in it, so ...
|
|
876
|
-
_onTouchRelease() {
|
|
862
|
+
_onTouchRelease (event) {
|
|
877
863
|
const { enableMomentum } = this.props;
|
|
878
864
|
|
|
879
865
|
if (enableMomentum && IS_IOS) {
|
|
@@ -884,7 +870,7 @@ export default class Carousel extends PureComponent {
|
|
|
884
870
|
}
|
|
885
871
|
}
|
|
886
872
|
|
|
887
|
-
_onLayout(event) {
|
|
873
|
+
_onLayout (event) {
|
|
888
874
|
const { onLayout } = this.props;
|
|
889
875
|
|
|
890
876
|
// Prevent unneeded actions during the first 'onLayout' (triggered on init)
|
|
@@ -900,7 +886,7 @@ export default class Carousel extends PureComponent {
|
|
|
900
886
|
}
|
|
901
887
|
}
|
|
902
888
|
|
|
903
|
-
_snapScroll(delta) {
|
|
889
|
+
_snapScroll (delta) {
|
|
904
890
|
const { swipeThreshold } = this.props;
|
|
905
891
|
|
|
906
892
|
// When using momentum and releasing the touch with
|
|
@@ -933,7 +919,7 @@ export default class Carousel extends PureComponent {
|
|
|
933
919
|
}
|
|
934
920
|
}
|
|
935
921
|
|
|
936
|
-
_snapToItem(index, animated = true, fireCallback = true, initial = false, lockScroll = true) {
|
|
922
|
+
_snapToItem (index, animated = true, fireCallback = true, initial = false, lockScroll = true) {
|
|
937
923
|
const { enableMomentum, onSnapToItem, onBeforeSnapToItem } = this.props;
|
|
938
924
|
const itemsLength = this._getCustomDataLength();
|
|
939
925
|
const wrappedRef = this._getWrappedRef();
|
|
@@ -977,9 +963,11 @@ export default class Carousel extends PureComponent {
|
|
|
977
963
|
|
|
978
964
|
this._scrollTo(this._scrollOffsetRef, animated);
|
|
979
965
|
|
|
966
|
+
this._scrollEndOffset = this._currentContentOffset;
|
|
967
|
+
|
|
980
968
|
if (enableMomentum) {
|
|
981
969
|
// iOS fix, check the note in the constructor
|
|
982
|
-
if (
|
|
970
|
+
if (!initial) {
|
|
983
971
|
this._ignoreNextMomentum = true;
|
|
984
972
|
}
|
|
985
973
|
|
|
@@ -1000,7 +988,7 @@ export default class Carousel extends PureComponent {
|
|
|
1000
988
|
}
|
|
1001
989
|
}
|
|
1002
990
|
|
|
1003
|
-
_onBeforeSnap(index) {
|
|
991
|
+
_onBeforeSnap (index) {
|
|
1004
992
|
const { onBeforeSnapToItem } = this.props;
|
|
1005
993
|
|
|
1006
994
|
if (!this._carouselRef) {
|
|
@@ -1008,10 +996,10 @@ export default class Carousel extends PureComponent {
|
|
|
1008
996
|
}
|
|
1009
997
|
|
|
1010
998
|
this._canFireBeforeCallback = false;
|
|
1011
|
-
|
|
999
|
+
onBeforeSnapToItem && onBeforeSnapToItem(index);
|
|
1012
1000
|
}
|
|
1013
1001
|
|
|
1014
|
-
_onSnap(index) {
|
|
1002
|
+
_onSnap (index) {
|
|
1015
1003
|
const { onSnapToItem } = this.props;
|
|
1016
1004
|
|
|
1017
1005
|
if (!this._carouselRef) {
|
|
@@ -1019,11 +1007,12 @@ export default class Carousel extends PureComponent {
|
|
|
1019
1007
|
}
|
|
1020
1008
|
|
|
1021
1009
|
this._canFireCallback = false;
|
|
1022
|
-
|
|
1010
|
+
onSnapToItem && onSnapToItem(index);
|
|
1023
1011
|
}
|
|
1024
1012
|
|
|
1025
|
-
startAutoplay() {
|
|
1013
|
+
startAutoplay () {
|
|
1026
1014
|
const { autoplayInterval, autoplayDelay } = this.props;
|
|
1015
|
+
this._autoplay = true;
|
|
1027
1016
|
|
|
1028
1017
|
if (this._autoplaying) {
|
|
1029
1018
|
return;
|
|
@@ -1040,12 +1029,19 @@ export default class Carousel extends PureComponent {
|
|
|
1040
1029
|
}, autoplayDelay);
|
|
1041
1030
|
}
|
|
1042
1031
|
|
|
1043
|
-
|
|
1032
|
+
pauseAutoPlay () {
|
|
1044
1033
|
this._autoplaying = false;
|
|
1034
|
+
clearTimeout(this._autoplayTimeout);
|
|
1035
|
+
clearTimeout(this._enableAutoplayTimeout);
|
|
1045
1036
|
clearInterval(this._autoplayInterval);
|
|
1046
1037
|
}
|
|
1047
1038
|
|
|
1048
|
-
|
|
1039
|
+
stopAutoplay () {
|
|
1040
|
+
this._autoplay = false;
|
|
1041
|
+
this.pauseAutoPlay();
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
snapToItem (index, animated = true, fireCallback = true) {
|
|
1049
1045
|
if (!index || index < 0) {
|
|
1050
1046
|
index = 0;
|
|
1051
1047
|
}
|
|
@@ -1059,7 +1055,7 @@ export default class Carousel extends PureComponent {
|
|
|
1059
1055
|
this._snapToItem(positionIndex, animated, fireCallback);
|
|
1060
1056
|
}
|
|
1061
1057
|
|
|
1062
|
-
snapToNext(animated = true, fireCallback = true) {
|
|
1058
|
+
snapToNext (animated = true, fireCallback = true) {
|
|
1063
1059
|
const itemsLength = this._getCustomDataLength();
|
|
1064
1060
|
|
|
1065
1061
|
let newIndex = this._activeItem + 1;
|
|
@@ -1072,7 +1068,7 @@ export default class Carousel extends PureComponent {
|
|
|
1072
1068
|
this._snapToItem(newIndex, animated, fireCallback);
|
|
1073
1069
|
}
|
|
1074
1070
|
|
|
1075
|
-
snapToPrev(animated = true, fireCallback = true) {
|
|
1071
|
+
snapToPrev (animated = true, fireCallback = true) {
|
|
1076
1072
|
const itemsLength = this._getCustomDataLength();
|
|
1077
1073
|
|
|
1078
1074
|
let newIndex = this._activeItem - 1;
|
|
@@ -1086,7 +1082,7 @@ export default class Carousel extends PureComponent {
|
|
|
1086
1082
|
}
|
|
1087
1083
|
|
|
1088
1084
|
// https://github.com/facebook/react-native/issues/1831#issuecomment-231069668
|
|
1089
|
-
triggerRenderingHack(offset) {
|
|
1085
|
+
triggerRenderingHack (offset) {
|
|
1090
1086
|
// Avoid messing with user scroll
|
|
1091
1087
|
if (Date.now() - this._lastScrollDate < 500) {
|
|
1092
1088
|
return;
|
|
@@ -1101,22 +1097,23 @@ export default class Carousel extends PureComponent {
|
|
|
1101
1097
|
this._scrollTo(scrollPosition + scrollOffset, false);
|
|
1102
1098
|
}
|
|
1103
1099
|
|
|
1104
|
-
_getSlideInterpolatedStyle(index, animatedValue) {
|
|
1100
|
+
_getSlideInterpolatedStyle (index, animatedValue) {
|
|
1105
1101
|
const { layoutCardOffset, slideInterpolatedStyle } = this.props;
|
|
1106
1102
|
|
|
1107
1103
|
if (slideInterpolatedStyle) {
|
|
1108
1104
|
return slideInterpolatedStyle(index, animatedValue, this.props);
|
|
1109
|
-
} if (this._shouldUseTinderLayout()) {
|
|
1105
|
+
} else if (this._shouldUseTinderLayout()) {
|
|
1110
1106
|
return tinderAnimatedStyles(index, animatedValue, this.props, layoutCardOffset);
|
|
1111
|
-
} if (this._shouldUseStackLayout()) {
|
|
1107
|
+
} else if (this._shouldUseStackLayout()) {
|
|
1112
1108
|
return stackAnimatedStyles(index, animatedValue, this.props, layoutCardOffset);
|
|
1113
|
-
} if (this._shouldUseShiftLayout()) {
|
|
1109
|
+
} else if (this._shouldUseShiftLayout()) {
|
|
1114
1110
|
return shiftAnimatedStyles(index, animatedValue, this.props);
|
|
1111
|
+
} else {
|
|
1112
|
+
return defaultAnimatedStyles(index, animatedValue, this.props);
|
|
1115
1113
|
}
|
|
1116
|
-
return defaultAnimatedStyles(index, animatedValue, this.props);
|
|
1117
1114
|
}
|
|
1118
1115
|
|
|
1119
|
-
_renderItem({ item, index }) {
|
|
1116
|
+
_renderItem ({ item, index }) {
|
|
1120
1117
|
const { interpolators } = this.state;
|
|
1121
1118
|
const {
|
|
1122
1119
|
hasParallaxImages,
|
|
@@ -1127,8 +1124,7 @@ export default class Carousel extends PureComponent {
|
|
|
1127
1124
|
sliderHeight,
|
|
1128
1125
|
sliderWidth,
|
|
1129
1126
|
slideStyle,
|
|
1130
|
-
vertical
|
|
1131
|
-
isCustomScrollWidth
|
|
1127
|
+
vertical
|
|
1132
1128
|
} = this.props;
|
|
1133
1129
|
|
|
1134
1130
|
const animatedValue = interpolators && interpolators[index];
|
|
@@ -1138,7 +1134,7 @@ export default class Carousel extends PureComponent {
|
|
|
1138
1134
|
}
|
|
1139
1135
|
|
|
1140
1136
|
const animate = this._shouldAnimateSlides();
|
|
1141
|
-
const
|
|
1137
|
+
const Component = animate ? Animated.View : View;
|
|
1142
1138
|
const animatedStyle = animate ? this._getSlideInterpolatedStyle(index, animatedValue) : {};
|
|
1143
1139
|
|
|
1144
1140
|
const parallaxProps = hasParallaxImages ? {
|
|
@@ -1151,24 +1147,19 @@ export default class Carousel extends PureComponent {
|
|
|
1151
1147
|
itemHeight
|
|
1152
1148
|
} : undefined;
|
|
1153
1149
|
|
|
1150
|
+
const mainDimension = vertical ? { height: itemHeight } : { width: itemWidth };
|
|
1154
1151
|
const specificProps = this._needsScrollView() ? {
|
|
1155
1152
|
key: keyExtractor ? keyExtractor(item, index) : this._getKeyExtractor(item, index)
|
|
1156
1153
|
} : {};
|
|
1157
|
-
|
|
1154
|
+
|
|
1158
1155
|
return (
|
|
1159
|
-
<
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
{...specificProps}
|
|
1163
|
-
>
|
|
1164
|
-
{renderItem({
|
|
1165
|
-
item, index, realIndex: this._getDataIndex(index), activeIndex: this._getDataIndex(this._activeItem)
|
|
1166
|
-
}, parallaxProps)}
|
|
1167
|
-
</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>
|
|
1168
1159
|
);
|
|
1169
1160
|
}
|
|
1170
1161
|
|
|
1171
|
-
_getComponentOverridableProps() {
|
|
1162
|
+
_getComponentOverridableProps () {
|
|
1172
1163
|
const {
|
|
1173
1164
|
enableMomentum,
|
|
1174
1165
|
itemWidth,
|
|
@@ -1179,18 +1170,18 @@ export default class Carousel extends PureComponent {
|
|
|
1179
1170
|
vertical
|
|
1180
1171
|
} = this.props;
|
|
1181
1172
|
|
|
1182
|
-
const visibleItems = Math.ceil(vertical
|
|
1183
|
-
|
|
1184
|
-
|
|
1173
|
+
const visibleItems = Math.ceil(vertical ?
|
|
1174
|
+
sliderHeight / itemHeight :
|
|
1175
|
+
sliderWidth / itemWidth) + 1;
|
|
1185
1176
|
const initialNumPerSide = this._enableLoop() ? loopClonesPerSide : 2;
|
|
1186
1177
|
const initialNumToRender = visibleItems + (initialNumPerSide * 2);
|
|
1187
1178
|
const maxToRenderPerBatch = 1 + (initialNumToRender * 2);
|
|
1188
1179
|
const windowSize = maxToRenderPerBatch;
|
|
1189
1180
|
|
|
1190
1181
|
const specificProps = !this._needsScrollView() ? {
|
|
1191
|
-
initialNumToRender,
|
|
1192
|
-
maxToRenderPerBatch,
|
|
1193
|
-
windowSize
|
|
1182
|
+
initialNumToRender: initialNumToRender,
|
|
1183
|
+
maxToRenderPerBatch: maxToRenderPerBatch,
|
|
1184
|
+
windowSize: windowSize
|
|
1194
1185
|
// updateCellsBatchingPeriod
|
|
1195
1186
|
} : {};
|
|
1196
1187
|
|
|
@@ -1205,12 +1196,12 @@ export default class Carousel extends PureComponent {
|
|
|
1205
1196
|
scrollsToTop: false,
|
|
1206
1197
|
removeClippedSubviews: !this._needsScrollView(),
|
|
1207
1198
|
inverted: this._needsRTLAdaptations(),
|
|
1208
|
-
|
|
1199
|
+
renderToHardwareTextureAndroid: true,
|
|
1209
1200
|
...specificProps
|
|
1210
1201
|
};
|
|
1211
1202
|
}
|
|
1212
1203
|
|
|
1213
|
-
_getComponentStaticProps() {
|
|
1204
|
+
_getComponentStaticProps () {
|
|
1214
1205
|
const { hideCarousel } = this.state;
|
|
1215
1206
|
const {
|
|
1216
1207
|
containerCustomStyle,
|
|
@@ -1225,11 +1216,11 @@ export default class Carousel extends PureComponent {
|
|
|
1225
1216
|
const containerStyle = [
|
|
1226
1217
|
containerCustomStyle || style || {},
|
|
1227
1218
|
hideCarousel ? { opacity: 0 } : {},
|
|
1228
|
-
vertical
|
|
1229
|
-
|
|
1219
|
+
vertical ?
|
|
1220
|
+
{ height: sliderHeight, flexDirection: 'column' } :
|
|
1230
1221
|
// LTR hack; see https://github.com/facebook/react-native/issues/11960
|
|
1231
1222
|
// and https://github.com/facebook/react-native/issues/13100#issuecomment-328986423
|
|
1232
|
-
|
|
1223
|
+
{ width: sliderWidth, flexDirection: this._needsRTLAdaptations() ? 'row-reverse' : 'row' }
|
|
1233
1224
|
];
|
|
1234
1225
|
const contentContainerStyle = [
|
|
1235
1226
|
vertical ? {
|
|
@@ -1246,15 +1237,14 @@ export default class Carousel extends PureComponent {
|
|
|
1246
1237
|
// extraData: this.state,
|
|
1247
1238
|
renderItem: this._renderItem,
|
|
1248
1239
|
numColumns: 1,
|
|
1249
|
-
getItemLayout: undefined, // see #193
|
|
1250
|
-
initialScrollIndex: undefined, // see #193
|
|
1251
1240
|
keyExtractor: keyExtractor || this._getKeyExtractor
|
|
1252
1241
|
} : {};
|
|
1242
|
+
|
|
1253
1243
|
return {
|
|
1254
|
-
ref:
|
|
1244
|
+
ref: c => this._carouselRef = c,
|
|
1255
1245
|
data: this._getCustomData(),
|
|
1256
1246
|
style: containerStyle,
|
|
1257
|
-
contentContainerStyle,
|
|
1247
|
+
contentContainerStyle: contentContainerStyle,
|
|
1258
1248
|
horizontal: !vertical,
|
|
1259
1249
|
scrollEventThrottle: 1,
|
|
1260
1250
|
onScroll: this._onScrollHandler,
|
|
@@ -1270,7 +1260,7 @@ export default class Carousel extends PureComponent {
|
|
|
1270
1260
|
};
|
|
1271
1261
|
}
|
|
1272
1262
|
|
|
1273
|
-
render() {
|
|
1263
|
+
render () {
|
|
1274
1264
|
const { data, renderItem, useScrollView } = this.props;
|
|
1275
1265
|
|
|
1276
1266
|
if (!data || !renderItem) {
|
|
@@ -1283,18 +1273,18 @@ export default class Carousel extends PureComponent {
|
|
|
1283
1273
|
...this._getComponentStaticProps()
|
|
1284
1274
|
};
|
|
1285
1275
|
|
|
1286
|
-
const ScrollViewComponent = typeof useScrollView === 'function' ? useScrollView :
|
|
1276
|
+
const ScrollViewComponent = typeof useScrollView === 'function' ? useScrollView : Animated.ScrollView
|
|
1287
1277
|
|
|
1288
1278
|
return this._needsScrollView() ? (
|
|
1289
1279
|
<ScrollViewComponent {...props}>
|
|
1290
1280
|
{
|
|
1291
|
-
this._getCustomData().map((item, index) =>
|
|
1292
|
-
item, index, realIndex: this._getDataIndex(index), activeIndex: this._getDataIndex(this._activeItem)
|
|
1293
|
-
})
|
|
1281
|
+
this._getCustomData().map((item, index) => {
|
|
1282
|
+
return this._renderItem({ item, index, realIndex: this._getDataIndex(index), activeIndex: this._getDataIndex(this._activeItem) });
|
|
1283
|
+
})
|
|
1294
1284
|
}
|
|
1295
1285
|
</ScrollViewComponent>
|
|
1296
1286
|
) : (
|
|
1297
|
-
<
|
|
1287
|
+
<Animated.FlatList {...props} />
|
|
1298
1288
|
);
|
|
1299
1289
|
}
|
|
1300
1290
|
}
|
|
@@ -1372,7 +1362,7 @@ Carousel.defaultProps = {
|
|
|
1372
1362
|
slideStyle: {},
|
|
1373
1363
|
shouldOptimizeUpdates: true,
|
|
1374
1364
|
swipeThreshold: 20,
|
|
1375
|
-
useScrollView: !
|
|
1365
|
+
useScrollView: !Animated.FlatList,
|
|
1376
1366
|
vertical: false,
|
|
1377
1367
|
showsPagination: true,
|
|
1378
1368
|
isCustomScrollWidth: false,
|