svgdotjs / svgdotjs.github.io

Documentation and website for SVG.js
http://svgjs.dev
Other
13 stars 23 forks source link

The fx module was completely reworked to be faster and less error prone. #64

Closed Fuzzyma closed 3 months ago

Fuzzyma commented 5 years ago

This is a big one. Will update later!

Fuzzyma commented 5 years ago

So the overall workflow for the user stayed almost the same.

el.animate().move(100, 1000)

However it works differntly under the hood. animate() returns a Runner which holds closures which it runs on every step.

Runners are scheduled on a timeline. Every element creates a timeline when a runner is created. However, you can easily create an external timeline and schedule different runners on it. Runner and Timeline both work without an element. Calling animate() on a runner creates a new runner which gets scheduled after the last one (or as specified in the parameters).

// create Runner independently from Element with duration 1000
var r = new SVG.Runner(1000)
// create Timeline independently
var t = new SVG.Timeline()
// schedule runner on the timeline at time 200
// note, that this also works: t.schedule(r, 200)
r.schedule(t, 200)
  .animate(500).loop(5, true, 100) // this creates a new Runner with duration 500 which is looped 5 times (bouncing) with a delay of 100 between the loops
  .animate(600, 200, 'absolute') // new runner, 600ms, scheduled at absolute 200
  .animate(600, 300) // new runner, 600ms, scheduled 300ms after the end of the last one
  .animate(600, 300, 'now') // new runner, 600ms, scheduled right now whenever this line is hit. So it starts right away
  .animate(1000, 0, 'absolute').loop(6, true) // rew runner, 1000ms. Starts at absolute 0

// returns the schedule of the timeline in the form [{start, duration, end, runner}, ...]
var schedule = t.schedule()

// we draw a rectangle for every runner, basically visualizing the schedule
schedule.forEach((s, i) => {
  var rect = canvas.rect(s.duration / 10, 25)
    .move(100 + s.start/10, 100 + i*30)
    .attr('fill', '#000')

  // we bind the created rectangle to the runner which means that this element is animated from this runner
  s.runner.element(rect)
    .attr('fill', getColor(i*0.1))

})

// creating a time-bar which shows where we are at in the animation
var mover = canvas.line(100, 100, 100, 300).attr('stroke', 'black')

// horizontal line and vertical line
mover.clone().insertAfter(mover)
canvas.line(100, 300, 800, 300).attr('stroke', 'black')

// update line at every timestep in the timeline
t.on('time', function (e) {
  mover.x(100 + e.detail/10)
})

Well that was quite a bunch of functions. Lets break it down:

Timeline

Ok - not done yet, will continue later