InTween

Your companion for building rich interactive media with Interactive Tweens

Get Started →

Interactive Tweens

Tweens that can accept user interaction (meddling) in flight, and then gracefully return to the intended state.

Highly Configurable

Control exactly how and when data structures transition between each other.

Powerful but Minimalistic

Easy to get started, but scales well to support incredibly complex projects.

Click!

It doesn't take much code to create something playful!

See the code!
const tween = new Tween({
  circle: [0, 0],
  outline: [0, 0]
}).loop()

tween.in('2s', {
  circle: [200, 0],
  outline: [200, 0]
}, 'quintInOut')
.in('2s', {
  circle: [200, 200],
  outline: [200, 200]
}, 'bounceOut')
.in('2s', {
  circle: [0, 200],
  outline: [0, 200]
}, 'backInOut')
.in('2s', '1s', {
  circle: [0, 0],
  outline: [0, 0]
}, 'elasticOut')

const meddle = new Meddle(tween).easing('quadInOut')

let lastPos = [0, 0]
const sub = animationFrames().pipe(
  spreadAssign(
    tween,
    meddle
  )
  , animationThrottle()
).subscribe(state => {
  lastPos = state.circle
  circleEl.style.transform = `translate(${state.circle[0]}px, ${state.circle[1]}px)`
  outlineEl.style.transform = `translate(${state.outline[0]}px, ${state.outline[1]}px)`
})

const clicks = new Subject()

const sub2 = clicks.pipe(
  smoothen(
    {
      duration: '.3s',
      easing: 'quadIn + backOut'
    },
    () => ({ pos: lastPos })
  )
).subscribe(({ pos }) => meddle.set({ circle: pos }))

const onInteract = e => {
  const ctx = circuitEl.getBoundingClientRect()
  let [x, y] = [e.clientX, e.clientY]
  x -= ctx.x
  y -= ctx.y
  clicks.next({ pos: [x, y] })
}

window.addEventListener('click', onInteract)