Skip to content

Instantly share code, notes, and snippets.

@jjylik
Last active May 17, 2021 14:52
Show Gist options
  • Save jjylik/dfade0180cff640cd40ea129a702beed to your computer and use it in GitHub Desktop.
Save jjylik/dfade0180cff640cd40ea129a702beed to your computer and use it in GitHub Desktop.
import React from 'react';
import {Icon as ElementsIcon} from 'react-native-elements';
import {IconProps} from 'react-native-elements';
import {GestureResponderEvent} from 'react-native';
import Animated, {
Easing,
block,
cond,
eq,
set,
and,
not,
clockRunning,
startClock,
timing,
stopClock,
sub,
useCode,
} from 'react-native-reanimated';
import {useValues, useClock} from 'react-native-redash';
export const runTiming = (
clock: Animated.Clock,
iterations: Animated.Value<number>,
): Animated.Node<number> => {
const to = 0.8;
const from = 1;
const state = {
finished: new Animated.Value(0),
position: new Animated.Value(from),
time: new Animated.Value(0),
frameTime: new Animated.Value(0),
iterations: iterations,
};
const config = {
duration: 70,
toValue: new Animated.Value(to),
easing: Easing.linear,
};
return block([
cond(eq(state.iterations, 0), stopClock(clock)),
cond(not(clockRunning(clock)), set(state.time, 0), [
timing(clock, state, config),
]),
cond(and(state.finished, eq(state.position, from)), [
set(state.finished, 0),
set(state.position, from),
set(state.frameTime, 0),
set(state.time, 0),
set(config.toValue, to),
set(state.iterations, sub(state.iterations, 1)),
]),
cond(and(state.finished, eq(state.position, to)), [
set(state.finished, 0),
set(state.position, to),
set(state.frameTime, 0),
set(state.time, 0),
set(config.toValue, from),
]),
state.position,
]);
};
export function AnimatedIcon(props: IconProps): JSX.Element {
const {onPress, ...rest} = props;
const clock = useClock();
const [scale, animationIterations] = useValues<number>(1, 0);
useCode(
() =>
block([
cond(
and(not(clockRunning(clock)), not(eq(animationIterations, 0))),
startClock(clock),
),
cond(
and(clockRunning(clock), eq(animationIterations, 0)),
stopClock(clock),
),
set(scale, runTiming(clock, animationIterations)),
]),
[clock, animationIterations, scale],
);
const press = onPress
? (event: GestureResponderEvent): void => {
animationIterations.setValue(1);
onPress(event);
}
: (): void => animationIterations.setValue(1);
return (
<Animated.View style={{transform: [{scale}]}}>
<ElementsIcon accessibilityRole="button" onPress={press} {...rest} />
</Animated.View>
);
}
import React from 'react';
import {GestureResponderEvent, TouchableWithoutFeedback} from 'react-native';
import {Icon as ElementsIcon, IconProps} from 'react-native-elements';
import Animated, {
Easing,
useAnimatedStyle,
useSharedValue,
withSequence,
withTiming,
} from 'react-native-reanimated';
export function AnimatedIcon(props: IconProps): JSX.Element {
const {onPress, style, ...rest} = props;
const scale = useSharedValue(1);
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [{scale: scale.value}],
};
});
const onAnimatedPress = (event: GestureResponderEvent): void => {
scale.value = withSequence(
withTiming(0.8, {duration: 100, easing: Easing.linear}),
withTiming(1, {duration: 100, easing: Easing.linear}),
);
onPress?.(event);
};
return (
<TouchableWithoutFeedback
accessibilityRole="button"
onPress={onAnimatedPress}>
<Animated.View style={[style, animatedStyle]}>
<ElementsIcon {...rest} />
</Animated.View>
</TouchableWithoutFeedback>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment