juliangarnier / anime

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

lazy targets (function that returns nodes, called at start of the animation) #845

Open Lakedaemon opened 1 year ago

Lakedaemon commented 1 year ago

I would like to create a timeline to animate dynamically added nodes (say in 15 min long tutoring javascript animations)

I think that I have 3 paths :

1 create a timeline with LAZY TARGETS (targets gets a function returning nodes, that it calls at start of the animation, when the objects exist). Looking at the anime.js code, it looks like a major refactoring would be needed.

  1. LIKELY : do not use a single timeline, but use hundreds of simple anime calls, in my event streams and reimplement/use play/pause, seek (which I need).

  2. UNLIKELY : Create my own very lightweight code that does this, with a tiny subset of anime.js features (that sucks :/).

A video of what I am doing

juliangarnier commented 1 year ago

Why not adding new animations to the timeline using .add() ? This way you can still use play / pause globally. Or maybe I'm missing something?

remlik commented 1 year ago
$('body').append('<div` id="first">');
timeline
    .add({/*transforms existing element, creates new DOM-element when completed*/
        target: '#first',
        top: 100,
        duration: 250,
        completed: function(anim) {
            $('body').append('<div id="second">');
        }
    })
    .add({/*transforms existing elements, but depends on the properties of the new element*/
        target: '#first',
        top: $('#second').css('top'), /*it doesn't give anything because the #second doesn't exist yet at the time of adding the animation to the timeline*/
        duration: 250
    })

the question is how to change timeline dynamically?

remlik commented 1 year ago
$('body').append('<div id="first">');
timeline
    .add({
        top: 100,
        duration: 250,
        completed: function(anim) {
            $('body').append('<div id="second">');
        }
    })
    .add({
        top: 0,
        duration: 250,
        begin: function(anim) {
            anim.animations[0].tweens[0].to = {
                original: $('#second').css('top'),
                numbers: [parseInt($('#second').css('top').split('px')[0])],
                strings: ['', 'px']
            };
        }
    })

changing tweens object in the begin function works fine, but I think this is not the most elegant solution :)