Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
react-native-interactable
Advanced tools
react-native-interactable
We love this project, but currently we don’t have enough time to work on it. So we are looking for a maintainer. If you have enough time and knowledge and want to become one - please let us know (levv@wix.com, sergeyi@wix.com)
All of these use-cases have views that continuously interact with the user's gestures. These interactions are normally physical in nature, having properties like springiness, friction, elasticity and damping. In order to feel natural on a touch device they need to run at 60 FPS.
The async nature of the React Native bridge incurs an inherent performance penalty. This traditionally prevents JavaScript code from running at high framerates. One of the most noticeable challenges is animations in JavaScript, which aren't guaranteed to run at 60 FPS.
Modern animation libraries for React Native, like Animated, tackle this challenge with a declarative approach. In order to minimize passes over the bridge, animations are only declared in JavaScript but executed by a native driver on the other side - in 60 FPS.
Fluid user interactions take this a step further than animations. Interactions require UI to continuously react to the user's gestures. This library is designed to support complex physical interactions with ease, using a full-fledged physics engine to drive the interaction on the native side.
First off, we are aware that interactable isn't a real word. The correct form is interactive but this has connotation that isn't necessarily related to physical interactions. Similar to Animated.View
, we wanted to have Interactable.View
- meaning a view you can interact with. And hey, Unity did it too.
Requires RN 0.40 and above.
npm install react-native-interactable --save
react-native link react-native-interactable
Note: instead of linking automatically you can also link manually according to these instructions
node_modules/react-native-interactable/ios/Interactable.xcodeproj
Manually link via Cocoa Pods (iOS)
Podfile
and run pod update
:pod 'Interactable', :path => '../node_modules/react-native-interactable'
The playground project has few use-cases implemented like: swipeable card, drawer, collapsible header and chat heads under the "Basic examples" section. It's simplistic but easy to learn from.
Under the "Real life example" you'll find more complex demonstrations. They're harder to learn from, but they're cool to watch. More info about the UX inspirations for the demo app.
npm start
npm run ios
Note: It's recommended to experience it on a real device and not on a simulator. The simulator has poor performance so the framerate isn't like the real thing.
The core of this library is the Interactable.View
component, used to wrap views you want to interact with:
import Interactable from 'react-native-interactable';
<Interactable.View
horizontalOnly={true}
snapPoints={[{x: 0}, {x: -200}]}
onSnap={this.onDrawerSnap}>
// the view that you wrap here will now support interactions
</Interactable.View>
Interactable.View
PropsClick here for the full reference for all props
snapPoints
- a list of points the view will snap to after being dragged by the usersnapPoints={[{x: 0}, {x: -200}]}
springPoints
- connect the view's center to a group of constant springsspringPoints={[{x: 0, tension: 6000, damping: 0.5, influenceArea: {left: 0}}]}
gravityPoints
- attract/repel the view's center with a group of constant gravity wellsgravityPoints={[{x: 0, y: 0, strength: 8000, falloff: 40, damping: 0.5}]}
frictionAreas
- add friction to the view's movement with a group of friction regionsfrictionAreas={[{damping: 0.5, influenceArea: {top: 0}}]}
alertAreas
- send alert event when the view's center enters/leaves any region within the groupalertAreas={[{id: 'myArea', influenceArea: {top: 0}}]}
horizontalOnly
- whether the view should be locked to horizontal movement onlyhorizontalOnly={true}
startOnFront
- [ANDROID ONLY] whether the view should call bringToFront
startOnFront
verticalOnly
- whether the view should be locked to vertical movement onlyverticalOnly={true}
boundaries
- limits to movement relative to the view's center (after initial layout)boundaries={{left: -100, right: 100, bounce: 0.5}}
onSnap
- a function called whenever the view finishes snapping to a snapPoints
point (after dragging)onSnap={this.onDrawerSnap}
onSnapStart
- a function called whenever the view starts snapping to a snapPoints
point (after dragging)onSnapStart={this.onDrawerSnapStart}
onStop
- a function called whenever the interaction stops (views freeze momentarily)onStop={this.onStopInteraction}
onDrag
- a function called whenever the user starts or stops dragging the viewonDrag={this.onDragEvent}
onAlert
- a function called whenever the view's center enters/leaves an alert areaonAlert={this.onAlertEvent}
dragEnabled
- whether the user can drag the view or notdragEnabled={true}
dragWithSpring
- specify to make dragging behavior of the view occur using a springdragWithSpring={{tension: 2000, damping: 0.5}}
dragToss
- time in seconds the view is allowed to be tossed before snapping to a pointdragToss={0.1}
animatedValueX
- Animated.Value
that will contain the delta from the center as the view moves (x axis)animatedValueX={this._deltaX}
animatedValueY
- Animated.Value
that will contain the delta from the center as the view moves (y axis)animatedValueY={this._deltaY}
animatedNativeDriver
- whether integration with Animated should use native driveranimatedNativeDriver={false}
initialPosition
- used to initialize the view's position to a position different than it's original centerinitialPosition={{x: -140, y: -280}}
Interactable.View
MethodssetVelocity(params)
- used to imperatively set the view's velocity in order to move it aroundinstance.setVelocity({x: 2000});
Takes a single argument, which is a params object containing:
x
- The horizontal velocity. Optional.y
- The vertical velocity. Optional.snapTo(params)
- used to imperatively cause the view to snap to one of its snap pointsinstance.snapTo({index: 2});
Takes a single argument, which is a params object containing:
index
- The index of the snap point in the snapPoints
array. Optional.changePosition(params)
- used to imperatively set the view's positioninstance.changePosition({x: 120, y: 40});
Takes a single argument, which is a params object containing:
x
- The x coordinate.y
- The y coordinate.bringToFront()
- bring view to front (Android Only)instance.bringToFront();
Interactable.View
positionThis library is integrated with the Animated library in order to support performant animations of other views according to the movement of the Interactable.View
.
Consider the following use-cases:
In these use-cases, we have views different from the one the user is interacting with, that animate according to the interactive view's position. Since Animated library uses Animated.Value
to animate view properties, we support setting the value of an Animated.Value
instance according to position of the interactable view. The Animated.Value
will contain the delta between the Interactable.View
original center and new center. This can be done separately on the X axis and Y axis.
After setting this up, use Animated to declaratively define interpolations of the Animated.Value
to various animatable view properties like opacity, scale, rotation, translateX and translateY:
this._deltaY = new Animated.Value(0);
<Animated.View style={{
transform: [{
scale: this._deltaY.interpolate({
inputRange: [-150, -150, 0, 0],
outputRange: [0.3, 0.3, 1, 1]
})
}]
}}>
...
</Animated.View>
<Interactable.View
verticalOnly={true}
snapPoints={[{y: 0}, {y: -150}]}
animatedValueY={this._deltaY}
>
...
</Interactable.View>
Originally, the iOS implementation relied on UIKit Dynamics - a powerful native animation engine for physical interactions. A physics engine is required in order to make the interaction life-like. Consider the action of tossing a view connected via a spring to a snap point. A simple native spring animation will not be enough to take the initial velocity vector into account.
At some point, UIKit Dynamics was dropped in favor of a home-brewed physics implementation in order to provide more control over the behaviors. This also paved the way for the Android port since there's no parallel to UIKit Dynamics for Android. The home-brewed physics engine was straightforward to port from Objective-C to Java and is now part of this library.
If you are interested in the project, have feedback or want to contribute don't hesitate to contact me. I'm particularly interested in ideas on how to expand the declarative API for more use-cases and suggestions on how to improve performance. PRs are always welcome.
MIT
FAQs
High performance interactable views in React Native
We found that react-native-interactable demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 5 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.