juliangarnier / anime

JavaScript animation engine
https://animejs.com
MIT License
49.28k stars 3.66k forks source link

Allowing CSS Keyframe Syntax with Percentages would Help #544

Open Kenny-Moore opened 5 years ago

Kenny-Moore commented 5 years ago

Is your feature request related to a problem? Please describe. There are many CSS library's for creating animated effects. I am planning to making an effect library based on AnimateCSS that could be used with Animejs. The problem is that the CSS keyframes syntax is very different from what is expected by Anime and the conversion process is not simple.

Describe the solution you'd like To make my task easier I wrote a parsing function that allows me to convert keyframes animations in CSS into an array that is consumable by Animejs with minimal syntax changes:

Converter:

function parseEffect(params) {
   var keyframes = params.keyframes;
  //Convert CSS style keyframe object into array to be flattened  
  if (Array.isArray(keyframes) === false) {
    var keys = Object.keys(keyframes);
    if (keys.length > 0) {
      var duration: number = params.duration || 1000;
      var splitKeysMap = keys.reduce(function (accumulator, key, i, array) {
        key.split(',').forEach(function (k, i) {
          let mk = (parseFloat(k) / 100.0); 
          accumulator.has(mk) ? Object.assign(accumulator.get(mk), keyframes[key]) : accumulator.set(mk, keyframes[key]);
        });
        return accumulator;
      }, new Map());

      var splitKeys = [].concat(_toConsumableArray(splitKeysMap.keys())).sort();

      keyframes = splitKeys.map(function (value, i) {
        var d = duration * value;
        if (i > 0) {
          d -= duration * splitKeys[i - 1];
        }
        return Object.assign({}, { duration: d }, splitKeysMap.get(value));
      });
      params.keyframes = keyframes;
    }
  }
  return params;
}

CSS

/* Bounce animation from Animate.css
   https://daneden.github.io/animate.css/
*/

@keyframes bounce {
    0%,20%,53%,80%,100% {
        animation-timing-function: cubic-bezier(.215,.61,.355,1);
        transform: translateZ(0)
    }

    40%,43% {
        animation-timing-function: cubic-bezier(.755,.05,.855,.06);
        transform: translate3d(0,-30px,0)
    }

    70% {
        animation-timing-function: cubic-bezier(.755,.05,.855,.06);
        transform: translate3d(0,-15px,0)
    }

    90% {
        transform: translate3d(0,-4px,0)
    }
}

.bounce {
    animation-name: bounce;
    transform-origin: center bottom
}

AnimeJs

// Based on: Bounce animation from Animate.css
// https://daneden.github.io/animate.css/

var bounceEffect = {
  duration: 1000,
  keyframes: {
    "0%,100%": {
      transformOrigin: "50% 0px 0px",
    },
    "0%,20%,53%,80%,100%": {
      translateY: "0px",
      easing: "easeOutCubic"
    },
    "40%,43%": {
      translateY: "-30px",
      easing: "easeInQuint"
    },
    "70%": {
      translateY: "-15px",
      easing: "easeInQuint"
    },
    "90%": {
      translateY: "-4px"
    }
  }
};
var bounceAnime= anime.timeline({
  targets: '.bounce',
  loop: true
});
bounceAnime.add(parseEffect(bounceEffect));

Here is a working example: https://codepen.io/GooeyIdeas/pen/RdPzyX

I personally think this should be built in. Like in this example: https://codepen.io/GooeyIdeas/pen/QobXBd

Would you be willing to consider this feature? If so I can make a pull request.

FlyDreame commented 4 years ago

Amazing code that saved me hours. Thank you. @gooeyideas

zfogg commented 3 years ago

+1.. this doesn't work exactly like css keyframes :( @juliangarnier are you looking into this? there are a buncha issues on this topic.. this project def needs proper css-like keyframes value tweening

skull-sage commented 3 years ago

+1, today while I was going to integrate animejs in VueJS I have also felt the same need. @juliangarnier My humble opinion it would be really good if you could integrate such feature in keyframe module.