Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React based Framer #158

Closed
koenbok opened this issue Jan 18, 2015 · 65 comments
Closed

React based Framer #158

koenbok opened this issue Jan 18, 2015 · 65 comments
Labels

Comments

@koenbok
Copy link
Owner

koenbok commented Jan 18, 2015

Maybe we can leverage the virtual dom from react to get:

  1. Closer to production
  2. Offload more advanced memory management (dom/events)
  3. Get performance improvements
@koenbok koenbok added the wanted label Jan 18, 2015
@koenbok
Copy link
Owner Author

koenbok commented Jan 25, 2015

I played around with this today. I built the most bare bones version of Framer on top of React (Context, Layer, Tween, Render). You can find it here: http://cl.ly/1M0X241G1X2y and to run it you need http://cactusformac.com.

First of all, I am no react/virtualdom expert so I might be doing things wrong. That is one of the reasons to post it here :-) This is a work in progress.

  • The animation performance is just slower because of the dom diffing. This system diffs the dom every 16ms for 100 layers. On my desktop system in Chrome that takes somewhere between 2-4ms. That is very quick but still almost 20% of your rendering budget per frame. In the current Framer we just set the element style as quickly as we can and that's it. On my iPhone 6 I can barely render 50 layers at 60fps this way.
  • I think that the virtual dom really shines for altering the dom, not for just style updates. And while we do modify the dom with Framer, the majority is style updates for animations. Maybe there is some way where we can do style updates directly and let the virtual dom handle dom alterations.

Next up: event system.

@iamralpht
Copy link

Sweet! Last time I seriously used React (8 months ago) I needed to set style directly to get perf for pan/pinch gestures. I did this by creating a mixin FastStyleMixin which added a dictionary for style properties and a setStyleProperty method. Internally it just called getDOMNode() and assigned all of the styles. It listened for the lifecycle hooks componentDidMount and componentDidUpdate and re-applied all of its styles in there, too.

I actually really liked this because I still had the robust encapsulation that's so nice about React, and I hadn't completely violated its model to get the performance I wanted (i.e.: there were no sharp edges exposed by my hack, so it was pretty nicely contained). It's good to have nice escape hatches :).

@koenbok
Copy link
Owner Author

koenbok commented Jan 25, 2015

That sounds like a great approach for take two! Thanks!

@koenbok
Copy link
Owner Author

koenbok commented Jan 25, 2015

Note to self: so a simpler version of this: https://github.com/elierotenberg/react-animate/blob/master/AnimateMixin.js [update: hmm not really]

@irvinebroque
Copy link

@koenbok - React-tween-state is also worth looking into for handling tweening and requestAnimationFrame

https://github.com/chenglou/react-tween-state

@koenbok
Copy link
Owner Author

koenbok commented Jan 25, 2015

Ha, I was just looking at that. Thanks!

@cleercode
Copy link

Very interesting. The thing about the virtual DOM being good for DOM manipulation and not just style updates seems accurate and is an important insight. This got me thinking a lot more about why a Framer/React hybrid would be interesting. In retrospect, I suspect that a virtual DOM-based method can't offer any benefits over Framer's current method.

I think actually the most interesting part about React is not the virtual DOM as an implementation method but the user-facing API, allowing people to reason statically and declaratively about the state of an application rather than in a series of manipulations of the original state. Here's an article about this. The virtual DOM is an implementation detail that makes declarative programming able to be relatively performant (but probably not as performant as imperative DOM manipulations, style changes, etc.).

So I think there may be some interesting thought around whether that'd be a useful way to think about the Framer API. It seems like the Tween part of your demo is an example of this: the layer.x = layer.tweenA.next() API instead of `layer.animate properties: layer.x: ..."

The approach I think I'd be interested in is starting with an API: what would a more declarative Framer API look like? Would it even be significantly different than the Framer of today? Would it be more useful or make more sense to prototypers? It's unclear to me; the declarative model of reasoning makes a lot of sense for states but might not be useful for things like animations and gestures. React is notoriously unclear on how to implement animations, probably because you can conceptualize them fitting in with the React model in many different ways. And given that Framer mostly needs to make style changes, not DOM changes, the declarative model of reasoning about states isn't as necessary; it's relatively easy to implement that sort of system for style changes (Framer's state system is already basically like this) but difficult for the DOM.

@koenbok
Copy link
Owner Author

koenbok commented Jan 25, 2015

@cleercode I hear you on the declarative api. I'd love to read more ideas on this. I know that more people like https://twitter.com/ianh_ are working on this: https://twitter.com/andy_matuschak/status/557282393212878849

In terms of the Framer React port I'm still optimistic that dom alterations performance and (presumably) better memory/event handling could be wins for Framer. So if I can make something work like @iamralpht suggests we could have both.

One thing that for example could be cool, but I'm not sure of, is that our TableComponent won't have to include logic (or maybe only partial) for re-using layers for performance while you scroll. React would re-use dom elements behind the screens. If this turns out to be true, that would be amazing.

@koenbok
Copy link
Owner Author

koenbok commented Jan 28, 2015

I think we just got one more good reason for a react based framer: native. I guess we'll have to see how it works.

@subtleGradient
Copy link

FWIW, I tried to convince you to do this forever ago ;)

@koenbok
Copy link
Owner Author

koenbok commented Feb 2, 2015

Ok I tried @iamralpht approach and I have a nice version that only uses dom diffing for structure but sets the style directly on the elements in an animation look. As expected, performance is equal to the current Framer.

I just don't know for sure if I did the React part right, I pass that layer as a prop to the component and then set the dom element after mount on the layer. I feel like @iamralpht had a cleaner way.

http://cl.ly/3d303o1e3Y34

@iamralpht
Copy link

I'm going to be bridging Slalom and React soon, so I'll have a go and doing what I said cleanly for that :). I'll post a link when it's up.

@bengotow
Copy link

bengotow commented Feb 8, 2015

Hey gang—this is really, really interesting stuff. My team is building a mail client on top of React (which will actually ship as a desktop app inside of Atom Shell), and I'd love to be able to use FramerJS to drive animations. I know "production-facing animation framework" isn't the intention of Framer, but Atom Shell means we only target the latest Chromium! In a perfect world, our designer would be able to save an animation in Framer Studio and see the change in the running app.

For what it's worth, it would be amazing if ReactLayer was actually a React Mixin that could be applied to any component. This Drag and Drop library for React is a great example of a Mixin that extends a React component with new styles, event hooks, etc: https://github.com/gaearon/react-dnd. It's also very nice React, imo!

The really cool bit is this: <div {...this.dropTargetFor(ItemTypes.IMAGE)}>

In your render function, you add this bit of code, and it allows the mixin to add styles, event handlers, etc. to the div. It would be totally incredible if something like this allowed Framer to add children to the element, styles in preparation for animation, etc. (Though I agree with the conversation here that tweening should not invoke the render cycle. That would be especially important if the render method included external code.)

@tehfailsafe
Copy link

Any update on this idea? Would love to hear how/if it's progressing!

@subtleGradient
Copy link

Relevant: http://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#other-languages

Defining React components using CoffeeScript is now possible with the latest release of React v0.13.0

div = React.createFactory 'div'

class Counter extends React.Component
  @propTypes = initialCount: React.PropTypes.number
  @defaultProps = initialCount: 0

  constructor: (props) ->
    super props
    @state = count: props.initialCount

  tick: =>
    @setState count: @state.count + 1

  render: ->
    div onClick: @tick,
      'Clicks: '
      @state.count

@chadobado
Copy link

Also love to hear how this is progressing and if it formally made it into the roadmap, thanks.

@chadobado
Copy link

@koenbok - now that React Native has been open sourced, can share a detailed thread on how they are approaching animation. Hopefully helpful to you.

facebook/react-native#46

@josefrichter
Copy link

Any updates here? I know Framer is intended for prototyping, but being able to get native app via React Native (+Backbone.js probably) could be a game changer..

@koenbok
Copy link
Owner Author

koenbok commented Sep 6, 2015

Hey @iamralpht I have a pretty simple react based Framer version here and it works with most prototypes. The implementation is pretty naive, a full render for each animation frame.

So you can definitely tell the perf is worse on mobile. I was wondering if you ever got to make (or have seen) the approach you describe above where you:

  • Store every animatable css property (source) value in the React Component
  • But rather then a full diff, update the properties directly in the case of an animation

@vjeux
Copy link

vjeux commented Sep 6, 2015

I recently gave a talk about the exact problem you are facing at React Rally and the slides are here: https://speakerdeck.com/vjeux/react-rally-animated-react-performance-toolbox

If you need to change the structure of the DOM, then you need to re-render and implementing shouldComponentUpdate is a must if you do not want everything to re-render.

Now, if you just need to update a scalar value such as top/left/width/height... then you can implement Data Binding on-top of React. See the slides starting at slides 29. This gives you the ability to do updates as fast as you can do raw dom mutations.

We are using this technique in React Native with the library called Animated. We're still working on the documentations but you can get information in those 4 links:

Let me know if you need more information or code review, I'd be happy to help out!

@iamralpht
Copy link

I really like Animated -- have been thinking about making Slalom run on top
of Animated values next time I get to make a pass at it.

@vjeux is there a module for using Animated with plain web React?
On Sun, Sep 6, 2015 at 12:45 PM Christopher Chedeau <
notifications@github.com> wrote:

I recently gave a talk about the exact problem you are facing at React
Rally and the slides are here:
https://speakerdeck.com/vjeux/react-rally-animated-react-performance-toolbox

If you need to change the structure of the DOM, then you need to re-render
and implementing shouldComponentUpdate is a must if you do not want
everything to re-render.

Now, if you just need to update a scalar value such as
top/left/width/height... then you can implement Data Binding on-top of
React. See the slides starting at slides 29. This gives you the ability to
do updates as fast as you can do raw dom mutations.

We are using this technique in React Native with the library called
Animated. We're still working on the documentations but you can get
information in those 4 links:

Let me know if you need more information or code review, I'd be happy to
help out!


Reply to this email directly or view it on GitHub
#158 (comment).

@vjeux
Copy link

vjeux commented Sep 6, 2015

Animated for React web is on my todo-list. I've got a hacky version working with forceUpdate (not dom mutations) here: http://fooo.fr/%7Evjeux/fb/animated-docs/ but am working on cleaning it up and pushing it for real. Hopefully soon.

@koenbok
Copy link
Owner Author

koenbok commented Sep 7, 2015

Ok this gives me more then enough to move forward :-) Thanks so much. I'll keep you posted.

@chadobado
Copy link

@vjeux thanks for chiming in here, excited to see this move forward

@wemakeweb
Copy link

@vjeux any updates for the animated react web version?

@vjeux
Copy link

vjeux commented Oct 2, 2015

@wemakeweb There's an initial web implementation commit here: facebook/react-native@a50b4ea but needs more work.

@venkysetty
Copy link

@vjeux What are the steps for building JS bundle for your initial web implementation commit? Any further updates on using dom mutation?

@jchavarri
Copy link
Contributor

@koenbok Is this Fabric animation component for React helpful for the new React-based-Framer?

I found these paragraphs on the blog post interesting:

The CSS transition properties modeled this pretty well: “whenever this other property is changed, apply that change gently.” The animations are declared, the transitions are derived. Keyframes are less successful: “when this is applied, set these properties to these specific values over time.” These semantics lead to CSS keyframe animations being applied at undesirable times (such as initial render), always from the very beginning, and without any means of dynamically modifying them.

To integrate smoothly with React’s declarative nature, we’ll need our animation behavior to be fully described by the output of our render methods: a desired end state.

I wonder how complex animations would be possible with this approach. In the Github repo they mention:

Unlike what you get from passing a style hash to VelocityComponent's animation property, Velocity "UI pack effects" can have chained animation calls and specify a defaultDuration, and also can take advantage of stagger and reverse properties on the VelocityComponent.

Blog post: https://fabric.io/blog/introducing-the-velocityreact-library
Github: https://github.com/twitter-fabric/velocity-react

@jchavarri
Copy link
Contributor

If the goal of using React is just the diffing efficiency, I found other alternative that is maybe simpler and would better fit Framer as they update the DOM just once per frame, keeping the rendering performant:

virtual-dom together with main-loop

That said, I 100% agree with @cleercode on the user-facing API and how React enforces composability and declarative reasoning. I would love to build reusable, declarative, animated components that respond at 60fps. In my mind there's something like:

  • Ease of use of Framer, targeted to mobile and very fast to get up and running
  • An animation API similar to react-motion but including Framer animation states, animators, etc
  • With prebuilt mobile components: scroll, page, slider (like Framer) but declarative (like react-canvas)
  • With a simple adaptative layout engine, it can be flex or any other

I think I just want React Native + Framer 😂

I have two questions:

  • @koenbok Do you think a more declarative API for Framer would help or go against the project interest and goals? I say this because frankly imho an imperative API is much simpler to understand for newcomers to the development world than a more declarative one
  • @vjeux In order to avoid data binding, would there a way on the current React DOM module to change the batching strategy to accumulate updates and apply them on every frame requested? I saw that Pete Hunt implemented it some time ago, but it seems abandoned. Or would it be better to "just" implement another rendering engine like react-canvas or react-three?

@breezykermo
Copy link

Would also be very interested in helping out with this! I've been developing with React Native for the past few months, and am now messing with Framer, and if you could port UI components directly into a React or React Native app through a React-based Framer, that would be incred.

@JesseBilsten
Copy link

This would be very beneficial to us as well. Our company has all our styleguide elements as react components that could be easily included into a framer project and then mocked up into a prototype.

@ghost
Copy link

ghost commented Aug 31, 2016

-1 let's keep Framer simple and easy to use. Building React apps brings a world of complexity and maintainability concerns to the table, and that's not the kind of headache designers or UI engineers need while prototyping.

@ghost
Copy link

ghost commented Nov 30, 2016

Seems to me that being afraid of additional complexity and maintainability is an excuse for not keeping it DRY, no? An animation sequence that translates directly from Framer to my App is essentially what keeps me from repeating myself.. how the translating is happening should be what I'm willing to learn.. not be afraid of, right? If we don't push tools.. then tools won't be better..

@ghost
Copy link

ghost commented Nov 30, 2016

Perhaps when more designers pick up React and ES6 we'all be all set. Until then just prototype in React Native. There are some awesome boilerplates and UI kits to choose from.

@chrislloyd
Copy link

chrislloyd commented Apr 14, 2017

Bump on this issue now that React Fiber is on the horizon (with better performance for animations). Being able to have a React context in Framer would be great for designers being able to prototype with React components from our design system.

@ghost
Copy link

ghost commented Apr 14, 2017

Please don't use React

@ghost
Copy link

ghost commented Apr 26, 2017

FYI https://github.com/airbnb/react-sketchapp. It does not change my opinion about using React, like it or not.

@jemgold
Copy link

jemgold commented Apr 27, 2017 via email

@jordandobson
Copy link
Contributor

jordandobson commented Apr 27, 2017 via email

@ghost
Copy link

ghost commented Apr 27, 2017

I'll put up a dozen chocolate chip cookies (we're talking Otis Spunkmeyer quality here folks) to the first designer that does it with Redux using Functional stateless components. Hint: You're going to need a developer to acutally do the work.

@andrictham
Copy link

andrictham commented Apr 27, 2017

@JHabdas @jongold There’s a learning curve with React and Redux, but there’s also a learning curve with Framer and Coffeescript.

Also, react-redux is a more “natural” way to think about interactions: a user event dispatches an action which results in a state change. The UI then reflects that state change. As a designer, I’m already thinking about it in these terms. If I prototype in react-redux, I’ll be self-documenting my design intent in a lossless form. Currently, I have to: prepare a Sketch file, write functional specs, and deliver a prototype.

One benefit of prototyping in code is you can use existing components from the world/your team which speeds up prototyping. Very rarely have I worked on a project where we designed everything from scratch, usually some third-party UI component is used.

Even if we make components from scratch, we still have to communicate how the component API will be designed (the text that should go in there, type of image, color variants, icon options, etc). Sketch symbols is one way, or perhaps a spec doc, but that’s very time consuming. If we are already spending time prototyping in code, why wouldn’t we just go ahead and do it in code too?

With designers picking up RxJS now, I don’t think it’s that hard to imagine some using Redux for prototyping.

@jemgold
Copy link

jemgold commented May 5, 2017

@JHabdas perhaps it's time to cool off with your hate or React, this isn't an appropriate forum for it. Btw Dan Abramov replied to everything in that post - https://medium.com/@dan_abramov/hey-thanks-for-feedback-bf9502689ca4

@ghost
Copy link

ghost commented May 5, 2017

Btw Dan Abramov replied to everything in that post

Is he a designer working on Framer?

@BLamy
Copy link

BLamy commented May 5, 2017

@JHabdas I'm actually having a hard time understanding why you are being so hostile in a thread like this. If react isn't your cup of tea that's fine but you're going a little overboard.

For the record, Dan Abramov works on React and is regarded as a pretty reliable source for responding to a thread like that.

@ghost
Copy link

ghost commented May 5, 2017

I'm actually having a hard time understanding why you are being so hostile in a thread like this.

If by "hostile" you mean openly espressing my opinion in a repo for a product I hold a paid license for I challenge your perception of the difference between hostility and candor. I've built enterprise with React. I've built enterprise with Redux. And I know who Abramov is. But you're taking us off-topic. Because this is a thread about React. Which is slow compared to Preact. And overengineered. And not friendly to designers as I mentioned earlier. But thanks for your input.

@tehfailsafe
Copy link

Just reread the whole thread, and pretty sure it's a simple misunderstanding. The derailment came when @JHabdas said "-1 let's keep framer simple".

See, no one was talking about using react inside of framer, or changing the designers build prototypes on framer. I'm not sure how you came to the conclusion that designers would need to learn redux and routing in order to use framer? No one mentioned using the react api in framer before that...

The proposal was to use react virtual dom to get better performance out of framer. Then another thought was that if framer was built on react under the hood, could we export our completely normal framer coffeescript layers and animation through some conversion process and get react component out of the other end to support our engineering team.

I think we can all agree that no one wants to be writing react inside of framer, so let's stop derailing then other valid ideas in this thread.

@samjt
Copy link

samjt commented Jul 18, 2017

I would be very keen to see the ability to use react components within the Framer environment.

A lot of our front end production UI is written in React, so being able to reuse those components inside Framer would make prototyping new concepts much quicker.

@ghost
Copy link

ghost commented Jul 18, 2017

[...] being able to reuse [...] would make prototyping new concepts much quicker.

If by prototyping going faster you mean to shorten the cycle time between design and going live I believe we may have discovered the true desire here. Question is, why not then just build the design prototype in React?

@samjt
Copy link

samjt commented Jul 18, 2017

Partly, but also to make it easier to have matching behaviours between the 'real' client and a mockup that we're testing some functionality on.

Lets say I have a list view with some new functionality added to it, to be able to reuse the existing list view component and not have to rebuild it in Framer would mean time-to-prototype becomes much faster. We could accomplish the same thing with pure React, but then it become harder for Designers to take on that process.
Alternatively we could build modules in Framer that duplicate the React behaviour, but then we'd have to keep those in sync as changes happen in production.

@ghost
Copy link

ghost commented Jul 18, 2017

This is purely hypothetical... But if we presented an artist with a blank canvas and gave them charcoal with which to draw, would some of them not yearn for paint?

@samjt
Copy link

samjt commented Jul 19, 2017

Well a purely hypothetical response would be:

In our company we draw everything in charcoal, and have a big stock of charcoal over here.
But for your prototypes, here is a Hazel sapling. Plant it over there, coppice it, then burn it to charcoal yourself in order to start making prototypes that look like the real thing.

No, you can't use any of our charcoal, because that's 'production only' charcoal, not for prototyping.

@robinsonkwame
Copy link

Would love to see this as well, might be worth pitching in funding for an open source implementation of this. Note you can convert coffeescript to javascript and Framer is switching to JS soon, both of which make things easier. My use case is to save time re-implementing UI behavior design into a mobile deployable framework.

@ghost
Copy link

ghost commented Sep 12, 2017

CoffeeScript has always transpiled to JS. It exists because it's a more expressive language and hides the bad parts of JS, of which there are many. I can tell you with confidence if Framer moved to JS they would alienate the majority of their exiting power users and fall quickly to a competitor.

@robinsonkwame You linked to a page hidden behind a signon page—it looks like graffiti to me. Do you have a resource you can share on the open web?

@robinsonkwame
Copy link

@JHabdas: Sorry, that's a Facebook link to the Framer Facebook group page. I can't provide an alternative link but the very last post in that thread, in August 2017, Koen Bok, Framer co-founder, states that Framer will be moving to ES6 at some point in the future.

@jemgold
Copy link

jemgold commented Sep 12, 2017

yooooo can we lock this thread yet?

@koenbok
Copy link
Owner Author

koenbok commented Sep 13, 2017

Yep I agree. We'll have some more news on this soon.

@koenbok koenbok closed this as completed Sep 13, 2017
Repository owner locked and limited conversation to collaborators Sep 13, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests