koenbok / Framer

Framer - Design Everything
https://framer.com
MIT License
5.85k stars 477 forks source link

Request: Proxy property on Layer #352

Open jordandobson opened 8 years ago

jordandobson commented 8 years ago

I'd really love to have a proxy property for layers that could be used for hooking into animations that aren't directly supported by Framer yet. I see this being useful for hooking in new ideas and having a controller to manipulate them sanely. So essentially animate the proxy value but get no output just a change event fired.

I'd also be interested in building this as well if this was something you might support.

Or would it make more sense to just create a proxy object class where you could spin up multiple proxies?

Thoughts?

nvh commented 8 years ago

I don't know if I understand what you mean. Could you provide an example, or maybe a suggestion of what such and API would look like?

jordandobson commented 8 years ago

Basically want to "animate" a value from 0 to 1 and then be able to take that value and apply it something that you currently don't support. Something like a background color alpha, a SVG's radius, the stokewidth... Basically a prop that I wouldn't have to simulate by creating a layer and animating it between 0 and 100 on X or Y... Something that would allow us to use your animation layers over a value that does really exist but responds to change events.

nvh commented 8 years ago

Would you want to use this to animate properties alongside an animation of a a current layer, or do you just want to have a shortcut to get the values out of an Animator?

jordandobson commented 8 years ago

Initially I was thinking along side but I guess a shortcut could work too. Initially was thinking on the layer so it could be done along side other properties as the issue states. But I could see that longer term, if extremely useful, some sort of shortcut to be better. But hooking into states is mainly the thinking here. On Tue, Aug 2, 2016 at 5:59 AM Niels van Hoorn notifications@github.com wrote:

Would you want to use this to animate properties alongside an animation of a a current layer, or do you just want to have a shortcut to get the values out of an Animator https://github.com/koenbok/Framer/blob/master/framer/Animator.coffee?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/koenbok/Framer/issues/352#issuecomment-236896250, or mute the thread https://github.com/notifications/unsubscribe-auth/AACbYvhOaqaIkPkVsG69dVbwGARt0euZks5qbz8mgaJpZM4ISK11 .

  • Jordan Dobson
jordandobson commented 8 years ago

I'll write up an example of what I am thinking here to start with... A good example would be animating a SVG mask... I'll just use a proxy layer instead too.. which I hope would take the place of a proxy property.

nvh commented 8 years ago

Cool! Looking forward to it!

jordandobson commented 8 years ago

Here's an example of what I'd hopefully have... in a simple way.

Example of Proxy property on Layer

Here's an example file doing it without the proxy and having to use another layer...

http://jrdn.io/3h1r0W470Y3s

I could see this being useful to manipulate other things that framer doesn't handle yet but still using the animation properties in Framer.

If we did get shortcuts out of Animator, how would that work?

koenbok commented 8 years ago

I think you want a basic building block like:

animation = new Animation(target, properties, options)

a1 = new Animation(layerA, {x: [0, 100], opacity: [0, 1]}, curve:"spring")

Where the target can be any object and the property any key.

koenbok commented 8 years ago

So in your example:

a1 = new Animation layerA, 
    "path.style.strokeDashOffset": [0, 100], 
    "path.style.strokeWidth": [0, 1],
    "path.style.r": [0, 10]
, curve: "spring"

This does imply some custom setters on your svg element that use setAttribute internally, although I think you can also use css properties on svg these days. This also implies we'd support keypaths.

jordandobson commented 8 years ago

Kind of yes... ideally it would be attached to the layer so it could be a part of states and I could just listen for changes and calculate changes (if needed) on the "change" event.

What if I could define custom properties on the layer inside custom (or directly on the layer)... and they could be included in a state.

Other things could be animating the backdrop-filter: blur(10px); value or box-shadow spread, etc, etc.

Unless I'm just doing quick sketches... I tend to use states a lot more when building out bigger prototypes for testing...

koenbok commented 8 years ago

If you build states on top of these they'll automatically work with anything.

koenbok commented 8 years ago

This is also actually also not too far off from how everything works already. We can clean this up and open it up. But we should do it after the upcoming animation api overhaul that @nvh is planning :-)

jordandobson commented 8 years ago

I mean yeah if I don't have to setup a change value then that's even better. But for something like backdrop-filter: blur(10px) or box-shadow: inset 0px 0px 0px 10px red I would need to handle the formatting I believe and couldn't directly pass in the value. So I would still want to animate from like 0 to 10 and then update the style properties directly I'd imagine.

Otherwise I think what you are saying would be amazing. I think this could also open things up a bit more and make this stuff much less painful.

I'm going to do one more example here for you guys.

jordandobson commented 8 years ago

Here's an example of something else I might like to do:

http://jrdn.io/0N1h2o3z0a13

Something like this would be along the lines of what I'd hope for...

example of request

jordandobson commented 8 years ago

I hope this helps!

jordandobson commented 8 years ago

Any thoughts here at all?

edwinvanrijkom commented 8 years ago

I've explored the related sources (Animation.coffee), @jordandobson - and there's quite a bit of Layer specific code there.

We'd have to go for quite a bit of a refactoring there to make things work like @koenbok is proposing and we don't have the resources available to do that right now, so it might take a while before we can get this in.

koenbok commented 8 years ago

Yeah I'd love to work on this but we need to carve some time out for it and we should do that only after the upcoming Animation refactor release. Luckily that already cleans some stuff up that we would need for this. Let's circle back here in a few weeks.

jordandobson commented 8 years ago

Awesome guys! I can get by as you can see but something like this would be helpful and great whenever you can get to it.

For me having some way to do states like @koenbok proposed as well as have Change events for props that the values are "string" based would be amazing.

If I come across other examples I'll make sure to share them here. One is likely a crazy SVG circle animation for Skype I'm still helping with.

jordandobson commented 8 years ago

I could really use something like this now that I'm doing work with A-frame and Framer.

jordandobson commented 8 years ago

Bump... would love this for some 3D / VR work I'm doing very soon. It would allow me to move things in 3D space via simple framer sliders.

jordandobson commented 8 years ago

Okay... after looking at this more... it might already just be damn close to working.

http://share.framerjs.com/7rkbapfqwq7n/

http://jrdn.io/0S3j0f3h1Z03

It prints out every time the y value changes... now I just need a change event that isn't tied to anything I think? Or some sort of progression of the animation.

jordandobson commented 8 years ago

Doing this gets me pretty much exactly where I would need to be:

http://share.framerjs.com/3c07s0dmrih7/

http://jrdn.io/1p0R2t420142

How hard would it be to open up that function layerProperty as either a class method?

I believe you could just do this inside the layer Class If I understand what's happening correctly.

class exports.Layer extends BaseClass

    @layerProperty = layerProperty

    constructor: (options={}) ->
        # The rest of the class....
jordandobson commented 8 years ago

Actually this seems like a solid way to approach this perhaps?

I either would need to use the unless conditional or a try with the way Framer handles reloads, but it seems pretty solid.

I would just love to have a method to set a custom property that would register a change event. How could we simplify this?

http://jrdn.io/1S1u0w271v2G

screen shot 2016-11-04 at 6 00 32 pm

jordandobson commented 8 years ago

One last example that reworks the example from https://github.com/koenbok/Framer/issues/352#issuecomment-237722856

EXAMPLE: http://jrdn.io/0z2R0h3L2N28

nvh commented 8 years ago

If you create a subclass that implements the defines, you can go without the try: http://share.framerjs.com/o6wdukp2q5yb/ I went even further and used the 'set' method to set the properties, so you're not limited to animations (try dragging the thing around:)

So basically the only thing we need for this to work, is make some form of the layerProperty function public. I think we need to rethink the arguments for that, and maybe expose it just as @customProperty <name>, <fallback>, <setter> or something

nvh commented 8 years ago

This could be useful for the TextLayer stuff in https://github.com/koenbok/Framer/pull/434 as well

jordandobson commented 7 years ago

Any thoughts or progress on this @koenbok @eelco @nvh ?

tehfailsafe commented 7 years ago

I have been tinkering with this idea using Proxy objects. Not sure if it works for this use case, have a look; https://github.com/tehfailsafe/ObservableLayer

I've been debating the syntax: Layer.observe(Store, "layerProperties", true) vs Store.layerProperties = Layer.getObserver({animated: true})

And then later we can modify/animate/anything to Store.layerProperties.x and the layer.x will update, either instantly or animated if animated was set to true.

tehfailsafe commented 7 years ago

The other benefit here is that Store can be a module that can be imported into other modules, and any module can modify the store which will update any layer that setup an observer.

(Heavily inspired by MobX )