react-native-reanimated#interpolate TypeScript Examples
The following examples show how to use
react-native-reanimated#interpolate.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts From react-native-wagmi-charts with MIT License | 7 votes |
export function getY({
value,
domain,
maxHeight,
}: {
value: number;
domain: TDomain;
maxHeight: number;
}) {
'worklet';
return interpolate(value, domain, [maxHeight, 0], Extrapolate.CLAMP);
}
Example #2
Source File: utils.ts From react-native-wagmi-charts with MIT License | 7 votes |
export function getHeight({
value,
domain,
maxHeight,
}: {
value: number;
domain: TDomain;
maxHeight: number;
}) {
'worklet';
return interpolate(
value,
[0, Math.max(...domain) - Math.min(...domain)],
[0, maxHeight],
Extrapolate.CLAMP
);
}
Example #3
Source File: utils.ts From react-native-wagmi-charts with MIT License | 7 votes |
export function getPrice({
y,
domain,
maxHeight,
}: {
y: number;
domain: TDomain;
maxHeight: number;
}) {
'worklet';
if (y === -1) return -1;
return interpolate(y, [0, maxHeight], domain.reverse(), Extrapolate.CLAMP);
}
Example #4
Source File: useInit.ts From react-native-gallery-toolkit with MIT License | 6 votes |
usedWorklets = {
withTiming,
withSpring,
bezier: Easing.bezier,
interpolate,
withDecay,
useAnimatedGestureHandler,
...usedVectors,
} as { [key: string]: any }
Example #5
Source File: CircularProgress.tsx From tic-tac-toe-app with MIT License | 6 votes |
CircularProgress: React.FC<PropTypes> = ({ progress, size = 64 }) => {
const strokeWidth = size * (1 / 2);
const radius = (size - strokeWidth) / 2;
const circumference = radius * 2 * Math.PI;
const theme = useSelector(selectTheme);
const α = interpolate(progress, {
inputRange: [0, 1],
outputRange: [0, -Math.PI * 2],
});
const strokeDashoffset = multiply(α, radius);
return (
<View style={{ transform: [{ rotate: '-90deg' }] }}>
<Svg width={size} height={size}>
<AnimatedCircle
stroke={colors[theme].main}
fill="none"
cx={size / 2}
cy={size / 2}
r={radius}
{...{ strokeWidth, strokeDashoffset }}
strokeDasharray={`${circumference} ${circumference}`}
/>
</Svg>
</View>
);
}
Example #6
Source File: getHeight.ts From react-native-wagmi-charts with MIT License | 6 votes |
export function getHeight({
value,
domain,
maxHeight,
}: {
value: number;
domain: TDomain;
maxHeight: number;
}) {
'worklet';
return interpolate(
value,
[0, Math.max(...domain) - Math.min(...domain)],
[0, maxHeight],
Extrapolate.CLAMP
);
}
Example #7
Source File: getPrice.ts From react-native-wagmi-charts with MIT License | 6 votes |
export function getPrice({
y,
domain,
maxHeight,
}: {
y: number;
domain: TDomain;
maxHeight: number;
}) {
'worklet';
if (y === -1) return -1;
return interpolate(y, [0, maxHeight], domain.reverse(), Extrapolate.CLAMP);
}
Example #8
Source File: getY.ts From react-native-wagmi-charts with MIT License | 6 votes |
export function getY({
value,
domain,
maxHeight,
}: {
value: number;
domain: TDomain;
maxHeight: number;
}) {
'worklet';
return interpolate(value, domain, [maxHeight, 0], Extrapolate.CLAMP);
}
Example #9
Source File: BasicSticky.tsx From react-native-sticky-item with MIT License | 5 votes |
BasicSticky = ({
x,
threshold,
itemWidth,
itemHeight,
stickyItemWidth,
stickyItemHeight,
separatorSize,
isRTL,
}: StickyItemContentProps) => {
//#region plus
const animatedPlusScale = interpolate(x, {
inputRange: [0, threshold],
outputRange: [0, 1],
extrapolate: Extrapolate.CLAMP,
});
const plusStyle = [
styles.plus,
{
width: stickyItemWidth,
height: stickyItemHeight,
[isRTL ? 'right' : 'left']: '50%',
transform: transformOrigin(
{ x: 0, y: 0 },
{
translateX: interpolate(x, {
inputRange: [separatorSize, threshold],
outputRange: [
(stickyItemWidth / 2) * (isRTL ? 1 : -1),
(itemWidth / 2 - stickyItemWidth) * (isRTL ? -1 : 1),
],
extrapolate: Extrapolate.CLAMP,
}),
translateY: itemHeight / 2 - stickyItemHeight / 2,
scale: animatedPlusScale,
}
) as Animated.AnimatedTransform,
},
];
//#endregion
//#region text
const animatedTextOpacity = interpolate(x, {
inputRange: [0, threshold * 0.6],
outputRange: [1, 0],
extrapolate: Extrapolate.CLAMP,
});
const textStyle = [
styles.text,
{
opacity: animatedTextOpacity,
paddingHorizontal: separatorSize,
lineHeight: itemHeight,
transform: [
{
translateY: 0,
},
] as Animated.AnimatedTransform,
},
];
//#endregion
return (
<>
<Animated.View style={plusStyle}>
<PlusSVG />
</Animated.View>
<Animated.Text style={textStyle}>
{isRTL ? 'להוסיף' : 'Add'}
</Animated.Text>
</>
);
}
Example #10
Source File: ScalableImageExample.tsx From react-native-gallery-toolkit with MIT License | 5 votes |
export default function StandaloneGalleryBasicScreen() {
const { controlsStyles, setControlsHidden } = useControls();
const opacity = useSharedValue(0);
const overlayStyles = useAnimatedStyle(() => {
return {
opacity: opacity.value,
backgroundColor: 'black',
};
});
const onScale = useWorkletCallback((scale: number) => {
opacity.value = interpolate(
scale,
[1, 2],
[0, 0.3],
Extrapolate.CLAMP,
);
}, []);
const onGestureStartCallback = () => {
StatusBar.setHidden(true);
};
const onGestureReleaseCallback = () => {
StatusBar.setHidden(false);
};
const onGestureStart = useWorkletCallback(() => {
setControlsHidden(true);
runOnJS(onGestureStartCallback)();
});
const onGestureRelease = useWorkletCallback(() => {
setControlsHidden(false);
runOnJS(onGestureReleaseCallback)();
});
return (
<View style={{ flex: 1, backgroundColor: 'transparent' }}>
<Animated.View
pointerEvents="none"
style={[StyleSheet.absoluteFill, overlayStyles]}
/>
<View
style={{
zIndex: 0,
flex: 1,
justifyContent: 'center',
}}
>
<ScalableImage
width={image.width}
height={image.height}
source={image.uri}
onScale={onScale}
onGestureStart={onGestureStart}
onGestureRelease={onGestureRelease}
/>
</View>
<Animated.View style={controlsStyles}>
<DetachedHeader.Container>
<DetachedHeader />
</DetachedHeader.Container>
</Animated.View>
</View>
);
}
Example #11
Source File: HorizontalFlatListExample.tsx From react-native-scroll-bottom-sheet with MIT License | 5 votes |
HorizontalFlatListExample: React.FC<Props> = ({ navigation }) => {
const bottomSheetRef = React.useRef<ScrollBottomSheet<any> | null>(null);
const animatedPosition = React.useRef(new Value(0));
const opacity = interpolate(animatedPosition.current, {
inputRange: [0, 1],
outputRange: [0, 0.75],
extrapolate: Extrapolate.CLAMP,
});
const renderRow = React.useCallback(
({ index }) => <Carousel index={index} />,
[]
);
return (
<View style={styles.container}>
<MapView
style={StyleSheet.absoluteFillObject}
initialRegion={initialRegion}
/>
<Animated.View
pointerEvents="box-none"
style={[
StyleSheet.absoluteFillObject,
{ backgroundColor: 'black', opacity },
]}
/>
<View style={StyleSheet.absoluteFillObject} pointerEvents="box-none">
<TouchableRipple
style={[styles.iconContainer, { right: 16 }]}
onPress={() => {
bottomSheetRef.current?.snapTo(2);
}}
borderless
>
<MaterialCommunityIcons
name="close"
size={32}
color="white"
style={styles.icon}
/>
</TouchableRipple>
{Platform.OS === 'ios' && (
<TouchableRipple
style={[styles.iconContainer, { left: 16 }]}
onPress={() => {
navigation.goBack();
}}
borderless
>
<Ionicons
name="ios-arrow-back"
size={32}
color="white"
style={styles.icon}
/>
</TouchableRipple>
)}
</View>
<ScrollBottomSheet<string>
ref={bottomSheetRef}
componentType="FlatList"
topInset={24}
animatedPosition={animatedPosition.current}
snapPoints={snapPointsFromTop}
initialSnapIndex={2}
renderHandle={() => <Handle />}
keyExtractor={i => `row-${i}`}
initialNumToRender={5}
contentContainerStyle={styles.contentContainerStyle}
data={Array.from({ length: 100 }).map((_, i) => String(i))}
renderItem={renderRow}
/>
</View>
);
}
Example #12
Source File: FlatListPageIndicator.tsx From nyxo-app with GNU General Public License v3.0 | 5 votes |
ExpandingDot: FC<Props> = ({
scrollX,
data,
dotStyle,
style,
inActiveDotOpacity,
expandingDotWidth,
width = WIDTH
}) => {
const defaultProps = {
inActiveDotOpacity: inActiveDotOpacity || 0.5,
expandingDotWidth: expandingDotWidth || 20,
dotWidth: (dotStyle?.width as number) || 10
}
return (
<Container style={style}>
{data.map((_, index: number) => {
const inputRange = [
(index - 1) * width,
index * width,
(index + 1) * width
]
const opacity = interpolate(scrollX, {
inputRange,
outputRange: [
defaultProps.inActiveDotOpacity,
1,
defaultProps.inActiveDotOpacity
],
extrapolateRight: Animated.Extrapolate.CLAMP,
extrapolateLeft: Animated.Extrapolate.CLAMP
})
const expand = interpolate(scrollX, {
inputRange,
outputRange: [
defaultProps.dotWidth,
defaultProps.expandingDotWidth,
defaultProps.dotWidth
],
extrapolateRight: Animated.Extrapolate.CLAMP,
extrapolateLeft: Animated.Extrapolate.CLAMP
})
return (
<Dot
// eslint-disable-next-line react/no-array-index-key
key={`dot-${index}`}
style={[dotStyle, { width: expand }, { opacity }]}
/>
)
})}
</Container>
)
}
Example #13
Source File: WeekIntro.tsx From nyxo-app with GNU General Public License v3.0 | 5 votes |
WeekIntro: FC<Props> = ({
intro,
description,
habitCount,
lessonCount,
loading
}) => {
const animationValue = useValue(0)
const isLoading = useValue(loading ? 1 : 0)
useCode(
() =>
cond(eq(isLoading, 1), [
set(
animationValue,
loop({
duration: DEFAULT_DURATION,
easing: DEFAULT_EASING,
boomerang: true
})
)
]),
[isLoading, animationValue]
)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const animatedStyle: any = {
transform: [
{
translateX: interpolate(animationValue, {
inputRange: [0, 1],
outputRange: ['-100%', '100%']
})
}
]
}
return (
<Container>
<Card>
{loading ? (
<IntroSkeleton animatedStyle={animatedStyle} />
) : (
<Intro>{intro}</Intro>
)}
<Information>
{habitCount > 0 && (
<>
<HabitIcon />
<Habits variables={{ count: habitCount }}>
WEEK_VIEW.HABIT_COUNT
</Habits>
</>
)}
{lessonCount > 0 && (
<LessonIcon>
<LessonIcon />
<Habits variables={{ count: lessonCount }}>
WEEK_VIEW.LESSON_COUNT
</Habits>
</LessonIcon>
)}
</Information>
<Description secondary>
{description && <RichText content={description} />}
</Description>
</Card>
</Container>
)
}
Example #14
Source File: AnimatedHelper.ts From curved-bottom-navigation-bar with MIT License | 5 votes |
useInterpolate = (
progress: Animated.SharedValue<number>,
input: number[],
output: number[],
type?: Animated.Extrapolate
) => useDerivedValue(() => interpolate(progress.value, input, output, type))
Example #15
Source File: HabitCard.tsx From nyxo-app with GNU General Public License v3.0 | 4 votes |
HabitCard: FC<Props> = (props) => {
const ref = useRef<Swipeable>(null)
const dispatch = useAppDispatch()
const { habit } = props
const {
habit: { period, dayStreak = 0 }
} = props
const { color } = getIcon(period)
const completed = isCompletedToday(habit)
const toggleCompleted = () => {
dispatch(markTodayHabitAsCompleted(habit))
close()
}
const editHabit = () => {
dispatch(draftEditHabit(habit))
dispatch(toggleEditHabitModal())
}
const deleteHabit = () => {
dispatch(deleteHabitById(habit))
close()
}
const archiveHabit = () => {
dispatch(archiveHabitThunk(habit))
close()
}
const close = () => {
// eslint-disable-next-line no-unused-expressions
ref?.current?.close()
}
const renderLeftActions = (
progress: Animated.Value<number>,
dragX: Animated.Value<number>
) => {
const animation = interpolate(dragX, {
inputRange: [0, 100],
outputRange: [0, 1]
})
return (
<>
<ActionComplete
animation={animation}
direction="LEFT"
icon="archive"
buttonText="HABIT.ARCHIVE"
action={archiveHabit}
/>
<ActionComplete
animation={animation}
direction="LEFT"
icon="bin"
buttonText="HABIT.DELETE"
action={deleteHabit}
/>
</>
)
}
const renderRightActions = (
progress: Animated.Value<number>,
dragX: Animated.Value<number>
) => {
const animation = interpolate(dragX, {
inputRange: [-150, 0],
outputRange: [1, 0]
})
return (
<>
<ActionComplete
animation={animation}
direction="RIGHT"
icon="checkMark"
buttonText="HABIT.COMPLETE"
action={toggleCompleted}
/>
</>
)
}
return (
<Swipeable
ref={ref}
renderLeftActions={renderLeftActions}
renderRightActions={renderRightActions}>
<BorderlessButton onPress={editHabit}>
<Card>
<PeriodBarIndicator backgroundColor={color} />
<MiddleSector>
<PeriodIndicator accent={color}>
{`HABIT.EVERY_${period.toUpperCase()}`}
</PeriodIndicator>
<Separator />
<TitleHolder completedToday={completed}>{habit.title}</TitleHolder>
<Separator />
<DayStreakContainer>
<IconBold width={12} height={12} name="flame" fill="#adadad" />
<DayStreak>{dayStreak}</DayStreak>
</DayStreakContainer>
</MiddleSector>
<CheckIconHolder>
{completed && (
<IconBold
width={15}
height={15}
name="checkMark"
fill={colors.darkBlue}
/>
)}
</CheckIconHolder>
</Card>
</BorderlessButton>
</Swipeable>
)
}
Example #16
Source File: FacebookStickyStory.tsx From react-native-sticky-item with MIT License | 4 votes |
FacebookStickyStory = ({
x,
threshold,
itemWidth,
itemHeight,
stickyItemWidth,
separatorSize,
borderRadius,
isRTL,
theme = 'light',
}: StickyItemContentProps & FacebookStickyStoryProps) => {
const stickyItemX = itemWidth / 2 + (itemWidth / 2 - stickyItemWidth);
const stickyItemY = itemHeight / 2 - stickyItemWidth / 2;
const stickyItemWidthWithoutPadding = stickyItemWidth - separatorSize * 2;
const separatorSizeToStickyWidthScale = Math.min(
separatorSize / stickyItemWidth,
0.2
);
//#region thumbnail
const thumbnailWidth = itemWidth;
const thumbnailHeight = itemWidth;
const thumbnailTranslateX =
Math.abs(thumbnailWidth / 2 - (stickyItemX + stickyItemWidth / 2)) *
(isRTL ? -1 : 1);
const thumbnailTranslateY = Math.abs(
thumbnailHeight / 2 - (stickyItemY + stickyItemWidth / 2)
);
const thumbnailScale =
stickyItemWidth / itemWidth - separatorSizeToStickyWidthScale;
const animatedThumbnailScale = interpolate(x, {
inputRange: [separatorSize, threshold],
outputRange: [1, thumbnailScale],
extrapolate: Extrapolate.CLAMP,
});
const animatedThumbnailTranslateX = interpolate(x, {
inputRange: [separatorSize, threshold],
outputRange: [0, thumbnailTranslateX],
extrapolate: Extrapolate.CLAMP,
});
const animatedThumbnailTranslateY = interpolate(x, {
inputRange: [separatorSize, threshold],
outputRange: [0, thumbnailTranslateY],
extrapolate: Extrapolate.CLAMP,
});
const animatedThumbnailBorderRadius = interpolate(x, {
inputRange: [separatorSize, threshold],
outputRange: [
borderRadius,
stickyItemWidth * (separatorSizeToStickyWidthScale + 1),
],
extrapolate: Extrapolate.CLAMP,
});
const thumbnailStyle = [
{
backgroundColor: theme === 'light' ? 'black' : 'white',
width: thumbnailWidth,
height: thumbnailHeight,
borderRadius: animatedThumbnailBorderRadius,
transform: [
{ translateX: (thumbnailWidth / 2) * -1 },
{ translateY: (thumbnailHeight / 2) * -1 },
{ translateX: animatedThumbnailTranslateX },
{ translateY: animatedThumbnailTranslateY },
{ translateX: thumbnailWidth / 2 },
{ translateY: thumbnailHeight / 2 },
{ scale: animatedThumbnailScale },
],
},
];
//#endregion
//#region add icon
const addIconWidth = 30;
const addIconHeight = 30;
const addIconPosition = findPointOnCircle({
radius: stickyItemWidthWithoutPadding / 2,
degrees: isRTL ? 135 : 45,
});
const animatedAddIconTranslateX = interpolate(x, {
inputRange: [separatorSize, threshold],
outputRange: [0, addIconPosition.x],
extrapolate: Extrapolate.CLAMP,
});
const animatedAddIconTranslateY = interpolate(x, {
inputRange: [separatorSize, threshold],
outputRange: [thumbnailHeight / 2, addIconPosition.y],
extrapolate: Extrapolate.CLAMP,
});
const animatedAddIconScale = interpolate(x, {
inputRange: [separatorSize, threshold],
outputRange: [1, 0.33],
extrapolate: Extrapolate.CLAMP,
});
const animatedAddIconBorderWidth = interpolate(x, {
inputRange: [separatorSize, threshold],
outputRange: [3, 2],
extrapolate: Extrapolate.CLAMP,
});
const addIconStyle = [
styles.addIcon,
{
width: addIconWidth,
height: addIconHeight,
borderRadius: addIconWidth,
borderWidth: animatedAddIconBorderWidth,
transform: [
{ translateX: (addIconWidth / 2) * -1 },
{ translateY: (addIconHeight / 2) * -1 },
{ translateX: thumbnailWidth / 2 },
{ translateY: thumbnailHeight / 2 },
{ translateX: animatedThumbnailTranslateX },
{ translateY: animatedThumbnailTranslateY },
{ translateX: animatedAddIconTranslateX },
{ translateY: animatedAddIconTranslateY },
{ scale: animatedAddIconScale },
],
},
];
//#endregion
//#region text
const animatedTextOpacity = interpolate(x, {
inputRange: [separatorSize, threshold * 0.6],
outputRange: [1, 0],
extrapolate: Extrapolate.CLAMP,
});
const animatedTextTranslateY = interpolate(x, {
inputRange: [separatorSize, threshold * 0.6],
outputRange: [itemHeight / 2 + itemHeight / 4, itemHeight / 2],
extrapolate: Extrapolate.CLAMP,
});
const textStyle = [
styles.text,
{
color: theme === 'light' ? 'black' : 'white',
opacity: animatedTextOpacity,
paddingHorizontal: separatorSize * 2,
transform: [
{
translateY: animatedTextTranslateY,
},
] as Animated.AnimatedTransform,
},
];
//#endregion
return (
<>
<Animated.View style={thumbnailStyle} />
<Animated.Text style={textStyle}>
{isRTL ? `إضافة إلى قصتك` : `Create a story`}
</Animated.Text>
<Animated.View style={addIconStyle} />
</>
);
}
Example #17
Source File: SectionListExample.tsx From react-native-scroll-bottom-sheet with MIT License | 4 votes |
SectionListExample: React.FC<Props> = () => {
const snapPointsFromTop = [96, '45%', windowHeight - 264];
const animatedPosition = React.useRef(new Value(0.5));
const handleLeftRotate = concat(
interpolate(animatedPosition.current, {
inputRange: [0, 0.4, 1],
outputRange: [25, 0, 0],
extrapolate: Extrapolate.CLAMP,
}),
'deg'
);
const handleRightRotate = concat(
interpolate(animatedPosition.current, {
inputRange: [0, 0.4, 1],
outputRange: [-25, 0, 0],
extrapolate: Extrapolate.CLAMP,
}),
'deg'
);
const cardScale = interpolate(animatedPosition.current, {
inputRange: [0, 0.6, 1],
outputRange: [1, 1, 0.9],
extrapolate: Extrapolate.CLAMP,
});
const renderSectionHeader = React.useCallback(
({ section }) => (
<View style={styles.section}>
<Text>{section.title}</Text>
</View>
),
[]
);
const renderItem = React.useCallback(
({ item }) => <Transaction {...item} />,
[]
);
return (
<View style={styles.container}>
<View style={styles.balanceContainer}>
<Text style={styles.poundSign}>£</Text>
<Text style={styles.balance}>4,345</Text>
</View>
<ProgressBar
style={styles.progressBar}
progress={0.8}
color={Colors.green600}
/>
<Animated.Image
source={require('../assets/card-front.png')}
style={[styles.card, { transform: [{ scale: cardScale }] }]}
/>
<View style={styles.row}>
<View>
<View style={styles.action}>
<FontAwesome5 name="credit-card" size={24} color="black" />
</View>
<Text style={{ textAlign: 'center' }}>Account</Text>
</View>
<View>
<View style={styles.action}>
<FontAwesome5 name="eye" size={24} color="black" />
</View>
<Text style={{ textAlign: 'center' }}>Pin</Text>
</View>
<View>
<View style={styles.action}>
<Ionicons name="md-snow" size={24} color="black" />
</View>
<Text style={{ textAlign: 'center' }}>Freeze</Text>
</View>
<View>
<View style={styles.action}>
<FontAwesome5 name="plus" size={24} color="black" />
</View>
<Text style={{ textAlign: 'center' }}>Top up</Text>
</View>
</View>
<ScrollBottomSheet<ListItemData>
enableOverScroll
removeClippedSubviews={Platform.OS === 'android' && sections.length > 0}
componentType="SectionList"
topInset={statusBarHeight + navBarHeight}
animatedPosition={animatedPosition.current}
snapPoints={snapPointsFromTop}
initialSnapIndex={1}
animationConfig={{
easing: Easing.inOut(Easing.linear),
}}
renderHandle={() => (
<Handle style={{ paddingVertical: 20, backgroundColor: '#F3F4F9' }}>
<Animated.View
style={[
styles.handle,
{
left: windowWidth / 2 - 20,
transform: [{ rotate: handleLeftRotate }],
},
]}
/>
<Animated.View
style={[
styles.handle,
{
right: windowWidth / 2 - 20,
transform: [{ rotate: handleRightRotate }],
},
]}
/>
</Handle>
)}
contentContainerStyle={styles.contentContainerStyle}
stickySectionHeadersEnabled
sections={sections}
keyExtractor={i => i.id}
renderSectionHeader={renderSectionHeader}
renderItem={renderItem}
/>
</View>
);
}
Example #18
Source File: InstagramFeed.tsx From react-native-gallery-toolkit with MIT License | 4 votes |
function RenderItem({
index: _index,
activeItemIndex,
item: { images, name },
setControlsHidden,
scrollViewRef,
}: RenderItemProps) {
const opacity = useSharedValue(0);
const backgroundScale = useSharedValue(0);
const activeIndexInPager = useSharedValue(0);
const normalizedImages = useMemo(
() =>
images.map((item) => {
const { targetWidth, targetHeight } = normalizeDimensions(
item,
);
return {
...item,
width: targetWidth,
height: targetHeight,
};
}),
[images],
);
const onScale = useWorkletCallback((scale: number) => {
opacity.value = interpolate(
scale,
[1, 2],
[0, 0.7],
Extrapolate.CLAMP,
);
backgroundScale.value = interpolate(
scale,
[1, 1.01, 2],
[0, 4, 5],
Extrapolate.CLAMP,
);
}, []);
const onGestureStart = useWorkletCallback(() => {
setControlsHidden(true);
runOnJS(StatusBar.setHidden)(true);
activeItemIndex.value = _index;
}, []);
const onGestureRelease = useWorkletCallback(() => {
//delay for smooth hiding background opacity
activeItemIndex.value = withDelay(200, withTiming(-1));
setControlsHidden(false);
runOnJS(StatusBar.setHidden)(false);
}, []);
const overlayStyles = useAnimatedStyle(() => {
return {
opacity: opacity.value,
transform: [
{
scale: backgroundScale.value,
},
],
};
});
const keyExtractor = useCallback(
({ id }: { id: string }) => id,
[],
);
const canvasHeight = useMemo(
() => Math.max(...normalizedImages.map((item) => item.height)),
[normalizedImages],
);
const renderPage = useCallback(({ item, pagerRefs }: RenderPageProps<SimpleGalleryItemType>) => {
return (
<ScalableImage
outerGestureHandlerRefs={[...pagerRefs, scrollViewRef]}
source={item.uri}
width={item.width}
height={item.height}
onScale={onScale}
onGestureStart={onGestureStart}
onGestureRelease={onGestureRelease}
/>
);
}, []);
const onIndexChangeWorklet = useWorkletCallback((nextIndex: number) => {
activeIndexInPager.value = nextIndex;
}, []);
const content = (() => {
if (images.length === 1) {
return (
<ScalableImage
source={images[0].uri}
width={images[0].width}
height={images[0].height}
onScale={onScale}
outerGestureHandlerRefs={[scrollViewRef]}
onGestureStart={onGestureStart}
onGestureRelease={onGestureRelease}
/>
);
} else {
return (
<>
<Pager
pages={images}
totalCount={images.length}
keyExtractor={keyExtractor}
initialIndex={0}
width={width}
gutterWidth={0}
outerGestureHandlerRefs={[scrollViewRef]}
verticallyEnabled={false}
// @ts-expect-error
renderPage={renderPage}
onIndexChange={onIndexChangeWorklet}
/>
<Pagination
length={images.length}
activeIndexInPager={activeIndexInPager}
/>
</>
);
}
})();
return (
<Animated.View style={s.itemContainer}>
<Header uri={images[0].uri} name={name} />
<Animated.View
pointerEvents="none"
style={[s.overlay, overlayStyles]}
/>
<View style={[s.itemPager, { height: canvasHeight }]}>
{content}
</View>
<Footer />
</Animated.View>
);
}
Example #19
Source File: Bar.tsx From expo-progress with MIT License | 4 votes |
function ProgressBar({
isIndeterminate = false,
duration = isIndeterminate ? 1000 : 500,
isAnimated = false,
progress = isIndeterminate ? 0.5 : 0,
height = 7,
borderRadius = height * 0.5,
// Default iOS blue
color = '#007aff',
trackColor = 'transparent',
style,
trackImage,
progressImage,
}: ProgressBarProps) {
const [width, setWidth] = React.useState(0);
const progressValue = useValue(isAnimated ? 0 : progress);
const indeterminateValue = useValue(0);
const animatedWidth = interpolate(
clamp(progressValue, minProgress, maxProgress),
{
inputRange: [minProgress, maxProgress],
outputRange: [0, width],
extrapolate: Extrapolate.CLAMP,
}
);
useCode(() => {
if (isAnimated) {
return set(
progressValue,
timing({
from: progressValue,
to: progress,
duration,
})
);
} else {
return set(progressValue, progress);
}
}, [progress]);
useCode(() => {
if (isIndeterminate) {
const loopingIndeterminateValue = loop({
autoStart: true,
boomerang: false,
duration,
});
return set(indeterminateValue, loopingIndeterminateValue);
}
const animatedIndeterminateValue = timing({
from: indeterminateValue,
to: 0,
});
return set(indeterminateValue, animatedIndeterminateValue);
}, [isIndeterminate]);
// todo: web has a bug where the reanimated Animated.View style is not updating unless this is an animated value.
let translateX: Node<number> | number = useValue(0);
if (isIndeterminate) {
translateX = interpolate(indeterminateValue, {
inputRange: [0, 1],
outputRange: [multiply(-1, animatedWidth), width],
});
}
return (
<ImageBackground
onLayout={(e: LayoutChangeEvent) => {
setWidth(e.nativeEvent.layout.width);
}}
resizeMode={'stretch'}
style={[
styles.container,
{
height,
borderRadius,
backgroundColor: trackColor,
},
style,
]}
// @ts-ignore
source={trackImage}
>
<Animated.Image
style={[
styles.bar,
{
width: animatedWidth,
transform: [
{
translateX,
},
],
backgroundColor: color,
borderRadius,
},
]}
// @ts-ignore
source={progressImage}
/>
</ImageBackground>
);
}