GSAP: Accordion children animation - javascript

I've been trying to create something along the lines of accordion component in React, (the code pen is in vanilla but demonstrates the problem).
Pen: https://codepen.io/tim-bitanov/pen/MXrVRE
Original issue:
Basically, the accordion changes its width when expanded and items begin to enter from below. My problem is that the items do not really come from below, but rather from bottom right since the left property of the container changing due to new width.
<TransitionGroup component={null}>
{this.props.expanded && (
React.Children.map(this.props.children, (child) => (
<Transition
timeout={500}
onEnter={this.onSubMenuEnter}
onExit={this.onSubMenuExit}
>
{child}
</Transition>
)))}
</TransitionGroup>
private onSubMenuEnter = (node: HTMLElement) => {
TweenLite.set(node, { clearProps: 'all' });
TweenLite.from(node, .5, { y: '+=50', opacity: 0 });
}
Can anyone suggest any way to tackle this?
I've tried using the TweenMax.ticker to get current parent left property but was unsure what to do with it

If you're still looking for a solution or someone else I forked your pen to make the items come from below.
You basically just need to translate them from half the width you're expanding the parent as long as you're using the same animation duration and easing.
see below for a container expanding from 0 to 130 as in your demo
TweenMax.from(items, 1, {y: '+=50'}); //not ok
TweenMax.from(items, 1, {y: '+=50', x:'-=65'}); //ok
The forked pen demo

Related

React Spring: dynamic values in useTransition() when using it alongside react-router

In this example you can see some nice transition between pages triggered by the route change. (took from LevelUp Tutorials' React Animation course, thanks a lot Scott Tolinski).
Now I'd like to make these transitions happen in both directions, depending on which page it's transitioning to (and from), for instance:
Page One -> Page Two (both pages transition from left to right)
Page Three -> Page One (both pages transition from right to left)
etc
From that first example I created this example where the value of x is dynamic and should be evaluated to either 100 or -100, based on the direction of the transition.
I haven't fundamentally understood how useTransition() works, and the documentation is rather limited. The examples look amazing but are quite hard to understand.
This example seems to do a similar thing to what I'm trying to achieve but the code feels like black magic: the y property of each object returned from rows.map() appears to be related to the y value on the functions assigned to enter and update properties because if I remove that I get the error: Cannot read property 'replace' of undefined. How does that work?
This problem has two part.
determining the direction
change the animation
I created an example for solving the second part. When the user click page one I reverse the animation.
const reverse = location.pathname === '/';
const transitions = useTransition(location, location => location.key, {
from: { opacity: 0, transform: `translate3d(${reverse ? '-100%' : '100%'},0,0)` },
enter: { opacity: 1, transform: "translate3d(0,0,0)" },
leave: { opacity: 0, transform: `translate3d(${reverse ? '100%' : '-100%'},0,0)` },
// "initial: null" should only disable the 'from' initial transition, not the subsequent 'leave' transition (on the first manually triggered transition)
initial: null
});
Here is the sandbox: https://codesandbox.io/s/spring-transition-with-routes-215t8
For the first part to determine when to reverse the animation, I would store the path at each click and compare the next one to the previous. There is an example of storing the path here: Check history previous location before goBack() react router v4
I hope it helps.

How to rebuild the iOS Picker animation in React Native

Is there a way in React Native to rebuild the iOS picker component completely in Java Script? I don't need the common picker, but a normal scroll view with a similar fade-out effect like the iOS picker.
EDIT – I think I have not explained my initial answer exactly enough. This is why I complete it here:
I want to build a scroll view that takes over the whole screen. It's not supposed to give the user the possibility to elect some item, like the the iOS Picker does. Nevertheless, it's supposed to be a 'normal' scroll view, that shows the user some information, e.g. different chats, tasks, news and so on.
The only difference to React Native's common scroll view should be the fade-out effect at the top: When the user scrolls the content up, it should not just leave the screen at its top edge, but it should use the iOS Picker's fade-out effect (see picture).
This fade-out effect is made up of two parts: First of all, it raises the content's transparency with a decreasing y-coordinate. Furthermore, this content seems to escape into the third dimension.
My problem is, that I don't see a way to achieve this three-dimensionality of the content in React Native. I've to add, that the content in my scroll view does not consist of small, equally sized items (like e.g. the texts 'Item 1', 'Item 2', 'Item 3',...), but of bigger items with different sizes like images or whole textboxes.
You can use this NPM module to get what you want. That module works the same in Android and iOS. Do not reinvent the wheel :)
EDIT: Now I've understood what you want. You can try this snack that I've made for you:
https://snack.expo.io/r1qnxSt9m
Of course you need to improve it, but it's a beginning.
You can achieve the desired effect with the Animated api. The idea is to set different input ranges to the items in your list. You then hook the opacity to the scroll value of your ScrollView (or any list component). I have simplified the code, but it should be enough to demonstrate the idea.
The example below only demonstrates an opacity effect, but you could easily add a translate effect to get the exact animation that you are looking for.
const data = []; // array that contains the text
const items = [];
for (let i = 0; i < data.length; ++i) {
const distanceFromViewCenter = Math.abs(i * ITEM_HEIGHT);
const inputRange = [
-distanceFromViewCenter - 2 * ITEM_HEIGHT,
-distanceFromViewCenter - ITEM_HEIGHT,
-distanceFromViewCenter, // Middle of picker
-distanceFromViewCenter + ITEM_HEIGHT,
-distanceFromViewCenter + 2 * ITEM_HEIGHT,
];
items.push(
<Animated.View
style={{
opacity: this._scrollValue.interpolate({
inputRange,
outputRange: [0.0, 0.3, 1.0, 0.3, 0.0],
}),
}}
>
<Text style={{ height: ITEM_HEIGHT }}>{data[i]}</Text>
</Animated.View>
)
}
<ScrollView
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: this._scrollValue } } }],
{ useNativeDriver: true }
)}
>
{items}
</ScrollView>

Animation in React Native: Modify the height of a view

I managed to made a snack in Expo to simulate the Facebook Navigation bar hiding effect on scroll event, thanks to this amazing post:
https://medium.com/appandflow/react-native-collapsible-navbar-e51a049b560a
Everything works like the Facebook main app.
Here you can find the snack: https://snack.expo.io/#univers3/barra-scomparsa
But now I need to put the scrollview inside a View and I was using this to modify the height of the ScrollView:
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: this.state.scrollAnim } } }],
{ useNativeDriver: true },
)}
The problem is this: if I will incapsulate the ScrollView into a normal View, this event (onScroll) is not available anymore for the parent View.
How I can achieve to modify the height of the parent View?
Edit
To let understand better my problem:
I'm not able to reproduce the same behavior with this environment =>
https://snack.expo.io/SkE2ORuH

make page peel effect better

I would like your suggestions here for the following points
Make peel effect more realistic if possible.
Reduce the size of the peel (to be able to see the full Ad).
Jsfiddle peel effect
I used a div pagePeelsmallrotate rotated at 24deg initially. Which i then animate its angle as well as dimensions .
Also div pagePeelcontainer dimensions are animated.
There are two functions
var pagePeelopen = function() {} /*opens the ad*/
var pagePeelclose = function() {} /*closes the ad */
I tried skewing only the pagePeelcontainer div and not its children to get small peel as provided here
css used to avoid child elements getting affected
#pagePeelcontainer > * {
transform:skew(-45deg);
}
But couldn't get the peel effect properly on click of open.
Jsfiddle skewed peel
Let me know how i can do it
Changing this section of code
$('#pagePeelcontainer').stop().animate({
width: 1000,
height: 1000
}, {
duration: 500
});
Will reveal the whole advert, as for the peeling it looks pretty good the way it is

React Native Card Carousel view?

Does anyone know how can we achieve this kind of view in React Native, or is there any available components out there that can help on this issue?
I've seen in F8 2016 app too, been searching on how to achieve the transition and the carousel-like view with horizontal scrolling.
I know that the question is old, but a co-worker and I recently had to create a component that answers this particular need. We ended up open-sourcing it, so it's all yours to try: react-native-snap-carousel.
The plugin is now built on top of FlatList (versions >= 3.0.0), which is great to handle huge numbers of items. It also provides previews (the effect you were after), snapping effect, parallax images, RTL support, and more.
You can take a look at the showcase to get a grasp of what can be achieved with it. Do not hesitate to share your experience with the plugin since we're always trying to improve it.
Edit : two new layouts have been introduced in version 3.6.0 (one with a stack of cards effect and the other with a tinder-like effect). Enjoy!
You can achieve this using ScrollView with paging enabled on iOS and ViewPagerAndroid on Android.
F8 being an open source app,
you can see that's what it's actually using:
https://github.com/fbsamples/f8app/blob/master/js/common/ViewPager.js
This component renders all pages.
If you only want to have the visible and left and right pages rendered to save memory, there's another component built on top of it that does it:
https://github.com/fbsamples/f8app/blob/master/js/common/Carousel.js
There are various other similar implementations available:
https://js.coach/react-native?search=carousel
https://js.coach/react-native?search=swiper
However I'm not recommending https://github.com/leecade/react-native-swiper as I've had several issues with it.
Speaking about the swiper-component claiming the best of the world, it still does not work out of the box (as of November 2018) as described in the official swiper-react-native documentation. The issue and a workaround is described in the swiper issue 444:
The error message (on Android) states console.error: "fontFamily 'Arial' is not a system font and has not been loaded through Exponent.Font.loadAsync.
Zach Dixon provided an elegant quick-fix which I repeat here for everybody's convenience. Simply use the following JSX-snippet inside your render()-function to avoid that a new font is required:
<Swiper style={styles.wrapper} showsButtons={true}
nextButton={<Text>></Text>} prevButton={<Text><</Text>}>
<View style={styles.slide1}><Text style>Slide 1</Text></View>
<View style={styles.slide2}><Text style>Slide 2</Text></View>
<View style={styles.slide3}><Text style>Slide 3</Text></View>
</Swiper>
For those interested in explanations on how to implement carousel with Scroll-View only, I recommend a tutorial on a simple image carousel with ScrollView. The tutorial is straight forward and elaborates on the things one has to take care of, but you cannot use it out of the box within or on top of other View-elements. In particular the snapping does not work to well (on Android).
You can create your own custom carousel. The Carousel end result looks like this-
goToNextPage = () => {
const childlenth = this.getCustomData().length;
selectedIndex = selectedIndex + 1;
this.clearTimer();
if (selectedIndex === childlenth) {
this.scrollRef.current.scrollTo({ offset: 0, animated: false, nofix: true });
selectedIndex = 1;
}
this.scrollRef.current.scrollTo({
animated: true,
x: this.props.childWidth * selectedIndex,
});
this.setUpTimer();
}
// pushing 1st element at last
getCustomData() {
const {data} = this.props;
const finaldata = [];
finaldata.push(...data);
finaldata.push(data[0]);
return finaldata;
}
This is the main logic used behind looped carousel.
Here we are pushing the first item at last in the list again and then when scroll reaches at last position we are making the scrollview to scroll to first position as first and last element are same now and we scroll to first position with animation like this
this.scrollRef.current.scrollTo({ offset: 0, animated: false, nofix: true });
For further reference go through the link provided.
https://goel-mohit56.medium.com/custom-horizontal-auto-scroll-looped-carousel-using-scrollview-42baa5262f95

Categories

Resources