react-native-ripple-button-reanimated
Version:
React Native Button with ripple effect. It works for android and ios.
102 lines (95 loc) • 3.2 kB
JavaScript
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import * as React from 'react';
import { StyleSheet, View } from 'react-native';
import { State, TapGestureHandler } from 'react-native-gesture-handler';
import Animated, { Easing, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
import { hexToRgbA } from './hexToRgba';
function RippleButton({
children,
color,
borderRadius,
onPress = () => {},
rippleScale = 1,
duration = 250,
overflow = false,
rippleColor = '#000',
rippleOpacity = 0.5
}) {
const [radius, setRadius] = React.useState(-1);
const child = React.Children.only(children);
const scale = useSharedValue(0);
const positionX = useSharedValue(0);
const positionY = useSharedValue(0);
const state = useSharedValue(State.UNDETERMINED);
const isFinished = useSharedValue(false);
const uas = useAnimatedStyle(() => ({
top: positionY.value - radius,
left: positionX.value - radius,
transform: [{
scale: scale.value
}]
}), [radius]);
return /*#__PURE__*/React.createElement(TapGestureHandler, {
maxDurationMs: 9999999999,
onHandlerStateChange: event => {
state.value = event.nativeEvent.state;
positionX.value = event.nativeEvent.x;
positionY.value = event.nativeEvent.y;
scale.value = event.nativeEvent.state !== State.FAILED ? withTiming(rippleScale, {
duration,
easing: Easing.bezier(0, 0, 0.8, 0.4)
}, finised => {
if (finised) {
isFinished.value = true;
scale.value = withTiming(0, {
duration: 0
});
}
if (state.value === State.BEGAN && finised) {
scale.value = withTiming(1, {
duration: 0
});
}
}) : 0;
if (event.nativeEvent.state === State.BEGAN) {
isFinished.value = false;
}
if (event.nativeEvent.state === State.END) {
if (isFinished.value) {
scale.value = withTiming(0, {
duration: 0
});
}
onPress();
}
}
}, /*#__PURE__*/React.createElement(Animated.View, _extends({}, child.props, {
style: child.props.style
}), /*#__PURE__*/React.createElement(View, {
style: { ...StyleSheet.absoluteFillObject,
borderRadius,
backgroundColor: color,
overflow: !overflow ? 'hidden' : undefined
},
onLayout: ({
nativeEvent: {
layout: {
width,
height
}
}
}) => {
setRadius(Math.sqrt(width ** 2 + height ** 2));
}
}, radius !== -1 && /*#__PURE__*/React.createElement(Animated.View, {
style: [uas, {
position: 'absolute',
width: radius * 2,
height: radius * 2,
borderRadius: radius,
backgroundColor: hexToRgbA(rippleColor, rippleOpacity)
}]
})), child.props.children));
}
export default RippleButton;
//# sourceMappingURL=RippleButton.js.map