Motion · GSAP-style

Playback control

A tween isn't fire-and-forget. Keep the object and you can pause(), reverse(), seek('label'), drag its progress() or slow it down with timeScale(0.25).

One control surface for tweens and timelines

$.to(), $.from(), $.fromTo() and $.timeline() all return an object with the same methods: play, pause, resume, reverse, restart, seek, progress, time, duration, timeScale, repeat, yoyo and kill. Each is a getter when called without arguments.

They are also thenables, so await tl waits for the end. $.killTweensOf(el) stops everything on an element, and jsKjs does that for you when the element is removed.

Live · Drive a timeline by hand

View the source for this demo
HTML
<div class="row">
  <button type="button" data-pc="play">Play</button><button type="button" data-pc="pause">Pause</button>
  <button type="button" data-pc="reverse">Reverse</button><button type="button" data-pc="restart">Restart</button>
  <button type="button" data-pc="seek">Seek to "spin"</button>
</div>
<div class="row" style="margin-top:10px">
  <div class="field" style="min-width:220px"><label for="pc-prog">Progress: <span id="pc-prog-v">0%</span></label><input id="pc-prog" type="range" min="0" max="1" step="0.001" value="0"></div>
  <div class="field" style="min-width:180px"><label for="pc-speed">Speed: <span id="pc-speed-v">1×</span></label><input id="pc-speed" type="range" min="0.25" max="3" step="0.25" value="1"></div>
  <label style="align-self:end"><input type="checkbox" id="pc-yoyo"> repeat + yoyo</label>
</div>
<div class="pc-lane"><div id="pc-dot" class="pc-dot"></div></div>
JavaScript
const lane = () => $('#pc-dot').parent().width() - 64;
const tl = $.timeline({ paused: true, onUpdate() {
  $('#pc-prog').val(tl.progress());
  $('#pc-prog-v').text(Math.round(tl.progress() * 100) + '%');
} })
  .to('#pc-dot', { x: () => lane() / 2, duration: 1, ease: 'power2.out' })
  .addLabel('spin')
  .to('#pc-dot', { rotate: 360, borderRadius: '50%', duration: .8, ease: 'back.inOut' })
  .to('#pc-dot', { x: lane, duration: 1, ease: 'power2.in' });

$('[data-pc]').on('click', function () {
  const cmd = this.dataset.pc;
  if (cmd === 'seek') tl.seek('spin').play(); else tl[cmd]();
});
$('#pc-prog').on('input', function () { tl.pause().progress(+this.value); });
$('#pc-speed').on('input', function () { tl.timeScale(+this.value); $('#pc-speed-v').text(this.value + '×'); });
$('#pc-yoyo').on('change', function () { tl.repeat(this.checked ? -1 : 0).yoyo(this.checked); if (this.checked) tl.play(); });

More examples

Hover animation that reverses cleanly

JavaScript
$('.card').each(function () {
  const t = $.to(this, { y: -6, scale: 1.02, duration: .25, paused: true });
  $(this).on('mouseenter', () => t.play()).on('mouseleave', () => t.reverse());
});

API

.play() .pause() .resume() .reverse() .restart() .seek(t) .progress(p) .time() .timeScale(s) .kill() .then() .duration() .isActive()

Every tween and timeline.

Reference: Tween control →
$.timeline({ defaults, paused, repeat, yoyo, onComplete… }) → .to .from .fromTo .set .add .call .addLabel .addPause .tweenTo

Sequence with positions: number, "label", "<", ">", "+=0.2", "-=0.2", "label+=1"; nest timelines.

Reference: $.timeline() →

Migrating

Coming from GSAPThe control methods have the same names and getter/setter behaviour as GSAP 3 — tl.progress(0.5), tl.timeScale(2), tl.seek('label').

Related features