---
title: 'Observer, Physics & Pixi'
excerpt: 'CustomWiggle, Physics2D, PhysicsProps, and PixiPlugin on canvas.'
icon: 'Layers3'
---

## Specialty motion

These plugins add **physics-flavored** and canvas-oriented motion. Use them for delight or game-like UI — not for every button. Register only what the page needs; Pixi especially should stay behind a dynamic import.

## Physics2D

**Physics2D** launches an element with velocity, angle, and gravity — a projectile arc without hand-keyframing `x`/`y`. Duration is how long the simulation runs.

Replay: the ball kicks up and falls under gravity. Good for confetti-adjacent accents, not form validation.

<ComponentPreview replay>
  <GsapPhysics2D />

  <DocsFileTabs title="Physics2d">

```tsx title="physics2d.tsx"
gsap.to('.ball', {
  duration: 2,
  physics2D: { velocity: 280, angle: -75, gravity: 600 },
});
```

```html title="physics2d-markup.html"
<div class="relative h-full overflow-hidden">
  <div class="gsap-ball absolute bottom-4 left-1/2 size-8 rounded-full"></div>
</div>
```

  </DocsFileTabs>
</ComponentPreview>

## PhysicsProps

**PhysicsProps** attaches velocity / acceleration / friction per property (`x`, `y`, …) with optional `end` targets. More control than Physics2D when axes need different rules.

Watch the orb glide with horizontal velocity and vertical acceleration — a soft throw, not a bounce loop.

<ComponentPreview replay>
  <GsapPhysicsProps />

  <DocsFileTabs title="Physics props">

```tsx title="physics-props.tsx"
gsap.to('.obj', {
  duration: 2,
  physicsProps: {
    x: { velocity: 120, end: 200 },
    y: { velocity: -80, acceleration: 200 },
  },
});
```

```html title="physics-props-markup.html"
<div class="relative h-full overflow-hidden">
  <div class="gsap-glide absolute bottom-4 left-1/2 size-8 rounded-full"></div>
</div>
```

  </DocsFileTabs>
</ComponentPreview>

## CustomWiggle

**CustomWiggle** builds a named ease that oscillates (wiggle) before settling. Register with `CustomWiggle.create`, then use that name as `ease` (or drive `wiggleY`-style props depending on setup).

Replay: the box shakes with a defined wiggle count, then rests — attention without a full physics sim.

<ComponentPreview replay>
  <GsapCustomWiggleDemo />

  <DocsFileTabs title="Custom wiggle">

```tsx title="custom-wiggle.tsx"
import { CustomWiggle } from 'gsap/CustomWiggle';
CustomWiggle.create('myWiggle', { wiggles: 12, type: 'easeOut' });
gsap.to('.box', { duration: 2, wiggleY: 20, ease: 'myWiggle' });
```

```html title="custom-wiggle-markup.html"
<div class="gsap-wiggle-box size-16 rounded-lg"></div>
```

  </DocsFileTabs>
</ComponentPreview>

## PixiPlugin

**PixiPlugin** lets GSAP tween PixiJS display-object props (`pixi: { x, rotation, scale }`). Keep Pixi behind an **isolated dynamic import** so canvas code only loads on pages that need it.

The demo stage is a canvas sprite under GSAP control — same mental model as DOM tweens, different renderer.

<ComponentPreview>
  <GsapPixiSprite />

  <DocsFileTabs title="Pixi plugin">

```tsx title="pixi-plugin.tsx"
import { PixiPlugin } from 'gsap/PixiPlugin';
gsap.registerPlugin(PixiPlugin);
gsap.to(sprite, { pixi: { x: 200, rotation: 360, scale: 1.2 }, duration: 2 });
```

```html title="pixi-plugin-markup.html"
<canvas><!-- Pixi stage; GSAP animates pixi sprite properties --></canvas>
```

  </DocsFileTabs>
</ComponentPreview>

<Callout variant="note">
  This site smooths page scroll with **Lenis**, not ScrollSmoother. ScrollSmoother needs a wrapper/content DOM structure — use it only when you control the full page layout.
</Callout>
