web-animations / web-animations-js

JavaScript implementation of the Web Animations API
http://web-animations.github.io
Apache License 2.0
3.77k stars 408 forks source link

Would allowing animation of plain object properties be a good thing? #176

Closed amrdraz closed 6 years ago

amrdraz commented 7 years ago

Given that the web animation API essentially provides a timeline and tween library built in to the browser. why limit it to only DOM elements?

A reason being for example if we want to animate properties that render on to canvas, like three.js

GSAP is often used with three.js to animate objects, which is done by mutating or calling the position properties of those objects.

An example from this pen

  var geometry = new THREE.PlaneGeometry(4, 4);

  var material = new THREE.MeshBasicMaterial({
    map: texture,
    transparent: true,
    side: THREE.DoubleSide
  });
  var plane = new THREE.Mesh(geometry, material);
  plane.position.set(3, 5, -0.4);

  var tl = new TimelineMax({
    repeat: -1
  });

  tl.to(plane.rotation, 2, {
    z: -Math.PI,
    ease: Power0.easeNone
  });

  scene.add(plane);

With the WEB API effectively a sort of a tween library built in, it reduces the need to load a library like GSAP if it's possible to do.

var tlEffect = new KeyframeEffect(plane, [{
    rotation:-Math.PI
}], {
   duration: 2000,
    repeat: Infinity,
});
domcument.timeline.play(tlEffect)
scene.add(plane);

I understand it's out of scope of the specification since it's meant to allow an extension on what CSS already does.

But allowing objects can provide a wider adoption path, since it makes the API more extensible. This matches a realistic workflow for large scale animations that use other renderers then the DOM.

Also it can generally be noted when an object is passed to the Keyframe object instead of a DOMNode, and so optimizations that are applied knowing that the object being animated.

So it it possible to do

var object = { x: 10, y: 0}
var objectEffect = new KeyframeEffect(object, [
  { x: 10, y: 0},
  { x: 20, y: 30}
], {
   duration: 2000,
});
var anim = document.timeline.play(objectEffect);
anim.addEventListener('finish', function() {
    console.log(object) //   { x: 20, y: 30}
});
Martin-Pitt commented 6 years ago

I've somewhat tried to propose this as a generalised WebEffect/CustomEffect node in https://github.com/w3c/csswg-drafts/issues/2062

const effectOptions = {
    onsample(timing) {
        let fraction = timing.progress;
    }
};
const timingOptions = {
    duration: 1250,
    easing: 'ease-in'
};
const effect = new WebEffect(effectOptions, timingOptions);
const animation = new Animation(effect, document.timeline);
animation.play();

It would then be possible to build ontop of this to do something similar.

I do like the idea of being able to directly target a KeyframeEffect against a JavaScript object though. It's an alternative that I'd really enjoy as well and provide a direct API. I wonder what @birtles thinks of this?

Also this issue doesn't affect the polyfill (although it could be incorporated as an experiment for sure), but more the web-animations standard itself, so this issue belongs in w3c/csswg-drafts/ really.

davidkpiano commented 6 years ago

I would strongly, strongly discourage the mutation of ~objects~ anything unknowingly in any DOM API. This can lead to many hard-to-trace bugs, especially if objects are references to anything not directly related to animation.

The problem with object mutation is that there is no automatic notification mechanism for anything that references the object whenever the object mutates (Object.observe is obsolete), whereas with DOM nodes, the WAAPI (I assume) updates the DOM nodes in a way that the DOM knows when to recalculate styles, due to changes.

GSAP makes it easy to animate by using mutation, but "robust" and "predictable" should be prioritized as goals over "easy".

notoriousb1t commented 6 years ago

I like the idea of having the "onsample" function in a WebEffect/CustomEffect as @Martin-Pitt proposed in the other issue , but using KeyframeEffect to mutate arbitrary properties sounds like a blackhole. What data types can be tweened? If it is only numbers, how do you handle values with units?

Providing a general progress/update function in WAAPI would be immediately useful to dozens of libraries and sounds pretty straightforward. I think trying to do keyframes of arbitrary properties would slow that to a halt due to complexities of specifying how everything would work.

ewilligers commented 6 years ago

This library is a polyfill implementation of the Web Animations API, which has publicly tracked issues.

Going beyond the API is out of scope for the polyfill.