Skip to content

Pinch to zoom, two fingers to move, on the timeline and the picture - #53

Merged
ibrahimweng merged 1 commit into
mainfrom
claude/pinch-and-pan
Aug 31, 2026
Merged

Pinch to zoom, two fingers to move, on the timeline and the picture#53
ibrahimweng merged 1 commit into
mainfrom
claude/pinch-and-pan

Conversation

@ibrahimweng

Copy link
Copy Markdown
Owner

There was no wheel handling anywhere in the app. Zoom was three buttons and a tool; a trackpad did nothing at all.

A pinch reaches a page as a wheel event with ctrlKey set — there's no pinch event on a desktop, and that's the only way a browser reports one. Both surfaces listen for it.

What it does

Timeline — pinch zooms the time axis around the pointer. That's the whole reason to do it with a gesture: the buttons zoom around the left edge because they have no pointer to zoom around, and pinching around the left edge would send whatever you were looking at off the side of the screen. Plain two-finger scroll is left alone — the viewport already scrolls both ways on its own, and handling it here would move it twice.

Picture — pinch zooms around the pointer through the same arithmetic the zoom tool already uses; two fingers without ctrl move it, but only once there's somewhere to move it. At Fit the scroll passes through rather than being swallowed.

Neither asks which tool is held. A gesture is not a tool: the hand and the zoom exist for a mouse, which has no way to say "closer" without one. Somebody pinching has already said it.

The step is exponential rather than a multiplier, so the gesture is symmetric — out and back by the same amount lands where it started.

Six tests, and two misses worth naming

They send the small repeated deltas a trackpad actually produces, not one large jump. Two of three injected faults were caught immediately. The third — replacing the exponential with a straight multiplier — took two attempts:

  1. Counting ruler labels couldn't see it. The ruler picks a sensible interval, so it's quantised: a 2% drift looks identical. Switched to measuring the drawn width.
  2. It still couldn't see it. A clip opens fitted — as far out as the timeline goes — so the gesture back out gets clamped to the floor and lands exactly where it started whether the arithmetic is symmetric or not. The clamp was hiding the drift.

Starting the test part-way in fixes it, and the fault now fails plainly:

Error: 1638.515625px became 1606.9375px

359 unit tests, 96 browser tests (was 90), build clean.


Still to come from your request: GIF/APNG/animated-WebP import via ImageDecoder, and the "without lagging" work for multi-minute 1080p.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ux1kydvUkLRoMbHp82ofDi


Generated by Claude Code

There was no wheel handling anywhere. Zoom was three buttons and a tool, and
a trackpad did nothing at all.

A pinch reaches a page as a wheel event with `ctrlKey` set. There is no
pinch event on a desktop and that is the only way a browser reports one, so
that is what both surfaces listen for.

On the timeline it zooms the time axis around the pointer, which is the
whole reason to do it with a gesture: the buttons zoom around the left edge
because they have no pointer to zoom around, and pinching around the left
edge would send whatever you were looking at off the side of the screen. A
plain two-finger scroll is left alone, because the viewport already scrolls
both ways on its own and handling it here would move it twice.

On the picture it zooms around the pointer through the same arithmetic the
zoom tool already uses, and two fingers without ctrl move it -- but only
once there is somewhere to move it, so at Fit the scroll is left to whatever
is underneath rather than swallowed.

Neither asks which tool is held. A gesture is not a tool: the hand and the
zoom exist for a mouse, which has no way to say "closer" without one, and
somebody pinching has already said it.

The step is exponential rather than a multiplier, so the gesture is
symmetric -- out and back by the same amount lands where it started. A
multiplier does not: a tenth up and a tenth down is 0.99 of where it began.

Six browser tests, sending the small repeated deltas a trackpad actually
produces rather than one large jump. Two of the three faults were caught at
once; the third took two goes and both misses are worth naming.

Counting ruler labels could not see the multiplier drift, because the ruler
picks a sensible interval and is therefore quantised: two per cent off looks
identical. Measured on the drawn width instead.

Then it still could not see it, because a clip opens fitted -- as far out as
the timeline goes -- so the gesture out is clamped to the floor and lands on
exactly where it started whether the arithmetic is symmetric or not. The
test starts part way in now, and the fault fails it: 1638.5px became
1606.9px.

359 unit tests, 96 browser tests, build clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ux1kydvUkLRoMbHp82ofDi
@vercel

vercel Bot commented Aug 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
beat-studio Ready Ready Preview Aug 31, 2026 3:31pm

@ibrahimweng
ibrahimweng merged commit 62e86cd into main Aug 31, 2026
5 checks passed
@ibrahimweng
ibrahimweng deleted the claude/pinch-and-pan branch August 31, 2026 18:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant