# Magnetic Glass Lens

> A glass loupe that follows the cursor and magnifies the live page beneath it, with refraction wobble, chromatic fringing and 3D tilt momentum.

Canonical: https://gsapvault.com/effects/magnetic-glass-lens
Live demo: https://gsapvault.com/demos/magnetic-glass-lens/index.html

| Property | Value |
|----------|-------|
| Type | effect |
| Tier | paid |
| Price | £5 |
| Difficulty | advanced |
| Plugins | Core GSAP only |
| Techniques | cursor-effects, physics, micro-interaction, 3d-transforms, svg-filters, velocity-reactive |
| Uses Lenis | No |

## Overview

A physical glass loupe that follows the pointer and magnifies the real page content beneath it. Glide slowly and it reads like an optician's instrument: the point under the lens centre stays locked under the glass while a refraction wobble bends the magnified image like a true convex lens.

Whip the cursor and the physics answer: the lens banks in 3D against its momentum, the magnified image splits into red and blue fringing scaled by velocity, and the specular glint swings around the bezel to face the direction of travel. Stop dead and everything settles with a damped elastic wobble.

Built with GSAP core only. The magnifier is live DOM, not a screenshot: the content under the glass is a synchronised clone of the page, so it stays sharp at any zoom and updates with the layout.

## Features

- One movement vector drives five response channels: smoothed spatial tracking, velocity-banked 3D tilt, RGB channel separation, a rotating bezel glint aimed at the travel heading, and a damped elastic settle
- True optical magnification: a synchronised full-size clone of the page is scaled and counter-translated so the point under the lens centre always lands on the optical centre
- Refraction wobble from an SVG feDisplacementMap whose strength is driven by cursor velocity, over a base level that reads as glass texture at rest
- Chromatic dispersion built from colour-isolated content layers that fade in and spread apart with speed, not a canvas trick
- Configured live through data attributes: change data-lens-zoom, data-lens-dispersion or data-lens-filter at runtime and the lens follows, which is all a preset switcher needs to do
- Film-negative mode inverts everything inside the glass, leaving the page untouched
- Touch support with pointer capture and an idle figure-8 preview orbit that resumes after interaction pauses
- Keyboard accessible: focusable inspection targets glide the loupe to themselves; reduced motion gets direct positioning with the physics switched off; without JavaScript the page simply renders without the lens

## Use Cases

- Print shops, poster stores and editorial archives where fine detail is the selling point
- Luxury product pages for horology, jewellery and fabric close-ups
- Type foundry specimens and design portfolio pieces built around micro-typography
- Photography and art gallery sites that want inspection to feel physical

## Vibe-Code Ready Setup

This effect includes `START-HERE-AI.md`, a product-specific copy-paste setup prompt for Cursor, Claude Code, ChatGPT, GitHub Copilot, Windsurf, and other coding assistants. It tells the assistant to inspect the existing stack, integrate the supplied files, preserve the design, scope selectors, retain accessibility and responsive behaviour, add framework-appropriate GSAP cleanup, and report what it tested.

[How AI-assisted setup works](https://gsapvault.com/vibe-coding)

## How It Works

The script clones the element marked data-lens-content into the lens aperture three times, one copy per colour channel, sized to match the stage exactly. Each frame, a GSAP ticker lerps the lens toward the pointer, then scales and counter-translates the cloned view so the point under the lens centre maps onto the aperture centre at the current zoom.

The frame-to-frame delta gives a velocity vector. Its magnitude drives the scale attribute of an SVG feDisplacementMap for the refraction wobble and sets the offset and opacity of the red and blue channel layers for the dispersion fringing; its heading angles both the 3D tilt (banking against momentum via rotateX and rotateY) and the conic-gradient glint on the bezel through CSS custom properties.

When speed falls to rest the loop hands off to tracked settle tweens: an elastic.out on the tilt and scale, and quick power2 decays on the fringing, glare and wobble. A MutationObserver watches the stage's data-lens-* attributes so zoom, dispersion and the negative filter can be changed live from outside the script.

## Integration Preview

How this effect integrates into a page. The full documentation (examples, events, programmatic API, customization guide) ships with the download.

### Quick Start

**1. Add to your HTML `<head>`:**

```html
<link rel="stylesheet" href="assets/style.css">
```

**2. Add the optical filters once, anywhere inside `<body>`:**

```html
<svg class="lens-filter-defs" aria-hidden="true" focusable="false">
    <defs>
        <filter id="lens-distortion" x="-20%" y="-20%" width="140%" height="140%">
            <feTurbulence type="fractalNoise" baseFrequency="0.015 0.015" numOctaves="2" result="noise" />
            <feDisplacementMap id="lens-displacement-map" in="SourceGraphic" in2="noise" scale="3" xChannelSelector="R" yChannelSelector="G" />
        </filter>
        <filter id="lens-filter-red">
            <feColorMatrix type="matrix" values="1 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 1 0" />
        </filter>
        <filter id="lens-filter-green">
            <feColorMatrix type="matrix" values="0 0 0 0 0  0 1 0 0 0  0 0 0 0 0  0 0 0 1 0" />
        </filter>
        <filter id="lens-filter-blue">
            <feColorMatrix type="matrix" values="0 0 0 0 0  0 0 0 0 0  0 0 1 0 0  0 0 0 1 0" />
        </filter>
    </defs>
</svg>
```

**3. Mark up the stage, your content, and the lens:**

```html
<section data-lens-stage data-lens-zoom="2.2" data-lens-dispersion="1">
    <div class="your-content" data-lens-content>
        <!-- whatever the lens should magnify -->
    </div>

    <div class="glass-lens" aria-hidden="true">
        <div class="lens-shadow"></div>
        <div class="lens-bezel"><div class="lens-bezel-glare"></div></div>
        <div class="lens-aperture"></div>
        <div class="lens-glass-finish"></div>
    </div>
</section>
```

**4. Add before closing `</body>` tag:**

```html
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<script src="assets/script.js"></script>
```

### Options

All read from the `[data-lens-stage]` element, all live: change the attribute at runtime and the lens follows (a `MutationObserver` watches them). The demo's toolbar is nothing more than buttons stamping these attributes.

| Attribute | Values | Default | Description |
|-----------|--------|---------|-------------|
| `data-lens-zoom` | number | `2.2` | Magnification factor. The change is tweened. |
| `data-lens-dispersion` | number | `1` | Multiplier on the chromatic fringing. `0` disables it entirely. |
| `data-lens-filter` | `invert` or absent | absent | Film-negative view inside the glass only. |
| `data-lens-focus` | on any focusable element | – | Keyboard hook: when the element receives focus, the loupe glides to it. Pair with `tabindex="0"`. |
| `data-lens-tint` | any string | absent | Not read by the script. A CSS hook for restyling the glass hardware per mode (see the tint blocks in `style.css`). |

`--lens-size` in `:root` sets the physical size of the loupe (240px desktop, 170px under 900px in the demo).

### Accessibility

- **Reduced motion**: the physics loop, tilt, fringing and idle orbit are all disabled; the lens positions directly under the pointer and zoom changes are instant. The CSS also forces the chromatic layers off.
- **Keyboard**: elements marked `data-lens-focus` (with `tabindex="0"` and a sensible `aria-label`) glide the loupe to themselves on focus, mirroring hover.
- **No JavaScript**: the page renders normally without the lens; nothing is hidden behind the effect.
- The lens itself and every cloned copy are `aria-hidden`, and focusables inside the clones are removed from the tab order.
- **Touch**: see below — the loupe is pinned to the screen and lifted off the fingertip.
- **Attract orbit**: a slow figure-8 runs on load to show the optics off, for a fixed number of passes, then parks back at the centre. Once the visitor has driven the lens themselves it does not run again. It is an attract loop, not an ambient animation.

### Dependencies

- GSAP core 3.x (no plugins)

## What You Get

- `index.html`: working demo page
- `assets/script.js`: commented, readable source
- `assets/style.css`: effect styles
- `README.md`: full documentation with examples and framework integration notes
- `START-HERE-AI.md`: product-specific copy-paste prompt for AI-assisted setup
- `LICENSE.txt`: standard license terms
- Lifetime updates: re-download anytime from your library

## Get the Code

This is a premium effect. The standard license costs £5 one-time and covers unlimited personal and commercial projects with no attribution required. The only restrictions: no redistribution of the code itself and no competing effect libraries.

- [Buy Magnetic Glass Lens](https://gsapvault.com/effects/magnetic-glass-lens)
- [Effects & Templates Vault (£39 one-time, best value): every current and future effect and template](https://gsapvault.com/effects)

## Judge the Code Quality First

These related effects are free with complete source published, written to the same production standard (cleanup functions, reduced-motion support, framework-agnostic):

- [Hover Underline](https://gsapvault.com/effects/hover-underline.md): Three material link underlines (an exit-through line, marker sweep, and hand-drawn wave) with coordinated type and active-index responses.

---

From [GSAP Vault](https://gsapvault.com): production-ready GSAP animation effects. Full catalog for agents: https://gsapvault.com/llms-full.txt
