Giter VIP home page Giter VIP logo

react-morph's Introduction

React Morph ๏ธ๐Ÿฆ‹

Morphing UI transitions made simple

npm version

Magically animates one element into another just by tagging the first and last state.

Getting Started ๐Ÿ›

npm install react-morph
# or
yarn add react-morph

Import the useMorph hook.

const morph = useMorph(options);

Then spread the props to the elements you want to morph.

<img {...morph} src="larva.png" width="50">
<img {...morph} src="butterfly.png" width="80">

Make sure you have just ONE element rendered at same time.

Simple Example ๐Ÿฆ‹

  1. Create two states as you normally would (HTML + CSS).
  2. Call useMorph hook.
  3. Spread the elements you want to morph with {...morph}
  4. Add and remove the element from the DOM
import React from 'react';
import { useMorph } from 'react-morph';
() => {
  // Handle toggle state as you normally would.
  const [toggle, setToggle] = useState(true);
  const morph = useMorph();

  return (
    <div>
      <button onClick={() => setToggle(!toggle)}>Let's morph!</button>
      <br />

      {toggle ? (
        <img {...morph} src={larva} width="30" />
      ) : (
        <img {...morph} src={butterfly} width="80" />
      )}
    </div>
  );
};

Please check the documentation.

Features ๐ŸŒŸ

  • Simplicity
  • No hardcoded absolute positions
  • All GPU accelerated props
  • No layout or paint browser rendering

Live Demos

react-morph's People

Contributors

andywer avatar brunnolou avatar byronhsu avatar colinhoernig avatar mattgperry avatar michaelmior 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-morph's Issues

Error Compiling

Getting a compilation error adding react-morph to an empty create-react-app project :(

Failed to compile.

./node_modules/react-morph/lib/index.js
Module not found: Can't resolve 'popmotion/lib/animations/keyframes' in '.../node_modules/react-morph/lib'

Images resizing only works when changing routes

I wanted to animate an image to resize but this only seems to work when I use the player example and have it animate between routes.

Using it like this makes the images disappear and appear at the end of the animation, the div container animates correctly though, it only seems to be an issue with images. Also the image type makes no impact whatsoever, png, svg, jpg, etc... none animate correctly.

App.js

import React, { Component, useState, useEffect } from "react";
import { createGlobalStyle } from "styled-components";
import { useMorph, useMorphKeys, presets } from "react-morph";
import { BrowserRouter as Router, Route } from "react-router-dom";

import "mapbox-gl/dist/mapbox-gl.css";
import { Container } from "./App.style";
import Header from "./components/Header";
import Map from "./components/Map";
import LoadingScreen from "./views/LoadingScreen";
const GlobalStyle = createGlobalStyle`
  html {
    height: 100%;
    width: 100%;
  }
  body {
    height: 100%;
    margin: 0;
    width: 100%;
    & #root {
      height: 100%;
      width: 100%;
    }
  }
`;

function App() {
  const [loaded, setLoaded] = useState(false);
  const morph = useMorph();
  const morphs = useMorphKeys(["logo", "container"]);

   return (
    <Container onClick={() => setLoaded(!loaded)}>
        <GlobalStyle />
        {!loaded ? <LoadingScreen morphs={morphs} /> : <Header morphs={morphs} />}
    </Container>
  );
}

export default App;

Loadingscreen:

import React from "react";
import logo from "../../assets/logo.png";
import { Container, Logo } from "./loadingScreen.style";

const LoadingScreen = ({ morphs }) => (
  <Container {...morphs.container}>
    <img {...morphs.logo} src={logo} />
  </Container>
);

export default LoadingScreen;

Header:

import React from "react";
import logo from "../../assets/logo.png";
import { HeaderContainer, Logo, Menu, Icon, MobileMenu } from "./header.style";
import doIcon from "../../assets/icons/do.svg";
import drinkIcon from "../../assets/icons/drink.svg";
import eatIcon from "../../assets/icons/eat.svg";
import seeIcon from "../../assets/icons/see.svg";

const Header = ({ morphs }) => (
  <HeaderContainer {...morphs.container}>
    <img {...morphs.logo} src={logo} />
    <Menu>
      <Icon icon={drinkIcon} />
      <Icon icon={eatIcon} />
      <Icon icon={seeIcon} />
      <Icon icon={doIcon} />
    </Menu>
    <MobileMenu>
      <Icon icon={drinkIcon} />
    </MobileMenu>
  </HeaderContainer>
);

export default Header;

Declarative API

Right now using go() imperatively doesn't feel right and limits the cases where react-morph can be applied. For example a state change can only be triggered from inside ReactMorph. In the real world this state comes from a Router, redux or a component somewhere else.

What I would love to see as an API would be a prop on the ReactMorph component that controls which state to show. E.g. <ReactMorph go={1}>.

How to create useMorph instances dynamically and share them (useMorphId?)

I have a list of posts, and I have the post.
The list item is visually very similar to the post header and I'm trying to morph it.

But I have two problems here: I need to create morph 'instances' dynamically, somethink like id based, "on demand", and I need to share this instance to different files/components.

Something like this:

listing page:

const PostTeaser = ({ ...post }) => {
  const useMorphId(`post-${post.id}`)
  return <div {...morph}>...</div>
}

const PostList = ({ posts }) => (
  <div>{posts.map(post => <PostTeaser {...post} key={post.id} />)}</div>
)

post page:

const PostHeader = ({ ...post }) => {
  const useMorphId(`post-${post.id}`)
  return <div {...morph}>...</div>
}

const PostPage = ({ post }) => (
  <div>
    <PostHeader {...post} />
    <div>...</div>
  </div>
)

After many attempts and tested workarounds, I was able to do it using a Context that saves the instances by id in its state, and a hook that ask for a instance by id: if it doesn't exist, it creates, if it exists, it uses the existing one.

Code: https://codesandbox.io/s/nervous-mendeleev-ynrbq
(the magic is in morpher.js, and morphs are in pages/posts.js and pages/post.js)

But... questions:

  1. Is there an easier way to satisfy this use case?
  2. Is there a more trivial way to share instances without prop drilling or context?

Support for React Portals in the second state

I do not know if it is already possible but it would be interesting for create modals for example.

Idea of โ€‹โ€‹how to allow this behavior: Only pick the styles (dimension, position, ...) when go to the second state and the portal is already mounted in the DOM.

Real life examples

It'd be great if you could include a list of React apps that use this for their morphing transitions. This would help new potential users get an idea of how it can be implemented in production apps.

Morphing wrapped with flex

It looks like whenever react-morph is wrapped with a layout that utilizes the flex-direction CSS properties (EX: flex-direction: row) it causes some weird behavior on the first morph..

Resizing the window breaks the morph animation

Hi, thanks for the cool library!
I've noticed that resizing the page breaks the animation:
screen shot 2018-03-05 at 13 57 48

To reproduce - load the storybook, resize the page (or in my case i opened the devtools docked to right) - trigger transition.

I don't really know if it's storybook specific, but just a heads up

Example for how to `go` in function

An example for how to go in function will be great. Thanks for the cool package!

handleGo = () => {
  // ...
}

<ReactMorph>
  {({ from, to, fadeIn, go }) => (
    <div>
      <a onClick={this.handleGo}>
        <strong {...from("title")}>ReactMorph ๐Ÿ›</strong>
        <br />
        <p {...from("description")}>Morphing transitions was never so easy!</p>
      </a>

      <div>
        <h1 {...to("title")}>ReactMorph ๐Ÿฆ‹</h1>
        <br />
        <h2 {...to("description")}>Morphing transitions was never so easy!</h2>

        <a onClick={() => go(0)} {...fadeIn()}>
          Back
        </a>
      </div>
    </div>
  )}
</ReactMorph>

Dependency issue

When I import the library import ReactMorph from 'react-morph' I get this error :

Failed to compile
./node_modules/react-morph/lib/index.js
Module not found: Can't resolve 'popmotion/lib/easing' in 'F:\morph-animation\node_modules\react-morph\lib'

SSR error

Hi,

I was trying to run the example on next.js but I got this issue:

ReferenceError: document is not defined
    at Object.<anonymous> (/node_modules/react-morph/lib/index.js:374:18)

My full code is:

import ReactMorph from "react-morph";

let something = "ricky";
if (process.browser){
  something = <ReactMorph>
    {({ from, to, fadeIn, go }) => (
      <div>
        <a onClick={() => go(1)}>
          <strong {...from("title")}>ReactMorph ๐Ÿ›</strong>
          <br />
          <p {...from("description")}>Morphing transitions was never so easy!</p>
        </a>

        <div>
          <h1 {...to("title")}>ReactMorph ๐Ÿฆ‹</h1>
          <br />
          <h2 {...to("description")}>Morphing transitions was never so easy!</h2>

          <a onClick={() => go(0)} {...fadeIn()}>
            Back
          </a>
        </div>
      </div>
    )}
  </ReactMorph>;
}

export default () => something;

Can't wait to use this lib on our upcoming landing pages!

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.