GithubHelp home page GithubHelp logo

ijzerenhein / react-native-magic-move Goto Github PK

View Code? Open in Web Editor NEW
973.0 9.0 45.0 38.37 MB

Create magical move transitions between scenes in react-native ๐Ÿฐ๐ŸŽฉโœจ

Home Page: https://expo.io/@ijzerenhein/react-native-magic-move-demo

License: MIT License

JavaScript 70.27% Java 14.50% Objective-C 14.78% Ruby 0.45%
react-native magic-move scene transitions ui-animation

react-native-magic-move's Introduction

Important react-native-shared-element update!

A follow up project called react-native-shared-element has been created which can be considered the successor to react-native-magic-move. It it an all native solution that provides superior performance (no more passes over the react-native bridge) and transitions. It however does not support some of the more exotic transition types (flip, shrinkAndGrow) that Magic Move does. It also doesn't support the web-platform yet and requires native extensions to run. New users are advised to use react-native-shared-element when possible. As for Magic Move, no more new developments will be started for Magic Move, merely critical bug-fixes. This notification will be updated as development on react-native-shared-element progresses.

react-native-magic-move

Create magical move transitions between scenes in react-native ๐Ÿฐ๐ŸŽฉโœจ

MagicMoveGif

Usage

Installation

$ yarn add react-native-magic-move

Link the native extensions (* recommended but not required)

$ react-native link react-native-magic-move 

* The native extensions are recommended to get the best performance, but they are not required. This makes it possible to use react-native-magic-move with expo or react-native-web. If you're having trouble installing the native extensions, please see this guide on how to install them manually.

Wrap your app with the <MagicMove.Provider> context.

import * as MagicMove from 'react-native-magic-move';

const App = () => (
  <MagicMove.Provider>
    {...}
  </MagicMove.Provider>
);

Add the <MagicMove.{View|Image|Text}> component to your views. Whenever the Magic Move component is mounted while another Magic Move component with the same id is already mounted, then a magic transition between the components is performed.

import * as MagicMove from 'react-native-magic-move';

const Scene1 = () => (
  <MagicMove.Scene>
    <MagicMove.View id="logo" style={{
        width: 100,
        height: 100,
        backgroundColor: "green",
        borderRadius: 50
      }} />
  </MagicMove.Scene>
);

const Scene2 = () => (
  <MagicMove.Scene>
    <MagicMove.View id="logo" style={{
        width: 200,
        height: 200,
        backgroundColor: "purple",
        borderRadius: 0
      }} />
  </MagicMove.Scene>
);

react-navigation

When you are using react-navigation (or react-native-router-flux), then also install the following binding:

Documentation

Components

The following magic-move components are supported out of the box.

  • MagicMove.View
  • MagicMove.Text
  • MagicMove.Image

You can also create your own custom MagicMove components.

const MyMagicMoveComponent = MagicMove.createMagicMoveComponent(MyComponent);

// When creating a custom image component (e.g. FastImage) also specify the `image` attribute
// so that the `move` transition treats this as an image.
const MagicMoveFastImage = MagicMove.createMagicMoveComponent(FastImage, {ComponentType: 'image'});

// Full signature
/* MagicMove.createMagicMoveComponent(Component, {
  AnimatedComponent,
  ComponentType,
  ...props
});*/

Props

Property Type Default Description
id string (required) Unique id of the magic-move instance
transition function MagicMove.Transition.move Transition effect, see below
duration number 400 Length of the animation (milliseconds)
delay number 0 Amount of msec to wait before starting the animation
easing function Easing.inOut(Easing.ease) Easing function to define the curve
disabled bool false Disables transitions to this component
zIndex number 0 Z-index to control the drawing order of the rendered animation. A component with a greater z-index is always drawn in front of a component with a lower z-index.
useNativeDriver boolean true Use the native-driver
debug boolean false Enables debug-mode to analyze animations
useNativeClone boolean Use this prop to disable native clone optimisations for this component (when applicable).
imageSizeHint {width: number, height: number} Optional size of the image that may be provided as a hint to the transition function

Transitions

The following transition functions are available out of the box.

Transition Description
MagicMove.Transition.move (default) Moves the component while adjusting for border-radii and size. Takes the image resizeMode into account to create a seamless image transition without any stretching.
MagicMove.Transition.morph Morphs the shape, size and colours of the target to look like the source
MagicMove.Transition.dissolve Cross fade the source into the target
MagicMove.Transition.flip Flip the source to reveal the target on the backside (auto choose axis)
MagicMove.Transition.flip.x Flip the source to reveal the target on the backside (over x-axis)
MagicMove.Transition.flip.y Flip the source to reveal the target on the backside (over y-axis)
MagicMove.Transition.flip.xy Flip the source to reveal the target on the backside (over x- and y-axes)
MagicMove.Transition.shrinkAndGrow Shrink and let the source disappear while letting the target appear and grow
MagicMove.Transition.squashAndStretch Scale the target to the size of the source and squash and stretch to give it the illusion of momentum and mass

You can also create your own transition functions, see src/transitions for examples.

Scenes

Use <MagicMove.Scene> to mark the start of a scene within the rendering hierarchy. This is important so that Magic Move can correctly assess the destination-position of an animation. MagicMove.Scene is implemented using a regular View and supports all its properties.

Property Type Default Description
disabled bool false Disable transitions to this scene.
active bool This special prop is intended for integrating magic-move with 3rd party navigators such as react-navigation. Do not use it unless you know what you are doing. By setting it to true or false the navigation package can control which scene is active and which is no longer active. See react-navigation-magic-move for an example on how to use it.
debug boolean false Enables debug-mode to analyze animations
onWillAppear function Callback that is called when the scene is about to appear
onWillDisappear function Callback that is called when the scene is about to disappear

Context

When a magic-move is performend, a temporary clone of the source and/or target component is rendered onto the screen. Now imagine you have some animations that run when your component is mounted (e.g. Animatable.View), that would also mean these animations are run on the cloned component. This is probably not what you want and you might want to hide those components entirely in the cloned component. To do so you can use the <MagicMove.Context> API. It allows you to detect whether the component is rendered as a clone and whether it is the source or target of a magic move animation.

Example

<MagicMove.View>
  <MagicMove.Context>
    {({isClone, isTarget}) => (
      <Animatable.View animation={isClone ? undefined : 'zoomIn'} />
    )}
  </MagicMove.Context>
</MagicMove.View>

Resources

Disclaimer ๐Ÿฐ๐ŸŽฉ

Magic-move creates the illusion of transitioning/morphing components from one scene to another. It however doesn't actually move components to different scenes. As with real magic tricks, there will be situations where the illusion will not work for you. And as with magic tricks, you may need to "set the stage" (e.g. change some stuff in your app) to create the transition that you want. So now that you've received this reality check โœ…, go forth and create some bad-ass illusions.

License

MIT

Cool?

Do you think this cool and useful? Consider buying me a coffee!
Buy Me A Coffee

react-native-magic-move's People

Contributors

ijzerenhein avatar stpch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-magic-move's Issues

multiple transitions are overlapping

i have a big image and an icon that sits on top of it. Whilst transitioning each of them, the Image which should be behind the icon gets in front of it so that the transition of the icon is not visible.
I would suggest a zIndex prop where we can give each transition their own zIndex to decide which order they will follow. Let me know if this sounds possible for you.

Request to add product in Start React

Hello,

I am Maheshwari from team GeekyAnts.
On behalf of Start React, we add open source products which we find helpful to the community & also we provide credits to author itself.

Let me know if you are interested showcase your products in our open source website.
If yes, then I request you to add MIT Licence in your repo.

Looking forward to hear from you.

iOS build fails on RN 0.60.x with native dependencies

Expected behaviour

Building a [email protected] project that uses react-native-magic-move and its native dependencies successfully on iOS.

Show Actual behaviour

RN relies on CocoaPods from v0.60 onwards to autolink native dependencies.

Doing:

$ cd ios
$ pod install

I get a warning saying this library does not support autolinking.

I tried the classical manual link steps, but I get odd errors with React *.h files not found. My guess is that this library tries to fetch React deps from libraries folder instead of the newly pods I guess, but I am not sure.

Do you foresee an easy fix to support Cocoapods in the upcoming days?

I'm seeing this behaviour on

  • Device: any iOS simulator
  • Routing/transition library: [email protected]
  • React-native version: v0.60.4
  • react-native-magic-move version: v0.6.5

Same Nested Magic Item on Three Screen

I want to show the same item animated on three screen. I wrote simple code but there is logical error. The animations don't seem to make sense.

These is my code. Is there any wrong? Or there is another way? I've examined your all examples.

First screen:

1

**Second screen:**

2

**Third screen:**

3

warning requireNativeComponent running on web

WARNING in ./node_modules/react-native-magic-move/src/clone/NativeCloneComponent.js 205:73-95
export 'requireNativeComponent' (imported as 'requireNativeComponent') was not found in 'react-native-web/dist/index' (possible exports:

Webpack config

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, './release'),
    filename: 'bundle.js',
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: './index.html',
    }),
  ],
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        include: [
          path.resolve('src'),
          path.resolve('node_modules/react-native-magic-move'),
        ],
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react'],
            plugins: [
              'babel-plugin-react-native-web',
              '@babel/plugin-proposal-class-properties',
            ],
          },
        },
      },
    ],
  },
  devServer: {
    contentBase: path.join(__dirname, 'release'),
    compress: true,
    port: 4000,
    historyApiFallback: true,
  },
  resolve: {
    alias: {
      'react-native$': 'react-native-web',
    },
    extensions:[
      '.web.js',
      '.web.jsx',
      '.web.ts',
      '.web.tsx',
      '.js',
      '.jsx',
      '.ts',
      '.tsx',
    ]
  },
};

using packages

"dependencies": {
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-native-magic-move": "^0.6.6",
    "react-native-web": "^0.15.0"
  },
  "devDependencies": {
    "@babel/core": "^7.13.10",
    "@babel/plugin-proposal-class-properties": "^7.13.0",
    "@babel/preset-env": "^7.13.10",
    "@babel/preset-react": "^7.12.13",
    "babel-loader": "^8.2.2",
    "babel-plugin-react-native-web": "^0.15.0",
    "html-webpack-plugin": "^5.3.1",
    "prettier": "^2.2.1",
    "webpack": "^5.26.0",
    "webpack-cli": "^4.5.0",
    "webpack-dev-server": "^3.11.2"
  },

Transition without a navigator

Issue

Is it possible to use the library without any router at all? I would love to simply provide subsequent Scenes that get displayed without the use of any navigator, as in the example below. Is this a use-case you support, or even intend to support?

The library looks incredibly, I truly appreciate the work you've put into it. Keep up the good work.

I'm seeing this behaviour on

  • Device: Android 9
  • Routing/transition library: none
  • React-native version: v58.4
  • react-native-magic-move version: v0.5.0

Provide the code

import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View, Button } from 'react-native';
import * as MagicMove from 'react-native-magic-move';

export default class App extends Component {
  state = { scene: 1 };
  render() {
    return (
      <View style={{
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
      }}>
        <Button onPress={() => this.setState({ scene: this.state.scene + 1 })} title={'next'}></Button>
        <MagicMove.Provider>
          {this.state.scene === 1 && <MagicMove.Scene>
            <MagicMove.View id="logo" style={{
              width: 100,
              height: 100,
              backgroundColor: "green",
              borderRadius: 50
            }} />
          </MagicMove.Scene>}
          {this.state.scene === 2 && <MagicMove.Scene>
            <MagicMove.View id="logo" style={{
              width: 300,
              height: 300,
              backgroundColor: "blue",
              borderRadius: 10
            }} />
          </MagicMove.Scene>}
          {this.state.scene === 3 && <MagicMove.Scene>
            <MagicMove.View id="logo" style={{
              width: 200,
              height: 200,
              backgroundColor: "red",
              borderRadius: 50
            }} />
          </MagicMove.Scene>}
        </MagicMove.Provider>
      </View>
    );
  }
}

Support for hooks

As suggested in this issue I implemented a similar approach as examples/native/src/explorer/ExplorerView.js, for triggering a transition without a navigator. However, it seems that hooks are not supported.

Expected behaviour

When using hooks to manage state, transitions should work as they do with class components.

Show Actual behaviour

No transition occurs.

Provide the code

The demo and code can be seen on this snack.

You'll notice a couple of things

  1. Upon first load, the functional component never works
  2. Upon first load, the class component works
  3. When going back and forth between the two, you'll notice additional odd behavior

RNMagicMove.podspec position

please move ios/RNMagicMove.podspec to /RNMagicMove.podspec
for react-native link react-navigation-magic-move

No animation when using react-navigation SwitchNavigator

Hi! Love this library!

But I'm having problems morphing one element into another when elements are on separate stacks / switch navigators.

All the examples are in react-native-router-flux which I'm totally unfamiliar with.

could you make some very simple examples in plain react-navigation v3 where elements are on separate stacks?

I'll show it exactly:

this is App.js

import React from 'react';
import { createAppContainer } from 'react-navigation';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';

import getStore from '@redux';
import AppNavigator from '@navigation';
import NavigationService from '@navigation/service';

import * as MagicMove from 'react-native-magic-move';
import "react-navigation-magic-move";


const { Store, Persistor } = getStore();
const AppContainer = createAppContainer(AppNavigator);


export default class App extends React.Component {

  render() {
    return (
      <Provider store={Store}>
        <PersistGate loading={null} persistor={Persistor}>
          <MagicMove.Provider>
            <AppContainer ref={navigatorRef => { NavigationService.setTopLevelNavigator(navigatorRef); }} />
          </MagicMove.Provider>        
        </PersistGate>
      </Provider>
    );
  }
  
}

Navigation

...
export default createSwitchNavigator({
  one: StackOne,
  two: StackTwo
});

StackOne ( FAB that is going to morph to a View with flex: 1 on a StackTwo

render() {

  let MagFAB = MagicMove.createMagicMoveComponent(FAB);

    return (
      <MagicMove.Scene style={styles.container}>

        ...

        <MagFAB 
          id="FABtoView"
          icon="md-add" 
          color={colors.secondary} 
          icolor="#FFFFFF" 
          onpres={()=>this.props.navigation.navigate('two')} />

      </MagicMove.Scene>
    );
  }
}

StackTwo

render() {
  return (
    <MagicMove.Scene style={{flex: 1}}>
      <MagicMove.View id="FABtoView" style={{flex:1}}>
        <ScrollView style={styles.container}>
          ...
        </ScrollView>            
      </MagicMove.View>
    </MagicMove.Scene>
  );
}

And the FAB element is:

  <TouchableWithoutFeedback onPress={this.handlePress}>
    <View style={[styles.fab, { backgroundColor: this.props.color ? this.props.color : '#5354FF' }]}>
      <Icon.Ionicons name={this.props.icon} size={24} color={this.props.icolor} />
    </View>
  </TouchableWithoutFeedback>

const styles = StyleSheet.create({

  fab: {
    alignItems: 'center',
    justifyContent: 'center',
    position: 'absolute',
    bottom: 32,
    right: 32,
    borderRadius: 1000,
    height: 56,
    width:  56
  }

});

What happens?
So I'm on StackOne and I click the FAB and it navigates me to a StackTwo properly, no errors, but also no animation. No effect.

I tried to do the same but instead of Switch navigator I used a StackNavigator, like this:

export default createStackNavigator({
  one: ScreenOne,
  two: ScreenTwo
}, ...);

and even worse - got error that measureLayout is not a function, both ways (StackOne -> StackTwo and when going back).
// edit, more specifically:
component.getRef().measureLayout is not a function. (In 'component.getRef().measureLayout((0, _reactNative.findNodeHandle)(sceneRef), onSuccess, onFail)', 'component.getRef().measureLayout' is undefined)

Stack trace:
  node_modules\react-native\Libraries\YellowBox\YellowBox.js:59:8 in error
  node_modules\react-native-magic-move\src\Animation.js:145:20 in errorHandler
  node_modules\promise\setimmediate\core.js:37:14 in tryCallOne
  node_modules\promise\setimmediate\core.js:123:25 in <unknown>
  node_modules\react-native\Libraries\Core\Timers\JSTimers.js:152:14 in _callTimer
...

What am I missing?

pod install failed

pod install failed!!
please add s.homepage value in RNMagicMove.podspec, thanks

Simple example doesn't show transition

Expected behaviour

A transition.

Show Actual behaviour

Can't actually see a transition with current setup.
Snack

I'm seeing this behaviour on

  • Device: Expo
  • Routing/transition library: None

Provide the code

import * as React from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import * as MagicMove from 'react-native-magic-move';

const Scene1 = () => (
  <MagicMove.Scene>
    <MagicMove.View
      id="logo"
      style={{
        width: 100,
        height: 100,
        backgroundColor: 'green',
        borderRadius: 50,
      }}
      transition={MagicMove.Transition.dissolve}
      debug={true}
      duration={1000}
    />
  </MagicMove.Scene>
);

const Scene2 = () => (
  <MagicMove.Scene>
    <MagicMove.View
      id="logo"
      style={{
        width: 200,
        height: 200,
        backgroundColor: 'purple',
        borderRadius: 0,
      }}
      transition={MagicMove.Transition.dissolve}
      debug={true}
      duration={1000}
    />
  </MagicMove.Scene>
);

const CurrComp = props => {
  return (
    <TouchableOpacity
      onPress={() => props.setState(!props.state)}
      style={{ height: 100, backgroundColor: 'blue' }}>
      <Text>Hello</Text>
    </TouchableOpacity>
  );
};
const App = () => {
  const [state, setState] = React.useState(true);

  return (
    <MagicMove.Provider>
      <CurrComp state={state} setState={setState} />
      {state ? <Scene1 /> : <Scene2 />}
    </MagicMove.Provider>
  );
};

export default App;

Question: Can I use magic move for two components within the same scene?

I'm looking to achieve an effect like the example here: https://dribbble.com/shots/3290017-In-chat-Broadcasting

The GIF above shows an image sending, like one does from iMessage, and animating from the text composer to the actual messages list.

Do you have any thoughts on how I could structure the scenes to achieve something like this? If not, I can keep taking a stab at it anyway.

I really love what you've done with the library, it's super cool. Can't wait for the new update you tweeted about.

Not working with React Navigation without enabling Remote Debug Debugging

Expected behaviour

I expect the shared transition to work without enabling Remote JS Debugging

Show Actual behavior

The shared transition doesn't work after navigating to another route where I have Magic.View component with the same id on the current screen am navigation from.
I keep getting an error: "parameter must be a descendant of this view". But if I enable Remote JS Debugging. it will work as expected.

I'm seeing this behavior on

  • Device: (e.g. Android 7.1, Honor 5X, Android 6 Infinix HOT Note)
  • Routing/transition library: (e.g. react-navigation v3.11.0)
  • React-native version: v0.59.8
  • react-native-magic-move version: v^0.6.2

Provide the code

if the Remote JS debugging is enabled. Everything works fine and I don't see any console error message. But when I stop Remote JS Debugging. I got back the same error when navigation to the new screen parameter must be a descendant of this view

Can't try with Expo

Expected behaviour

Try with Expo

Show Actual behaviour

Getting this error message when try it with Expo: The experience you requested is not viable by you. You will need to log in or ask the owner to grant you access.

I'm seeing this behaviour on

N/A

Provide the code

N/A

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.