ssbc / visual-docs

Diagrams and animations documenting Secure Scuttlebutt (scuttlebutt.nz) and Āhau (ahau.io)
https://scuttlebutt.nz
Other
16 stars 1 forks source link

convert Easings #2

Closed cameralibre closed 3 years ago

cameralibre commented 3 years ago

Context:

Problem

Currently, convert-anime-to-css.js does not deal with easings at all, as I don't understand how to pull the required information out of the anim object.

Example anime.js timeline:

const tl = anime.timeline({
  easing: 'easeInOutQuad'
})

tl
  .add({
    targets: '#light-a',
    opacity: [0, 1]
    // easing will be inherited, i.e. 'easeInOutQuad'
  })
  .add({
    targets: '#antenna',
    rotate: [-40, 0],
    easing: 'linear'
  })
  .add({
    targets: '#wifi-wave',
    keyframes: [
      { scale: [0, 1], easing: 'cubicBezier(.5, .05, .1, .3)' },
      { opacity: [1, 0] } // easing will be inherited, i.e. 'easeInOutQuad'
    ]
  })

I can call logAnimations(anim) on changeBegin for each of these animation sections, and log the currentTween's easing:

for (j = 0; j < currentAnimation.tweens.length; j++) {
  const currentTween = currentAnimation.tweens[j]
  console.log('easing:', currentTween.easing)

What I get for the four tweens in the above example is:

easing: function (r)  // = inherited default for timeline (easeInOutQuad)
easing: function linear(n)  // = linear easing
easing: function p(n) // = cubicBezier(.5, .05, .1, .3)
easing: function (r)  // = inherited default for timeline (easeInOutQuad)

So this is referring to the specific functions of the minified anime.js library that calculates easings... but I don't know how I can get the required information (my inline comments above) from the anim object.

cameralibre commented 3 years ago

@zachmandeville suggested using String(currentTween.easing) and checking it against an object with all the easing functions as keys, with their cubic-bezier() CSS equivalents as values. A great plan! I logged all of Penner's easing functions from a test animation (at least, the ones which can be converted to Bezier), and these were my results:

easing-functions

Unfortunately, most of the results of String(currentTween.easing) are duplicates (indicated by a red dot in the screenshot above). easeInQuad, easeInCubic, easeInQuart etc all share the same function:

function(n){return Math.pow(n,e+2)}

So the difference between them must be either the n or e value, I'll have to look into how easings work in the anime.js code, and see if there's a way to find those values from the anim object.

cameralibre commented 3 years ago

I thought that I would be clever and use a non-minified version of anime.js in my SVG instead, to make it easier to hunt down the relevant bits and pieces, but I get an error which I don't know how to solve: Uncaught SyntaxError: export declarations may only appear at top level of a module

cameralibre commented 3 years ago

I got a whole lot of help from @mixmix to determine the easing of an animation:

  1. Use the anime.js source code and run each easing function with the same two parameters (0.2 & 0.7), and check that a unique fingerprint is produced.
  2. Use these fingerprints as a lookup table, so that when we're logging the easing in our animation, we can run the easing function with 0.2 and 0.7 to determine which easing is being used:

https://github.com/ssbc/visual-docs/blob/ba0f0340b1b4306bbc96af3ad7ab1da856efef3a/js/convert-anime-to-css.js#L65-L112

Unlike anime.js, CSS doesn't allow an animation to have multiple easings at different points, so that complicates things further. You gotta choose one!

OK, first, record every instance of each easing being used on a particular target: https://github.com/ssbc/visual-docs/blob/ba0f0340b1b4306bbc96af3ad7ab1da856efef3a/js/convert-anime-to-css.js#L26-L27

...and if more than one easing is used on a target's animation, then make a stab at deciding which easing should be used in the CSS animation (the most frequent easing used). If there's a tie for most frequent easing, fuck it, just use the first one.

https://github.com/ssbc/visual-docs/blob/ba0f0340b1b4306bbc96af3ad7ab1da856efef3a/js/convert-anime-to-css.js#L177-L200

This is just logging information for now, I'll need to dig back into the RegEx to actually write it into the CSS animations, but that's the hard part done.

cameralibre commented 3 years ago

Easings are now being applied to the CSS animations (f09312f) All those lines of complicated RegEx to convert the monolithic stringified object were just too daunting to adapt, so I re-wrote the conversion, instead iterating through each level of the original object and writing to the CSS string along the way: https://github.com/ssbc/visual-docs/blob/f09312f4e085eabd5e4dcfa8b669519a7b3702ca/js/convert-anime-to-css.js#L357-L382

mixmix commented 3 years ago

Woop!

On Thu, 26 Nov 2020, 15:13 Sam Muirhead, notifications@github.com wrote:

Closed #2 https://github.com/ssbc/visual-docs/issues/2.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ssbc/visual-docs/issues/2#event-4040468712, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAUK3HWKCNWDPM7PTGZ6VKTSRW2TRANCNFSM4TH53J4A .