FIZZX v0.0.4

UI physics without duration or easing

        import Fizzx from 'fizzx'
      
        
const emoji = new Fizzx(window.emoji)

document.body.addEventListener('click', e =>
  emoji.to({
    translate: {
      x: e.clientX, 
      y: e.clientY + window.scrollY,
    }
  }))
        
      
Explanation:

When a fizzx element is initialized, the element passed in has it's position in the window asynchronously evaluated to prepare for stage/document anchored absolute animation. Works great on elements initially in flow that need to F.L.I.P.

This emoji demo; on click, 2d translates the emoji from it's current x, y to the mouse position in the window. Fizzx figures out speed and timing based on mass, etc.

To help you orient, the top left of the document is x and y. Pass 0 and 0, the emoji would animate from it's current position to the top left, and do so based on it's physical properties.

          
// top left of the document
emoji.to({
  translate: {
    x: 0, 
    y: 0,
  }
})
          
        

2 steps; 2 functions

Give nodes mass; Give nodes a new pose

1) Initialize

Fizzx returns a class representing an element that you gave physics properties

          
const fx = new Fizzx(Element)
          
        


2) Animate

Direct it somewhere on the document absolutely or direct it somewhere relative to itself

          
// absolute
fx.to({translate,rotate})

// relative
fx.effect({translate,rotate})
          
        

to(): <Promise>
directs the element to a new location on the document body, as if it's absolutely positioned

effect(): <Promise>
changes the element from it's current location, as if it's relatively positioned

💡

Each return a promise, making async/await with Promise.all() very powerful for orchestration of sequences or repetition!

Notice the use of await in the demo code.

Fizzx Options

Since there's no duration,
your element's physical properties and distance inform the motion

Provide physics properties at initialization time

            
// (defaults shown)
const fx = new Fizzx(Element, {
  mass:      1,
  damping:   26,
  stiffness: 170,
  arc:       1, // 0 sharp ↔ 1 curved redirects
})

// or start from a named preset
const fx = new Fizzx(Element, Fizzx.presets.wobbly)
            
          

Or, set them later

            
// many properties at once
fx.options = {...}

// only one
fx.options['mass'] = 10
            
          

Bouncy Moves

Give physics to elements in flow and effect 😉 them

            
await box.effect({ translate: {x:  300} })
await box.effect({ translate: {x: -300} })
            
          

Bouncy Redirects

Momentum survives a retarget — arc decides what happens to the sideways part

arc 1
arc 0

click around the arena — both boxes chase the same point

Watch the trails: pink (arc: 1) keeps its perpendicular momentum and curves through every redirect. Blue (arc: 0) drops it and beelines. Same clicks, same spring — only arc differs. Try clicking while they're moving fast.

            
const pink = new Fizzx(el1, { arc: 1 })
const blue = new Fizzx(el2, { arc: 0 })

arena.on('pointerdown', e => {
  pink.to({ translate: cursor(e) })
  blue.to({ translate: cursor(e) })
})
            
          

Bouncy Zoomies

Spring the scale param for easy depth physics

            
await box.to({ scale: 0.25 })
await box.to({ scale: 1 })
            
          

Bouncy Spins

Fling the dial — fling it again mid-spin and the momentum stacks

            
// every fling adds a springy turn —
// retargets inherit the rotational velocity
dial.on('pointerdown', e =>
  fx.effect({
    rotate: { z: randomInRange(120, 360) },
  }))
            
          

Bouncy Dimensions

Springy 3D tilt with perspective — glide your pointer across the stage

fizzx
            
// 3D rotation rides the JS engine
const card = new FizzxJS(el)

stage.on('pointermove', e =>
  card.to({ rotate: {
    x: -dy * 24,  // tilt toward the pointer
    y:  dx * 24,
  }}))

stage.on('pointerleave', e =>
  card.to({ rotate: {x: 0, y: 0} }))
            
          

Bouncy Whatevers

Put it all together

            
await box.effect({
  rotate:    {z: 20, x: -10, y: 20},
  translate: {x: 100, y: 20},
  scale:     0.8,
})

await box.effect({
  rotate:    {z: -20, x: 10, y: -20},
  translate: {x: -100, y: -20},
  scale:     1.25,
})
            
          

Bouncy Orchestration

Rearrange, have fun!

            
await Promise.all([
  box_1.effect({ translate: {y: 120}, delay: 0 }), 
  box_2.effect({ translate: {y:  40}, delay: 50 }), 
  box_3.effect({ translate: {y: -80}, delay: 100 }),
  box_4.effect({ translate: {y: -80}, delay: 150 }),
])
            
          

Bouncy Force

Springiness in z-space

            
// squish on press
btn.on('pointerdown', e =>
  fizzx_btn.to({
    scale: randomInRange(.5, .85),
  }))

// spring back on release
btn.on('pointerup', e =>
  fizzx_btn.to({
    scale: 1,
  }))