Skip to content

Commit

Permalink
fix: sticky item width calculation (#13)
Browse files Browse the repository at this point in the history
* chore: updated the sticky size calculation

* chore: updated examples

* chore: updated custom separator example
  • Loading branch information
gorhom authored Jun 1, 2020
1 parent 7700731 commit e5b246b
Show file tree
Hide file tree
Showing 14 changed files with 262 additions and 192 deletions.
28 changes: 15 additions & 13 deletions example/src/components/basic-sticky/BasicSticky.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import React from 'react';
import Animated, { interpolate, Extrapolate } from 'react-native-reanimated';
import { transformOrigin } from 'react-native-redash';
import type { StickyItemContentProps } from '@gorhom/sticky-item';
import PlusSVG from '../../icons/PlusSVG';
import { styles } from './styles';

const BasicSticky = ({
Expand All @@ -15,29 +15,29 @@ const BasicSticky = ({
separatorSize,
isRTL,
}: StickyItemContentProps) => {
const stickyScaleX = stickyItemWidth / itemWidth;
const stickyScaleY = stickyItemHeight / itemHeight;
const scaledSpaceX = (separatorSize * 2) / itemWidth;
const scaledSpaceY = (separatorSize * 2) / itemHeight;
const containerScaleX = stickyScaleX + scaledSpaceX;

//#region plus
const animatedPlusScale = interpolate(x, {
inputRange: [0, threshold * 0.6],
inputRange: [0, threshold],
outputRange: [0, 1],
extrapolate: Extrapolate.CLAMP,
});
const plusStyle = [
styles.plus,
{
width: stickyItemWidth,
lineHeight: stickyItemHeight,
[isRTL ? 'left' : 'right']: 0,
paddingHorizontal: separatorSize,
height: stickyItemHeight,
[isRTL ? 'right' : 'left']: '50%',
transform: transformOrigin(
{ x: 0, y: 0 },
{
translateX: isRTL ? separatorSize : -separatorSize,
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,
}
Expand Down Expand Up @@ -69,7 +69,9 @@ const BasicSticky = ({

return (
<>
<Animated.Text style={plusStyle}>+</Animated.Text>
<Animated.View style={plusStyle}>
<PlusSVG />
</Animated.View>
<Animated.Text style={textStyle}>
{isRTL ? 'להוסיף' : 'Add'}
</Animated.Text>
Expand Down
8 changes: 3 additions & 5 deletions example/src/components/basic-sticky/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({
plus: {
position: 'absolute',
textTransform: 'uppercase',
textAlign: 'center',
fontSize: 34,
fontWeight: '500',
color: 'white',
alignContent: 'center',
justifyContent: 'center',
alignItems: 'center',
},
text: {
position: 'absolute',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import React from 'react';
import Animated, { interpolate, Extrapolate } from 'react-native-reanimated';
import { transformOrigin } from 'react-native-redash';
Expand All @@ -11,40 +10,42 @@ const FacebookStickyStory = ({
itemWidth,
itemHeight,
stickyItemWidth,
stickyItemHeight,
separatorSize,
borderRadius,
isRTL,
}: StickyItemContentProps) => {
const stickyScaleX = stickyItemWidth / itemWidth;
const separatorSizeToStickyWidthScale = separatorSize / stickyItemWidth;
const stickyScaleX =
stickyItemWidth / itemWidth - separatorSizeToStickyWidthScale;
const stickyWidthWithoutPadding = stickyItemWidth - separatorSize * 2;

//#region thumbnail
const animatedThumbnailScale = interpolate(x, {
inputRange: [0, threshold],
inputRange: [separatorSize, threshold],
outputRange: [1, stickyScaleX],
extrapolate: Extrapolate.CLAMP,
});
const animatedThumbnailTranslateX = interpolate(x, {
inputRange: [0, threshold],
inputRange: [separatorSize, threshold],
outputRange: [0, isRTL ? separatorSize : -separatorSize],
extrapolate: Extrapolate.CLAMP,
});
const animatedThumbnailBorderRadius = interpolate(x, {
inputRange: [0, threshold],
inputRange: [separatorSize, threshold],
outputRange: [borderRadius, itemWidth],
extrapolate: Extrapolate.CLAMP,
});

const thumbnailStyle = [
styles.thumbnail,
{
top: -1,
width: itemWidth,
height: itemWidth,
borderRadius: animatedThumbnailBorderRadius,
transform: transformOrigin(
{
x: (itemWidth / 2) * (isRTL ? -1 : 1),
y: itemHeight / 2 + stickyItemHeight / 2 - itemWidth / 2,
y: itemHeight / 2 + stickyWidthWithoutPadding / 2 - itemWidth / 2,
},
{
translateX: animatedThumbnailTranslateX,
Expand All @@ -56,22 +57,29 @@ const FacebookStickyStory = ({
//#endregion

//#region icon
const iconPosition = findPointOnCircle({
radius: stickyWidthWithoutPadding / 2,
degrees: isRTL ? 135 : 45,
});
const animatedIconTranslateX = interpolate(x, {
inputRange: [0, threshold],
inputRange: [separatorSize, threshold],
outputRange: [
itemWidth / 2 - stickyItemWidth / 2,
isRTL ? 0 : itemWidth - stickyItemWidth / 2 - separatorSize,
(stickyItemWidth / 2) * (isRTL ? 1 : -1),
-(stickyWidthWithoutPadding / 2) + iconPosition.x + separatorSize,
],
extrapolate: Extrapolate.CLAMP,
});
const animatedIconTranslateY = interpolate(x, {
inputRange: [0, threshold],
outputRange: [itemHeight / 2, itemHeight / 2 - separatorSize / 2],
inputRange: [separatorSize, threshold],
outputRange: [
-(stickyItemWidth / 2),
-(stickyWidthWithoutPadding / 2) + iconPosition.y - separatorSize,
],
extrapolate: Extrapolate.CLAMP,
});
const animatedIconScale = interpolate(x, {
inputRange: [0, threshold],
outputRange: [1, 0.4],
inputRange: [separatorSize, threshold],
outputRange: [1, 0.25],
extrapolate: Extrapolate.CLAMP,
});
const iconStyle = [
Expand All @@ -80,29 +88,28 @@ const FacebookStickyStory = ({
borderRadius: stickyItemWidth,
width: stickyItemWidth,
height: stickyItemWidth,
[isRTL ? 'right' : 'left']: '50%',
top: itemHeight / 2,
transform: transformOrigin(
{
x: 0,
y: 0,
},
{ x: 0, y: 0 },
{
translateX: animatedIconTranslateX,
translateY: animatedIconTranslateY,
scale: animatedIconScale,
}
) as Animated.AnimatedTransform,
),
},
];
//#endregion

//#region text
const animatedTextOpacity = interpolate(x, {
inputRange: [0, threshold * 0.6],
inputRange: [separatorSize, threshold * 0.6],
outputRange: [1, 0],
extrapolate: Extrapolate.CLAMP,
});
const animatedTextTranslateY = interpolate(x, {
inputRange: [0, threshold * 0.6],
inputRange: [separatorSize, threshold * 0.6],
outputRange: [itemHeight / 2 + itemHeight / 4, itemHeight / 2],
extrapolate: Extrapolate.CLAMP,
});
Expand Down Expand Up @@ -131,4 +138,16 @@ const FacebookStickyStory = ({
);
};

const findPointOnCircle = ({
radius,
degrees,
}: {
radius: number;
degrees: number;
}) => {
var newX = radius * Math.cos(degrees * (Math.PI / 180));
var newY = radius * Math.sin(degrees * (Math.PI / 180));
return { x: newX, y: newY };
};

export default FacebookStickyStory;
Loading

0 comments on commit e5b246b

Please sign in to comment.