Skip to content

feat: add pan, zoom, and auto-fit to whiteboard canvas#31

Merged
cosarah merged 25 commits intoTHU-MAIC:mainfrom
YizukiAme:fix/whiteboard-overflow-pan
Mar 19, 2026
Merged

feat: add pan, zoom, and auto-fit to whiteboard canvas#31
cosarah merged 25 commits intoTHU-MAIC:mainfrom
YizukiAme:fix/whiteboard-overflow-pan

Conversation

@YizukiAme
Copy link
Copy Markdown
Contributor

Summary

Fixes #19 — Whiteboard content that exceeds the fixed canvas bounds was clipped by overflow-hidden with no way to view hidden parts.

Changes

components/whiteboard/whiteboard-canvas.tsx

  • Auto-fit scaling: When elements overflow the 1000×562.5 canvas, computes bounding box and applies scale + translate to ensure all content is visible (with 24px padding). When content fits normally, no transform is applied — zero visual regression.
  • Drag-to-pan: Hold mouse and drag to pan around the whiteboard (pointer events with capture)
  • Scroll-to-zoom: Mouse wheel zooms in/out (0.2x–5x range), using native addEventListener({ passive: false }) for proper preventDefault
  • Double-click reset: Double-click or click "Reset View" button to return to default view (with smooth 0.25s animation)
  • Text selection prevention: select-none + preventDefault prevents accidental text selection during drag/double-click
  • Auto-reset on content change: View resets when whiteboard content changes (tracked by stable element ID key, not object reference)
  • Grab cursor: Shows grab/grabbing cursor when pan/zoom is available

lib/i18n/stage.ts

  • Added resetView translation key for zh-CN ("重置视图") and en-US ("Reset View")

How it works

Content fits canvas → No change, original behavior
Content overflows → Auto-fit scales down to show all
User scrolls wheel → Zoom in/out (centered)
User drags → Pan around
User double-clicks/button → Smooth reset to auto-fit
New content loads → Auto-reset view

Testing

Tested with injected overflow elements (left/right/bottom + negative coordinates) and confirmed:

  • ✅ Auto-fit scales content to fit
  • ✅ Scroll zoom works
  • ✅ Drag-to-pan works (no text selection)
  • ✅ Double-click reset with smooth animation
  • ✅ Reset View button appears and works
  • ✅ No visual regression when content fits normally

When AI generates whiteboard elements that exceed the fixed 1000x562.5
canvas, content was clipped by overflow-hidden with no way to view it.

This commit adds interactive navigation to the whiteboard:

- Auto-fit: when elements overflow, content is scaled and centered to
  ensure nothing is clipped (with 24px padding)
- Drag-to-pan: hold and drag to pan around the whiteboard
- Scroll-to-zoom: mouse wheel zooms in/out (0.2x to 5x range)
- Double-click or Reset View button to return to default view
- View auto-resets when new whiteboard content loads

When content fits within the canvas, behavior is unchanged - no extra
cursor, no transforms, no visual regression.

Fixes THU-MAIC#19
- Remove dead code: ?? 'Reset View' fallback (i18n key exists)
- Add useMemo for elementsKey (perf optimization)
- Fix el.height type narrowing (remove implicit any)
- Disable pan/zoom/cursor when whiteboard is empty (UX improvement)
@cosarah
Copy link
Copy Markdown
Collaborator

cosarah commented Mar 18, 2026

dragging and scrolling works, but can't drag without scrolling

@YizukiAme
Copy link
Copy Markdown
Contributor Author

YizukiAme commented Mar 18, 2026

Thanks for testing! This is intentional — we found that when content fits the canvas at 1x zoom, unrestricted drag would accidentally move the whiteboard off-screen.

Current behavior:

Scroll wheel to zoom in/out → then drag to pan around
If content overflows the canvas bounds → drag is enabled automatically
We could switch to always-enabled pan for more freedom — let us know your preference and we'll update today~ 👀

@cosarah
Copy link
Copy Markdown
Collaborator

cosarah commented Mar 18, 2026

OK, you can add a small hint like "scroll to zoom and drag", and I'll merge it

@YizukiAme
Copy link
Copy Markdown
Contributor Author

OK, you can add a small hint like "scroll to zoom and drag", and I'll merge it

Got it, thanks! I’ll add a small hint for the interaction and push an update once I’m back home. 😊

wyuc and others added 9 commits March 18, 2026 19:32
…ll flow

Restructure the OpenClaw quickstart: install skill first, then pick mode.
Add meme-style nudge for OpenClaw to star the repo. Enlarge logo and
put "OpenClaw" in the TIP heading for visibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(build): use cross-platform file copy in mathml2omml build script

Replace Unix `cp` with Node.js `fs.copyFileSync` so that `pnpm install`
works correctly on Windows where `cp` is not available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add .worktrees to .gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(build):
1、README.md / README-zh.md — Node.js 版本要求 >= 18 → >= 20
2、package.json — 新增 engines: { node: ">=20.9.0" }
3、ci.yml — node-version: 20 → 22(与 Dockerfile 一致)
4、.nvmrc — 新建,内容 22

Co-authored-by: humingfeng <humfsss@gmail.com>
Removed bodyParser configuration from Vercel functions.
* Fix SSRF/credential forwarding via client-supplied baseUrl

* chore: format SSRF fix
@YizukiAme YizukiAme force-pushed the fix/whiteboard-overflow-pan branch from 9853a28 to ba0a16a Compare March 18, 2026 11:32
@YizukiAme
Copy link
Copy Markdown
Contributor Author

OK, you can add a small hint like "scroll to zoom and drag", and I'll merge it

Hint added in the latest push!

When AI generates whiteboard elements that exceed the fixed 1000x562.5
canvas, content was clipped by overflow-hidden with no way to view it.

This commit adds interactive navigation to the whiteboard:

- Auto-fit: when elements overflow, content is scaled and centered to
  ensure nothing is clipped (with 24px padding)
- Drag-to-pan: hold and drag to pan around the whiteboard
- Scroll-to-zoom: mouse wheel zooms in/out (0.2x to 5x range)
- Double-click or Reset View button to return to default view
- View auto-resets when new whiteboard content loads

When content fits within the canvas, behavior is unchanged - no extra
cursor, no transforms, no visual regression.

Fixes THU-MAIC#19
- Remove dead code: ?? 'Reset View' fallback (i18n key exists)
- Add useMemo for elementsKey (perf optimization)
- Fix el.height type narrowing (remove implicit any)
- Disable pan/zoom/cursor when whiteboard is empty (UX improvement)
@cosarah cosarah force-pushed the fix/whiteboard-overflow-pan branch from ba0a16a to 13db9ac Compare March 18, 2026 12:04
YizukiAme and others added 2 commits March 19, 2026 00:22
Copy link
Copy Markdown
Collaborator

@cosarah cosarah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally — whiteboard pan/zoom and hint display all work correctly. LGTM!

@cosarah cosarah merged commit a680fcf into THU-MAIC:main Mar 19, 2026
1 check passed
cosarah added a commit that referenced this pull request Mar 20, 2026
zhenzhu143321 pushed a commit to zhenzhu143321/OpenMAIC that referenced this pull request Apr 4, 2026
* feat: add pan, zoom, and auto-fit to whiteboard canvas

When AI generates whiteboard elements that exceed the fixed 1000x562.5
canvas, content was clipped by overflow-hidden with no way to view it.

This commit adds interactive navigation to the whiteboard:

- Auto-fit: when elements overflow, content is scaled and centered to
  ensure nothing is clipped (with 24px padding)
- Drag-to-pan: hold and drag to pan around the whiteboard
- Scroll-to-zoom: mouse wheel zooms in/out (0.2x to 5x range)
- Double-click or Reset View button to return to default view
- View auto-resets when new whiteboard content loads

When content fits within the canvas, behavior is unchanged - no extra
cursor, no transforms, no visual regression.

Fixes THU-MAIC#19

* fix: correct pan tracking math and reset button event propagation

* fix: guard against zero containerScale and fix zoom docstring

* fix: cleanup reviewer feedback and disable pan/zoom on empty whiteboard

- Remove dead code: ?? 'Reset View' fallback (i18n key exists)
- Add useMemo for elementsKey (perf optimization)
- Fix el.height type narrowing (remove implicit any)
- Disable pan/zoom/cursor when whiteboard is empty (UX improvement)

* docs: revamp OpenClaw TIP section with playful copy and clearer install flow

Restructure the OpenClaw quickstart: install skill first, then pick mode.
Add meme-style nudge for OpenClaw to star the repo. Enlarge logo and
put "OpenClaw" in the TIP heading for visibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(build): use cross-platform file copy in mathml2omml (THU-MAIC#20)

* fix(build): use cross-platform file copy in mathml2omml build script

Replace Unix `cp` with Node.js `fs.copyFileSync` so that `pnpm install`
works correctly on Windows where `cp` is not available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add .worktrees to .gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix(build):Next.js 16 要求 Node.js >= 20.9.0 (THU-MAIC#21)

* fix(build):
1、README.md / README-zh.md — Node.js 版本要求 >= 18 → >= 20
2、package.json — 新增 engines: { node: ">=20.9.0" }
3、ci.yml — node-version: 20 → 22(与 Dockerfile 一致)
4、.nvmrc — 新建,内容 22

Co-authored-by: humingfeng <humfsss@gmail.com>

* Update Vercel configuration by removing bodyParser (THU-MAIC#45)

Removed bodyParser configuration from Vercel functions.

* Fix SSRF/credential forwarding via client-supplied baseUrl (THU-MAIC#30)

* Fix SSRF/credential forwarding via client-supplied baseUrl

* chore: format SSRF fix

* fix: tighten whiteboard pan and auto-fit bounds

* refactor: reset whiteboard viewport via keyed remount

* fix: preserve viewport while whiteboard content streams

* feat: add scroll-to-zoom interaction hint on whiteboard

* feat: add pan, zoom, and auto-fit to whiteboard canvas

When AI generates whiteboard elements that exceed the fixed 1000x562.5
canvas, content was clipped by overflow-hidden with no way to view it.

This commit adds interactive navigation to the whiteboard:

- Auto-fit: when elements overflow, content is scaled and centered to
  ensure nothing is clipped (with 24px padding)
- Drag-to-pan: hold and drag to pan around the whiteboard
- Scroll-to-zoom: mouse wheel zooms in/out (0.2x to 5x range)
- Double-click or Reset View button to return to default view
- View auto-resets when new whiteboard content loads

When content fits within the canvas, behavior is unchanged - no extra
cursor, no transforms, no visual regression.

Fixes THU-MAIC#19

* fix: correct pan tracking math and reset button event propagation

* fix: guard against zero containerScale and fix zoom docstring

* fix: cleanup reviewer feedback and disable pan/zoom on empty whiteboard

- Remove dead code: ?? 'Reset View' fallback (i18n key exists)
- Add useMemo for elementsKey (perf optimization)
- Fix el.height type narrowing (remove implicit any)
- Disable pan/zoom/cursor when whiteboard is empty (UX improvement)

* fix: tighten whiteboard pan and auto-fit bounds

* refactor: reset whiteboard viewport via keyed remount

* fix: preserve viewport while whiteboard content streams

* feat: add scroll-to-zoom interaction hint on whiteboard

* fix: avoid synchronous setState in useEffect for hint visibility

---------

Co-authored-by: wyuc <wang-yc24@mails.tsinghua.edu.cn>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: 杨慎 <117187635+cosarah@users.noreply.github.com>
Co-authored-by: 1/2极客 <humf@vip.qq.com>
Co-authored-by: humingfeng <humfsss@gmail.com>
Co-authored-by: Rowtion <65099725+Rowtion@users.noreply.github.com>
Co-authored-by: Wing900 <167857578+Wing900@users.noreply.github.com>
jaumemir pushed a commit to jaumemir/OpenMAIC that referenced this pull request Apr 8, 2026
* feat: add pan, zoom, and auto-fit to whiteboard canvas

When AI generates whiteboard elements that exceed the fixed 1000x562.5
canvas, content was clipped by overflow-hidden with no way to view it.

This commit adds interactive navigation to the whiteboard:

- Auto-fit: when elements overflow, content is scaled and centered to
  ensure nothing is clipped (with 24px padding)
- Drag-to-pan: hold and drag to pan around the whiteboard
- Scroll-to-zoom: mouse wheel zooms in/out (0.2x to 5x range)
- Double-click or Reset View button to return to default view
- View auto-resets when new whiteboard content loads

When content fits within the canvas, behavior is unchanged - no extra
cursor, no transforms, no visual regression.

Fixes THU-MAIC#19

* fix: correct pan tracking math and reset button event propagation

* fix: guard against zero containerScale and fix zoom docstring

* fix: cleanup reviewer feedback and disable pan/zoom on empty whiteboard

- Remove dead code: ?? 'Reset View' fallback (i18n key exists)
- Add useMemo for elementsKey (perf optimization)
- Fix el.height type narrowing (remove implicit any)
- Disable pan/zoom/cursor when whiteboard is empty (UX improvement)

* docs: revamp OpenClaw TIP section with playful copy and clearer install flow

Restructure the OpenClaw quickstart: install skill first, then pick mode.
Add meme-style nudge for OpenClaw to star the repo. Enlarge logo and
put "OpenClaw" in the TIP heading for visibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(build): use cross-platform file copy in mathml2omml (THU-MAIC#20)

* fix(build): use cross-platform file copy in mathml2omml build script

Replace Unix `cp` with Node.js `fs.copyFileSync` so that `pnpm install`
works correctly on Windows where `cp` is not available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add .worktrees to .gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix(build):Next.js 16 要求 Node.js >= 20.9.0 (THU-MAIC#21)

* fix(build):
1、README.md / README-zh.md — Node.js 版本要求 >= 18 → >= 20
2、package.json — 新增 engines: { node: ">=20.9.0" }
3、ci.yml — node-version: 20 → 22(与 Dockerfile 一致)
4、.nvmrc — 新建,内容 22

Co-authored-by: humingfeng <humfsss@gmail.com>

* Update Vercel configuration by removing bodyParser (THU-MAIC#45)

Removed bodyParser configuration from Vercel functions.

* Fix SSRF/credential forwarding via client-supplied baseUrl (THU-MAIC#30)

* Fix SSRF/credential forwarding via client-supplied baseUrl

* chore: format SSRF fix

* fix: tighten whiteboard pan and auto-fit bounds

* refactor: reset whiteboard viewport via keyed remount

* fix: preserve viewport while whiteboard content streams

* feat: add scroll-to-zoom interaction hint on whiteboard

* feat: add pan, zoom, and auto-fit to whiteboard canvas

When AI generates whiteboard elements that exceed the fixed 1000x562.5
canvas, content was clipped by overflow-hidden with no way to view it.

This commit adds interactive navigation to the whiteboard:

- Auto-fit: when elements overflow, content is scaled and centered to
  ensure nothing is clipped (with 24px padding)
- Drag-to-pan: hold and drag to pan around the whiteboard
- Scroll-to-zoom: mouse wheel zooms in/out (0.2x to 5x range)
- Double-click or Reset View button to return to default view
- View auto-resets when new whiteboard content loads

When content fits within the canvas, behavior is unchanged - no extra
cursor, no transforms, no visual regression.

Fixes THU-MAIC#19

* fix: correct pan tracking math and reset button event propagation

* fix: guard against zero containerScale and fix zoom docstring

* fix: cleanup reviewer feedback and disable pan/zoom on empty whiteboard

- Remove dead code: ?? 'Reset View' fallback (i18n key exists)
- Add useMemo for elementsKey (perf optimization)
- Fix el.height type narrowing (remove implicit any)
- Disable pan/zoom/cursor when whiteboard is empty (UX improvement)

* fix: tighten whiteboard pan and auto-fit bounds

* refactor: reset whiteboard viewport via keyed remount

* fix: preserve viewport while whiteboard content streams

* feat: add scroll-to-zoom interaction hint on whiteboard

* fix: avoid synchronous setState in useEffect for hint visibility

---------

Co-authored-by: wyuc <wang-yc24@mails.tsinghua.edu.cn>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: 杨慎 <117187635+cosarah@users.noreply.github.com>
Co-authored-by: 1/2极客 <humf@vip.qq.com>
Co-authored-by: humingfeng <humfsss@gmail.com>
Co-authored-by: Rowtion <65099725+Rowtion@users.noreply.github.com>
Co-authored-by: Wing900 <167857578+Wing900@users.noreply.github.com>
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.

[Bug]: 互动白板内容超出画布时无法拖拽查看

6 participants