Is it possible to let SlideInMenu of react-native-popup-menu slide in from the right or left? - react-native-popup-menu

Standard Behaviour for react-native-popup-menu SlideInMenu renderer is to slide in from the bottom and slide out towards it again. Can this be changed to left or right?

Ok it is quite easy. You can just edit the
transform: [{
translateY: this.state.slide.interpolate({
inputRange: [0, 1],
outputRange: [oHeight, 0]
}),
}]
in SlideInMenu.js and change the translateY to translateX. Or if you want to change directions accordingly change the values.
I added a dynamic SlideInMenuDirection.js now for all my needs and registered it in the index.js.

Related

How to do series/parallel animation in react-native-reanimated 2?

I'm looking for the equivalent of Animated.sequence and Animated.parallel from react-native. So far from the docs for v2, I could only see the withSequence function that changes the value of only on value and therefore the style of only one component in series.
What I was looking for was to trigger animations in two different components, either in series or in parallel.
For parallel, it seems changing values in statements one after another worked. Correct me if I'm wrong.
// these will run in parallel
val1Shared.value = withTiming(50);
val2Shared.value = withTiming(100);
But for series, I need to have each animation inside a useTiming callback. Which leads to kind of callback hell.
val1Shared.value = withTiming(50, undefined, () => {
val2Shared.value = withTiming(100);
});
Please help with the best practices in achieving this with reanimated 2.
Thanks.
I think there is no way of doing it like in Animated.
This library requires you to think a different way. If you want you run two animations (each one for a separate view) using interpolation, you can use a single shared value and a sufficient interpolation config.
Let's assume (according to your example) that you have two views you want to animate. The first animation is from 0 to 50, the second one is from 0 to 100.
Let's also assume you're transforming an X axis (I don't know what's your case, but it's going to be very similar) and we count the animation progress from 0 to 1, and both views will animate for the same period of time.
Initialize the shared value:
const animation = useSharedValue(0);
And do sth like this (of your choice):
animated.value = withTiming(1, { duration, easing });
For the first view, your transformation will look like this:
const animatedStyles1 = useAnimatedStyle(
() => ({
transform: [
{
translateX: interpolate(animation.value, [0, 0.5, 1], [0, 50, 50]),
},
],
}),
[mode, rectSize]);
and for the second one, like this:
const animatedStyles2 = useAnimatedStyle(
() => ({
transform: [
{
translateX: interpolate(animation.value, [0, 0.5, 1], [0, 0, 100]),
},
],
}),
[mode, rectSize]);
Now the explanation.
For the first view, we only work for the half of progress from the whole animation, so we from 0 to 0.5 we'll animate from 0 to 50. then, for the reset of the progress we'll stay in the same place (this is called a dead zone), to from 0.5 to 1 value of the progress does not change (50 to 50).
Now, for the second view, we wait for the progress to be in half, so from 0 to 0.5 we don't do anything (0 to 0). Then, when the progress is in half, we animate the view from 0 to 150.
In general, that way you can orchestrate the whole thing using just a single shared value.
Here you can find more info about the interpolation. The docs is from the react-native's Animated, but the idea is the same.
Good luck!

how can I stop the wheel of fortune to particular point using Animated API in React Native?

I'm developing wheel of fortune where I want the wheel to iterate four times while spinning, and stop to a particularly given value. All I want is to spin the wheel four times and stop to a particular slice. I'm thinking below code can work my idea.
Animated.loop(
Animated.timing(this._angle, {
toValue: 920,
duration: 5000,
}),//.start();
{
iterations: 1
}
).start();
I'm using angle as value. My formula to get the 'toValue' is "targetAngle * 4". This works but I want to decelerate the spinning in its last iterate just like Animated.decay() does. Is there any better idea to resolve this issue?
you can do
const onPress = () => {
Animated.timing(RotateAnimeted, {
toValue: 6,
duration: 1000,
}).start();
};
const Rotate = RotateAnimeted.interpolate({
inputRange: [0, 1, 2, 3, 4, 5, 6],
outputRange: [
"0deg",
"360deg",
"720deg",
"840deg",
"940deg",
"1020deg",
"1080deg",
],
});
You can change the values to get the result you want
I did an example at the expo
Attaches a gif image

React Native - How to start another animation conditionally

I want to create my own loader using animation, my idea is using scale to handle it, so the step should be like:
show an image scale from (n) to 1 for the first time
check if conditional is accepted or not
if conditional accepted, show an image scale from 1 to (n)
I can achieve 1st condition, but when i try 2nd and 3rd condition, the animation start in a blink of eye,
anyone can help me how to fix this?
here's the code i've tried:
//animation function
playAnimation(){
this.setState({onLoad:true})
this._load.setValue(0)
this._scale.setValue(0)
Animated.timing(this._load, {
toValue: 100,
useNativeDriver: true,
duration:1000
}).start(()=>{
setTimeout(() => {
Animated.timing(this._scale, {
toValue: 100,
useNativeDriver: true,
duration:1000
}).start(()=>this.setState({onLoad:false}));
}, 2000);
});
onLoad = this._load.interpolate({
inputRange: [0, 50, 75, 100],
outputRange: [10, 1, 1.4, 1],
})
imageScale = this._scale.interpolate({
inputRange: [20, 35, 70],
outputRange: [1.2, 1, 20],
})
}
//on render
<Animated.Image
style={{
resizeMode:'contain',
position:'absolute',
zIndex:1,
width:width/2,
height:200,
transform:[{scale:this.state.onLoad?onLoad:imageScale}]
}}
source={{uri: "https://www.knittedhome.com/communities/5/004/012/872/235/images/4628207884.jpg"}}
/>
and the result:
How your code works right now is somewhere in your code, you're calling PlayAnimation().
PlayAnimation() will:
start and complete first animation
Wait 2 sec
start and complete second animation
What you're doing in your Animated.Image is setting the transforms to different values. This doesn't start or stop the animation, just tells Animated.Image what value to set transform to.
What you should do
Use one Animated.Value to keep track of the scale. Assign that value to the Animated.Image transform.
Write two Animation functions:
scaleDown, call this where you're currently calling PlayAnimation
scaleUp, use your onLoad conditional to execute this in render or somewhere appropriate.

Creating a parallax image in React Native

I'm trying to create an animated "parallax" image in React-Native. I have a static background image and two individual images as an overlay. The goal is to create something similar to the image found on this website http://www.digitalhands.net/ or https://www.galaxia.co/. Where do I even start with this? Initially I'd be happy with it moving just on itself from left to right and etc. Afterwards I want to make it so that it would use the gyroscope to get the x and y values for animating the image.
A parallax effect consists of images moving in different speeds and in the same direction, such that the 'closer' an object is, the faster it moves, which creates the illusion of three dimensions.
To achieve this effect in react-native, you can use the Animated library to interpolate the position of one image as a fraction of the position of another.
For the sake of an example, let's assume you want the parallax effect in the vertical direction, and that all images are positioned at 0 vertically.
First, you would need an animated value in your component's state:
this.state = {
...
imagePos: new Animated.Value(0)
}
Then, for each Image style you can add a transform on its y axis:
<Animated.Image src={...} style={[firstImageStyle, {
transform: [{translateY: this.state.imagePos.interpolate({
inputRange: [0, 1],
outputRange: [0, 100]
})}]
}]}
<Animated.Image src={...} style={[secondImageStyle, {
transform: [{translateY: this.state.imagePos.interpolate({
inputRange: [0, 1],
outputRange: [0, 50]
})}]
}]}
Note the use of Animated.Image instead of Image to make the image animatable.
This would cause the first image to move horizontally between 0-100 dp when imagePos has values between 0 and 1, and the second image to move between 0-50 dp.
To change the value of the animated value you can use any of the functions in the Animated library (timing, spring, decay, etc.) or you can attach it to some native event.
The animated library documentation has much more detail.
As for the use of the gyroscope, I haven't gone into the details, but you can probably use react-native-sensors or react-native-motion-manager to get the values you need, and attach them to the animation.
By using a package like https://github.com/react-native-sensors/react-native-sensors I managed to get the x, y, z values of the phones position and animate an image with it.
constructor() {
super();
this.state = {
x: 0,
y: 0,
z: 0,
};
}
componentWillMount() {
// Normal RxJS functions
accelerationObservable
.subscribe(({x, y, z}) => this.setState({
x: x,
y: y,
z: z,
}));
}
render() { return (
<Image style={{left: this.state.x + this.state.y, top: this.state.z}}
source={require('image.png')}/>
)
}

JSPdf autotable header border

How to create border in Header? I am using jspdf autotable to create table but cannot find any idea to apply border to header. Is there any hook that can be used to create header border?
You can use the header styles:
doc.autotable(columns, data, {
headerStyles: {
lineWidth: 1,
lineColor: [255, 0, 0]
}
});
As of today (version 3.5.25) the property name is headStyles and still different border widths is not supported.
Example:
autoTable(doc, {
headStyles: {
lineWidth: 0.5, // 1 is too thick for me
lineColor: [255, 0, 0] // Or gray level single value from 0-255
}
})
I use the imported method version (autoTable) in TypeScript.