LayoutAnimation in React-Native not running - reactjs

I'm trying to animate a stack of cards moving up as the cards on the top get swiped off the deck but I cannot make the animation to run.
I try to run the animation when the number of cards on the deck changes
useEffect(() => {
LayoutAnimation.spring();
},[currentCard]);
Also, I try to run it on the function that is called on swiped completion:
function onSwipeComplete(direction) {
const item = data[currentCard];
direction === 1 ? onSwipeRigt(item) : onSwipeLeft(item);
pan.setValue({ x: 0, y: 0 });
setCurrentCard(index => index + 1);
LayoutAnimation.configureNext({
duration: 5000,
update: {
type: LayoutAnimation.Types.spring,
springDamping: 0.7
}
});
}
On the attached sandbox you will find both solutions implemented but of course I try to use one at the time.
To see the problem jump into the sandbox if you swipe the top card left or right you will notice that the cards bellow snap to the top, instead I want to slowly animate it to the top.
https://codesandbox.io/s/react-native-deckj-z1nwb?file=/src/Deck.js

Related

R3F OrbitControls with fixed camera position

I'm using this for a 360 image and I need the camera to stay fixed at (0,0,0)
If I update the camera position the controls stop working.
I've seen this post https://codeworkshop.dev/blog/2020-04-03-adding-orbit-controls-to-react-three-fiber/ which kind of has a fix but seems out of date, the extend functionality doesn't make orbitControls available.
I've tried various combinations of
const onChange = () => {
camera.position.set(0, 0, 0);
ref.current.update();
};
Or
useEffect(() => {
if (ref.current && scene.projection === SceneProjection['3603D']) {
camera.position.set(0, 0, 0);
ref.current.update();
}
}, [ref, scene]);
Is there a simple way to lock the camera position with OrbitControls and just rotate the camera?
I think you might be able to set controls.maxDistance to something really small, like 0.01. That way it only rotates around its origin by an imperceptible amount.
You can read more about the .maxDistance attribute in the docs](https://threejs.org/docs/index.html?#examples/en/controls/OrbitControls.maxDistance)

Set value immediately after another one have been set in Reanimated 2

I am using Reanimated 2 to build a game with React Native its performance is incredibly good but I have a problem.
I am using a shared value to animate a View as we all know setting the value of the shared value will automatically change the style of the View, my problem is that let's say it will be a Button that the user presses to give the View an elevation simply by changing a shared value used in the animated style of the View, the elevation is simply translation in the y axis.
The elevation value is 0 at first. The user clicks the button the value changes to for example 500 immediately with no transition and no animation, the View will immediately show at 500 above its starting position. And from 500 the View will drop back to 0 with animation.
I tried the code below but no help.
const elevation = useSharedValue(0);
const handleClick = () => {
elevation.value = 500;
elevation.value = withTiming(0, { duration: 1000 });
}
const viewAnimatedStyle = useAnimatedStyle(() => ({
transform: [
{
translateY: elevation.value,
}
]
}))
when pressing the button the view doesn't move, it seems that Reanimated skips the first elevation.value assignment, and since the second assignment is to 0 (the same old value) the View doesn't move.
[Edit] Animated.View is imported from Reanimated 2 and used. I left it out for simplicity.
You need to use <Animated.View> for the useAnimatedStyle, If you are now using It will not be working correctly.
function App() {
const width = useSharedValue(50);
const animatedStyle = useAnimatedStyle(() => {
return {
width: width.value,
};
});
// attach animated style to a View using style property
return <Animated.View style={[styles.box, animatedStyle]} />;
}

GSAP TweenMax mouse animation acts weirdly on mouse events

I'm creating a portfolio website using React and I decided to replace the default cursor with a personalized one. I used GSAP TweenMax to animate my custom mouse.
Everything works fine except for some weird cases.
At certain times, when the user clicks on an element or scrolls through a component, the mouse position animates by itself to the 0,0 position (upper left corner of the screen).
I tried console.log in the only function that animated the mouse position but It's not even fired when I click or scroll. (See gifs in the bottom for illustration of the problem)
This is the mouse function used to animate the position of the custom mouse.
export const handleMouseMove = (bigMouseCircle, smallMouseCircle) => e => {
TweenMax.to(bigMouseCircle.current, 0.3, {
x: e.pageX - 16,
y: e.pageY - 16
});
TweenMax.to(smallMouseCircle.current, 0.1, {
x: e.pageX - 4,
y: e.pageY - 4
});
};
Where its used:
App.js
(...)
useEffect(() => {
document.addEventListener(
"mousemove",
handleMouseMove(bigMouseCircle, smallMouseCircle)
);
(...)
return () => {
document.removeEventListener(
"mousemove",
handleMouseMove(bigMouseCircle, smallMouseCircle)
);
};
(...)
});
(...)
<div className="cursor">
<div ref={bigMouseCircle} className="cursor__ball cursor__ball--big" />
<div
ref={smallMouseCircle}
className="cursor__ball cursor__ball--small"
/>
</div>
(...)
Other mousehandlers are used (mousedown, mouseup, mouseout, mouseenter, mouseover) but none are fired when the bug occurs.
GIF of the bug:
preview 1: https://i.imgur.com/YvJC3gM.gif
preview 2: https://i.imgur.com/yyd7ZrQ.gif
Live website: http://adamchami.com/

ReactJS custom cursor effect:Cursor not working when user scroll

Those days I watch in youtube great video how to create custom cursor CSS and JS.
So I wrote this code in ReactJS and create almost similar custom cursor effect.But there and small bug when user scroll (without move mouse only scroll) my custom cursor not moving.
Codesandbox
Please help how to solve this issue.
state = {
xMain: 0,
yMain: 0,
expand: false
};
componentDidUpdate() {
if (this.state.expand) {
setTimeout(() => {
this.setState({ expand: false });
}, 500);
}
}
handleMouseMove = e => {
const { pageX, pageY } = e;
this.setState({
xMain: pageX,
yMain: pageY
});
};
expandCursor = () => {
this.setState({
expand: true
});
};
render = () => {
const { xMain, yMain } = this.state;
return (
<div
className="container"
onClick={this.expandCursor}
onMouseMove={e => this.handleMouseMove(e)}
>
<div
className={this.state.expand ? "cursor expand" : "cursor"}
style={{
left: xMain,
top: yMain
}}
/>
</div>
);
};
I have write this demo.
It has a little delay while scrolling, which is about the performance issue. I haven't come up the way to fix.
Anyway, still hope this helps!
In my opinion, to achieve this needs to consider 2 steps:
Add a scroll event listener
In your code, to add onScroll in .container will not working, because when you scroll, only body element can detect this event.
Hence we have two ways available:
a. Bind vanilla Javascript eventList in lifecycles like this.
b. Make your element scrollable, and bind onScroll in JSX.
In my code I tried b method. The key is to create a parent wrapper(position: relative; width: 100%;) for container, and add the style height: 100%; to html, body, #root. I have to say I don't know the real reason why add height: 100%; would make this work. I learn this by react-sprint example.
Get the scroll offset for the event, and calculate the position of cursor.
Once the onScroll works, the second thing is : how to calculate the cursor position form scroll event?
I notice that previous wrap approach made the pageX, pageY value changes.
The value is not the offset to the document anymore, it's the offset to the viewport. (I guess it only count in the scroll offset with body.)
And we can use scrollTop value of scroll event to get the scroll offset from the document:
scrollTop
The Element.scrollTop property gets or sets the number of pixels that an element's content is scrolled vertically.
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop
Last step, defined the x,y properties for scroll event and mouse event individually, then sum up the scrollX and mouseY as left; sum up the scrollY(the scrolled height) and mouseY (the y offset of mouse from viewport) as top.
You need to handle the scroll event. Try something like this.
componentDidUpdate() {
if (this.state.expand) {
setTimeout(_ => {
this.setState({ expand: false });
}, 500);
}
window.addEventListener('scroll', this.handleScroll);
}
handleScroll = e => {
console.log('x');
this.setState({
xMain: e.pageX,
yMain: e.pageY
});
};

Scrolling to X,Y direction given number of pixels in react native scrollview

In react native there is a scrollTo function which programatically scrolls to a given x and y coordinate, animated or not.
https://facebook.github.io/react-native/docs/scrollview.html#scrollto
scrollTo({x: 0; y: 0; animated: true})
In some cases this is useful, but there are some cases in which I only want to scroll down for 100 pixels or scroll up for 200 pixels regardless of the position x,y on the screen. Is there a way to programatically do this in react-native currently.
You can keep track of your current X and Y scroll position in state by doing something like what is mentioned in this answer. So for example:
<ScrollView
ref={(scrollView) => { this._scrollView = scrollView; }}
onScroll={this.handleScroll}
/>
handleScroll = (event: Object) => {
this.setState({scrollX: event.nativeEvent.contentOffset.x, scrollY: event.nativeEvent.contentOffset.y})
}
Then you can move your scroll using scrollTo and the current position +/- whatever you wish. Example:
moveScroll = () => {
this._scrollView.scrollTo({y: this.state.scrollY + 100});
}
Do read through the linked StackOverflow answer though to understand the caveats of how onScroll works. I'm also not checking to see if you hit the end/beginning of the scroll window so check your bounds as well.

Resources