Jump to content
Search Community

kvndy

Members
  • Posts

    2
  • Joined

  • Last visited

Everything posted by kvndy

  1. Thanks for considering this. OSUBlake you are too kind. First I have to mention the animated text is a native Mac app, and I don’t mean React Native. It suffers from an awful class inheritance hierarchy, and poor handling of ligatures or text input with anything other than Western style glyphs. I never posted the code and probably never will. It is a good example of the need to copy animations. (Line fragments are continuously split and merged.) It looks like in the future we might get very robust glyph metrics that could make this possible in a browser, with HTML5 canvas and one of the new Houdini specs. Layout thrashing could be a deal breaker. The underlying value could be affected by className change or programmatic style sheet changes. I don’t know a solution other than either constant style recalcs or caching the value at the start and ignoring changes coming from elsewhere. Not good. Cluttering up an API is nearly as bad as negatively impacting performance. Unfortunately I have to mention one more point that I did not stress enough before. There is value in automatic conversion from absolute to relative values for animating like (implicit & declarative) CSS Transitions and (explicit & imperative) CSS Animations. But there is also a use for additive without that conversion, for those like CSS Animations. For instance CSS Transform rotate3d has arguments for both amplitudes and the angle. It is unlikely that someone would want to animate all arguments to zero. In those cases I do the conversion to relative values manually. One neat thing is that if someone does manual conversion but then uses a function that also does this, it results in the same values. From 2 to 10 manually converted into from -8 to 0, if converted a second time is still -8 to 0. That would break things though, if the inputted (absolute) destination value is used as the underlying value. There are also uses for animating from zero to zero. The scaling done in this next video kind of does that, but uses an excessively complex custom easing. To get the magnitude of the scaling right, the easing function is what actually goes from zero to zero, instead of from zero to one. It’s weird, and probably a bad example. I think it could be done better by compositing simpler animations together: This is a better example. At least, it looks cool but may not be the best to peruse. It gets the idea across what you can do with two animations running simultaneously: They are both for iOS. I will hopefully get around to making them simple DOM or canvas examples, one of these days. That animating floats jsFiddle is not recommended. It uses Web-Animations and an earlier version of Hypermatic when it was a jQuery plugin, but I do not recommend even looking at it. My javascript skills have improved in the last two years, somewhat. I prefer: http://kevindoughty.github.io/Hypermatic/relativeFloat.html It seems many of my examples have broken. I would avoid anything with a file name prefixed with negative-delta. They can be found here: https://github.com/kevindoughty/Hypermatic/tree/gh-pages
  2. I’m happy to hear you’re interested in additive animation. You might not be so happy as this post turned out a lot longer than I thought. I developed the technique five years ago and made the feature requests to Apple, which is what brought me here. I actually blogged about GreenSock a couple of years ago, but perhaps I came off as attacking the platform instead of making a proper feature request. [1] (My bad.) As was pointed out in this thread earlier, it is difficult to convey what is happening and why it is beneficial. There are drawbacks as well. It is a powerful but counter-intuitive technique that I hope to explain. In short, you animate from the old value minus the new value to zero. Animations do not get removed, instead many can run concurrently. The values get added together, to themselves but also to an underlying, non-animated value. When an animation’s duration has elapsed, its effective value is zero and can be removed without side effects. All that remains is the underlying value. Combined with an easing function, it gives seamless blending and beautiful curves. It lends itself to discrete app state. In simple use cases the developer no longer has to reason about current animated values or quasi indeterminate state, and can focus solely on destination values and layout. Because multiple animations can run concurrently, it gives complete separation of concerns. Animation of an element triggered in one part of your code does not need to know about animations running on the same property triggered elsewhere. Let’s consider interrupting an in progress animation. The typical way to handle interruption has been to prevent it by completely blocking the UI until the animation is done, or to replace it with a new animation that begins where the previous left off. The former is a complete disaster but prevents visual discrepancy. The latter is an improvement but not without drawbacks. This is CSS transition behavior. Interruption will give sharp sudden angles, or asymmetric timing when reversing an in progress animation, like a hover. (The reverse distance travelled is shorter than the original, but the duration stays the same.) Additive animation provides a solution, and a simple one. There are other ways to accomplish animation blending. Facebook POP is the most notable, ported to the web in Rebound.js. POP relies on a single animation per property. Interrupting will mutate the animation to include smoothing/dampening. Of course nowadays everyone advocates immutable data. Mutating may not be such a big deal, but does prevent optimization like running on a separate process. But also information gets lost. Unlike additive animation, POP cannot blend two keyframe animations. [2] Web-Animations also takes a blending approach. At the very bottom of the spec they have a note claiming to have a solution to blending timing functions but deferred it to a later version. [3] Frankly, I will believe it when I see it. I think all blending techniques are overly complex and fall short of desirable behavior. Blending animation duration and easing/timing functions doesn’t make sense to me, and I have not seen any other solutions to blending path or keyframe animations, all of which an additive solution can do easily. Additive javascript implementations have appeared. Unfortunately they may never see the same performance benefits as native Core Animation, which actually runs the animations in a separate process with a very high priority. Currently Mozilla is implementing what they call Electrolysis (e10s) which will mean Firefox will have separate processes per browser tab, like “Chrome Helper” et al, but still will not compete with Core Animation in terms of performance, because what drives animations gets lumped together with everything else. Thus I don’t think the Javascript community has yet been convinced, because of availability of these competing techniques and for lack of a performance benefit. Unfortunately they miss out on blending keyframe animations, and running multiple animations on the same property of an object simultaneously. From an API standpoint, first and foremost is to automatically convert developer input from absolute to relative values. Relative means from old minus new, to zero. A transition for a change from 2 to 10 would instantly set the new underlying value to 10, then an animation from 2 to 10 would be converted to -8 to 0 behind the scenes. When added to the underlying value, the negative value puts the element back to the apparent start value. When interrupting and reversing the above example animation, say at an animated value of 5.5, the underlying value is instantly changed from 10 back to 2. The second animation’s converted values are from 8 to 0. The previous animation continues to animate to zero, which when added to the new underlying value of 2 does not cause a sudden jump because the second animation puts the element again back to where it started from, this time 10. The animated value can be ignored. Matrices are more complicated but the operation is concatenate the old transform with the inverse of the new, with zero being the identity matrix. In my opinion, there is no benefit whatsoever to use additive animation without this conversion, or with a destination value other than zero. So I prefer to call it “Relative Animation” and let the additive nature be a private implementation detail. My experience with GreenSock is very limited, please forgive me if I make statements about it that are not accurate, but two years ago I found its additive/relative functionality is not the same thing that I describe. It does look like GreenSock’s overwrite setting might permit concurrent animations on the same property and element, but I have not tried it out. The documentation does not mention additive. I think all operations can either replace or override any other animations, optionally without destroying previous ones, which could then come back into effect, say, if the previous has a longer duration and the newer ends sooner. You need to have a strong concept of non-animated vs. animated values. In Core Animation that means model vs. presentation values, and is wonderful. Web-Animations has specified vs. computed values. My concerns about a GreenSock implementation is that its animations seem to be predominantly forward filling. By that I mean when animating an object from A to B, the value persists at B after the animation is complete because the animation is still active and its values still applied. A forward filling system can work, and may be required for things like transform rotation. To animate from 0 to 90 degrees (non-additive seems a lot simpler) the way I do this using Web-Animations is to also have a non-additive constant animation, from 90 to 90 degrees that is forward filling and does not get removed. I call them underlying value animations, when toggled they get replaced instantly, while their relative interpolations do not. This complication is not necessary in Core Animation because of its clear distinction of model and presentation values, sadly absent from CSS. This is an implementation detail that probably could be taken care of by GreenSock’s own internal handling of state. I bring attention to forward filling because there are benefits of animating relative to an underlying value specified elsewhere. The web already has CSS to layout elements. It would become unwieldy to layout only with forward filling animations, in anything but the simplest of use cases. A developer could position an element via left and top using element.style or the style sheet, then animate its transform for performance. This is easy to do as both the absolute and relative destination values are zero. Paul Lewis blogged about this technique, but his version was not additive and so does not handle interruption. [4] The I_Am_Ralph_T physics animation also animates transforms to zero, and they are interruptible, but not additive (I don’t think). [5] A problem with animating CSS laid out elements relatively is browsers will re-calculate layout, but also unfortunately redraw before I have a chance to calculate the deltas, causing flicker. Web-Animations has a single line to fix this, requiring vendors not redraw immediately. [6] Thus, relatively animating floated content is now possible in Chrome but not yet viable in Safari. I should also point out that getBoundingClientRect gives animated values, which means the developer has to use offsetLeft and offsetTop to calculate non-animated values for relative animation. Using non-animated values is normally a benefit, perhaps not in this case. Having to work around APIs that did not anticipate relative animation is a drawback. Another feature more complicated animations might need is the ability to copy animations from one element to another. I’m not sure if this is possible now or makes sense with the GreenSock API. The path produced by many additive animations can be complex and hard to recreate. If the developer needs to insert a new element alongside an existing animating one, copying animations can accomplish this. Of course this and many of the features of additive animation can also be replicated by nesting elements. Drawbacks to additive mostly involve having to deal with an unknown number of animations instead of only one. You would have to track and copy many animations, for instance. In the WWDC 2014 #236 video, it is mentioned that it is hard to “catch” or instantly stop animations. All animations would need to be removed, then a new underlying value set to compensate. I would argue that the true relative pattern is to never remove them, instead permit them to finish. This is a case where a true physics simulation might be superior. If animations are not removed, very slow or different animation durations could be a problem. It might give expected behavior, it might not, but I tend to prefer short and unchanging durations. I forgot to mention, physics can be simulated in additive Core Animation or Web-Animations by calculating your own keyframes to give a nice springy effect or wobble, but it can be somewhat simplistic. I find the wobbling usually blends well. Large value changes cause a greater wobble, smaller and more continuous changes, having a smaller delta, barely produce a wobble and do not look bad. But again, this might be a bit simplistic for some. I found that in javascript, scientific notation shows up often, especially when you animate to a value of 0 with a little wobble. CSS cannot parse scientific notation, which would cause flickering, so it needs to be converted. To calculate keyframes, say for example A, B, C, D, E, F, G, relative conversion means A-G, B-G, C-G, etc. Another neat trick is a solution to rotating matrices. Since you cannot determine intent from a destination value matrix alone, for example if it should rotate 720 degrees multiple times or a combination of flips, the traditional approach has been to use keyframe animations with half rotations, or use a provided special animation function where the developer explicitly says to rotate n times (which cannot be determined otherwise.) Additively this can be accomplished by simultaneously running twice as many half rotations. I have my own animation framework that is a derivative work of the Web-Animations legacy javascript shim. It is a significant departure from Web-Animations, instead meant to resemble more closely Core Animation’s API, or at least its usage. I do not however recommend people use it for anything other than experimentation as I haven’t implemented tests and make breaking changes on a whim. But I have examples below. Also, I am very impressed that you were able to figure out additive animation from the slides in that WWDC video, because of the errors. In that picture, the second animation’s duration should be the same as the first, they imply the second is shorter for some reason, from 1.0 second to 0.4. The end time would also be different. But anyway, there isn’t really an animation API for the web out there that gives me all the tools I would like. The Web-Animations team refused my proposal to implement a property to enable conversion from absolute to relative values. This means in the future there will never be a CSS Transition property that uses relative (or additive) animation, but additive CSS Animation might be possible. My hopes are with GreenSock now! 1. Dissing GreenSock: (No not really. I called it negative delta back then, it is poorly written, and should be no surprise that I did not convince anyone.) http://kxdx.org/greensock-is-nice-but/ 2. POP cannot not blend keyframe animations: (no one can, but me… for now. Maybe you can change this.) https://github.com/facebook/pop/issues/64 3. Proposed smooth timing function: (Maybe it doesn’t mean what I think it does) http://www.w3.org/TR/2015/WD-web-animations-1-20150707/#acknowledgements 4. Paul Lewis: (FLIP sounds a lot catchier than negative-delta) https://aerotwist.com/blog/flip-your-animations/ 5. iamralpht (Sigh. Physics is very nice, I can’t deny it) http://iamralpht.github.io/physics/ 6. Changes made within the same task are synchronized such that the whole set of changes is rendered together: http://www.w3.org/TR/2015/WD-web-animations-1-20150707/#model-liveness 7. Animating floated content, requires Chrome: (click or resize window) http://kevindoughty.github.io/Hypermatic/relativeFloat.html 8. Blending keyframe animations !!! (compare single click vs. double click vs quintuple click) http://codepen.io/kvndy/pen/YyXLWp 9. Chained together animation sequence, requires Chrome: (click) http://kevindoughty.github.io/Hypermatic/relativeLayout.html 10. Implicit animation. The blue div uses constant underlying value animations, but is not something I would do unless I had to. More notable is how the orange and purple divs get animated automatically on element.style change, without CSS transitions or explicitly adding animations. They are declared and triggered automatically: http://codepen.io/kvndy/pen/meJYEj
×
×
  • Create New...