Animation in React Native: Modify the height of a view - javascript

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

Related

Collapsing and Expanding Side Panels in React

I apologize is this is a very simple task this is really my first time transitioning to react.
I have an existing application built with js/css/html that I am attempting to shift over to react. It has a full length horizontal side panel that is open by default, when the window is shrunk beyond a point it collapses with a hamburger icon, and expands again when the window is resized larger. Fairly easily done with media queries in css.
A perfect example is https://purecss.io/layouts/side-menu/ (note the side menu) This is exactly what the current app does.
I'm struggling to do this in react. I can build a side panel that is collapsible (https://reactjsexample.com/react-side-nav-component/) and mofify it for my needs, but I cannot figure out how to set it up so it collapses and expands by itself. I understand I can set it up react to use media queries, however I figured there was likely a more efficient way.
Any advice of good libraries to use, or examples would be greatly appreciated.
You could do something like this:
const Component = props => {
const [windowWidth, setWindowWidth] = useState(0)
useEffect(() => {
window.addEventListener('resize', updateWindowDimensions)
updateWindowDimensions()
return () => window.removeEventListener('resize', updateWindowDimensions)
}, [])
useEffect(() => {
if (windowWidth < 500) {
closeModal()
return
}
openModal()
}, [windowWidth])
updateWindowDimensions() {
setWindowWidth(window.innerWidth)
}
}

How to get Xterm.js resize properly?

tl;dr
I've created a React wrapper to render an array of log messages into a terminal but resizing is giving a weird output (see screenshot). (There is a React-Wrapper on NPM but that wasn't working for my use-case - caused screen flickering)
I'm working on a feature for Guppy where I'm adding Xterm.js for the terminal output.
The PR can be found here.
I've added xterm because of hyperlink scanning/parsing and that is working.
But I'm stuck with getting resize to work. If I'm starting the devServer in the app and wait for some text it will display with correct letter width.
If I reduce the size I'm getting an output with an incorrect letter width.
Like in the following screenshot:
It is always looking correct in the not resized state but after resize it will get the wrong display - so this will happen for enlarging & shrinking the screen width.
The output should look similar to the following screenshot (maybe with some wrapped lines):
I think this is caused by Fit addon or the way I'm handling resizing with the resize observer but I'm not sure.
The span style of xterm letter are getting a width of NaNpx like in the following screenshot:
Is this caused by a media query I'm using? I haven't seen that yet maybe I have to temporarily disable all media queries to see if that's causing the behaviour.
What I have tried so far:
Wrapped this.xterm.fit() into a setTimeout(func, 0) but with-out an effect
Modified some of the styles I'm using but I haven't found the cause.
Code
The code I'm using can be found on Github branch feature-terminal-links but here I'd like to extract the parts I've added to get Xterm to work with React:
I created a styled-component XtermContainer as a div so I can add Xterm styles and own styling. The following code is inside render and will be our xterm.js container (innerRef will be used later in ComponentDidMount to intialize Xterm with that container):
<XtermContainer
width={width}
height={height}
innerRef={node => (this.node = node)}
/>
Init xterm in componentDidMount with the container above:
componentDidMount() {
Terminal.applyAddon(webLinks);
Terminal.applyAddon(localLinks);
Terminal.applyAddon(fit);
this.xterm = new Terminal({
convertEol: true,
fontFamily: `'Fira Mono', monospace`,
fontSize: 15,
rendererType: 'dom', // default is canvas
});
this.xterm.setOption('theme', {
background: COLORS.blue[900],
foreground: COLORS.white,
});
this.xterm.open(this.node);
this.xterm.fit();
/* ... some addon setup code here (not relevant for the problem) ... */
}
Added react-resize-observer inside of the wrapper that is also containing the terminal container so I can trigger this.xterm.fit() if the size changes (in the repo there is a setTimeout wrapper around for testing).
<ResizeObserver onResize={() => this.xterm && this.xterm.fit()} />
Using componentDidUpdate(prevProps, prevState) to update the terminal and scroll the terminal to the bottom if the component is getting new logs:
componentDidUpdate(prevProps, prevState) {
if (prevProps.task.logs !== this.state.logs) {
if (this.state.logs.length === 0) {
this.xterm.clear();
}
for (const log of this.state.logs) {
/*
We need to track what we have added to xterm - feels hacky but it's working.
`this.xterm.clear()` and re-render everything caused screen flicker that's why I decided to not use it.
Todo: Check if there is a react-xterm wrapper that is not using xterm.clear or
create a wrapper component that can render the logs array (with-out flicker).
*/
if (!this.renderedLogs[log.id]) {
this.writeln(log.text);
this.xterm.scrollToBottom();
this.renderedLogs[log.id] = true;
}
}
}
}
Ideas I have to find the cause:
Check ResizeObserver code. (see update below)
Try to find why xterm css is getting a NaN width. Is Xterm.js using the style width of the container? If yes, maybe that's not correctly set.
Update
OK, the resize obeserver is probably not needed as I'm getting the same behaviour after commenting out the <ResizeObserver/> in render. So I think it's caused by xterm.js or the css in Guppy.
I have a fix for the issue. It's now working in the above mentioned feature branch. Not sure if there is a better solution but it's working for me.
I like to explain how I have fixed the resizing issue:
The problem was the OnlyOn component that was used in DevelopmentServerPane. It always rendered two TerminalOutput components. One terminal was hidden with display: none and the other was displayed with display: inline - the style change was handled with a media query inside a styled-component.
After replacing OnlyOn with React-responsive and using the render props to check mdMin breakpoint it was working as expected. React-responsive is removing the not displayed mediaquery component from DOM so only one terminal in DOM at the same time.
I still don't know why there was a problem with the letter width but probably the two instances collided somehow. I couldn't create a minimal reproduction. I tried to recreate the issue in this Codesandbox but I have only resized one Terminal at a time and so I haven't got the issue there.
The code that fixed the problem (simplified version from the above mentioned repo):
import MediaQuery from 'react-responsive';
const BREAKPOINT_SIZES = {
sm: 900,
};
const BREAKPOINTS = {
mdMin: `(min-width: ${BREAKPOINT_SIZES.sm + 1}px)`,
};
const DevelopmentServerPane = () => (
<MediaQuery query={BREAKPOINTS['mdMin']}>
{matches =>
matches ? (
<div>{/* ... render Terminal for matching mdMin and above */}</div>
) : (
<div> {/* ... render Terminal for small screens */}</div>
)
}
</MediaQuery>
);

GSAP: Accordion children animation

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

Looping bubbles animation

I'm working on a react website but new to the animation area.
I'm trying to accomplish the effect like the hero section of this page: https://stripe.com/us/customers, where there's an infinite loop of circles scrolling from right to left, each with different images and sizes.
How should I get started with this infinite loop of objects animation using React? Is there some library that I can use, or is there a react code snippet sample that I can learn from?
you may be able to accomplish this using purely CSS (check out these crazy pure CSS animation examples that you can fork https://envato.com/blog/pure-css-animation-snippets/)
But the ReactJS approach would be to create a component like.. lets say FloatingIcon
import React from 'react';
class FloatingIcon extends React.Component {
constructor(props) {
super(props);
this.state{
horizontalPosition: "0px",
verticalPosition: "0px",
imgRef: "http://blah.com/asdf",
backgroundColor: "#000000"
}
}
changePosition(horizontalPosition, verticalPosition) {
this.setState({
horizontalPosition,
verticalPosition
});
}
render() {
return (
<div>
<img
href={this.state.imgRef}
style={
{translate(this.state.horizontalPosition,
this.state.verticalPosition)},
backgroungColor:{this.state.backgroundColor}}>
</img>
</div>
);
}
}
export default FloatingIcon;
each floating icon has an image, background-color, and position in it's state. Create as many as you need for your page and store them in an array. You can change the position using the changePosition function that sets the state and updates causing the DOM to render again. Getting it to float all pretty will take some work, but if you calculate correctly and create a good position change. This will work in a React technical sense and this is a React like design for such a problem creating components to accomplish these tasks using single responsibility principles. Let me know how it goes. Hope this helps friend.
Cheers!

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