Skip to content

Conversation

@congzhou09
Copy link
Contributor

@congzhou09 congzhou09 commented Dec 9, 2025

Problem

●Similar to PR#14015, the container's own scaling factor (viewScale) was not taken into account. This time the issue affects non-canvas blocks (e.g. edgeless-note, edgeless-image, and any component extending GfxBlockComponent).
●The follwing image and video show the case when zoom is 0.5.

图片
before.mp4

Solution

●Incorporated viewScale into the CSS translate calculation for all GfxBlockComponent instances.

Additional Improvement

●Minor refactor: the class returned by toGfxBlockComponent() now reuses the original getCSSTransform() implementation from GfxBlockComponent.prototype via .call(this), eliminating duplicated code.

After

●The refined is as follows.

after.mp4

Summary by CodeRabbit

  • Refactor
    • Improved viewport scaling so visual transforms (translation and zoom) correctly account for view scale, yielding more consistent rendering during zoom and pan.
    • Centralized transform calculation to a shared implementation, reducing duplication and ensuring uniform behavior across views.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 9, 2025

Walkthrough

Refactors CSS transform computation in gfx-block-component to use viewport's viewScale. Translations (X/Y) and scale are divided by viewScale; wrapper now delegates getCSSTransform to the base GfxBlockComponent implementation.

Changes

Cohort / File(s) Change Summary
CSS transform and wrapper update
blocksuite/framework/std/src/view/element/gfx-block-component.ts
Adjusted getCSSTransform to read viewScale from viewport and divide translations and scale by viewScale; removed inlined transform logic from the toGfxBlockComponent wrapper and delegate to base implementation.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Inspect viewScale retrieval and division to ensure no integer/zero-edge cases
  • Verify delta translation math and that delegation preserves prior behavior
  • Check visual output at multiple viewport scales

Poem

🐰 I nibble at pixels, tidy and neat,
ViewScale now waltzes with every repeat;
Translates and zooms find their proper place,
A cleaner transform, hopping with grace. 🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main issue (incorrect positioning/size) and the specific context (non-canvas blocks in embed-edgeless-doc at non-1 zoom), matching the core change in the PR.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
blocksuite/framework/std/src/view/element/gfx-block-component.ts (1)

108-119: viewScale-aware transform looks consistent; consider guarding against viewScale = 0 and minor cleanup

  • The new math (scaledX = (bound.x * zoom) / viewScale, same for y, and dividing translateX/translateY and zoom by viewScale) preserves the old behavior when viewScale === 1 and correctly compensates for an outer container scale so the effective zoom remains zoom. This matches the PR goal of fixing embed behavior when the container itself is scaled.
  • One edge case to double-check: viewport.viewScale is computed as boundingClientRect.width / _cachedOffsetWidth. If boundingClientRect.width can be 0 while _cachedOffsetWidth > 0, viewScale becomes 0, and this function will divide by zero, yielding Infinity/NaN in the CSS transform. It may be safer to clamp viewScale to a small positive value (or 1) in the viewport getter so all consumers are protected.
  • Optional: for readability, you could factor out the combined scale once and reuse it, e.g.:
-    const { translateX, translateY, zoom, viewScale } = viewport;
+    const { translateX, translateY, zoom, viewScale } = viewport;
+    const scale = zoom / viewScale;
     const bound = Bound.deserialize(this.model.xywh);
 
-    const scaledX = (bound.x * zoom) / viewScale;
-    const scaledY = (bound.y * zoom) / viewScale;
+    const scaledX = bound.x * scale;
+    const scaledY = bound.y * scale;
     const deltaX = scaledX - bound.x;
     const deltaY = scaledY - bound.y;
 
-    return `translate(${translateX / viewScale + deltaX}px, ${translateY / viewScale + deltaY}px) scale(${zoom / viewScale})`;
+    return `translate(${translateX / viewScale + deltaX}px, ${translateY / viewScale + deltaY}px) scale(${scale})`;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 90d0ca8 and 7d3a590.

📒 Files selected for processing (1)
  • blocksuite/framework/std/src/view/element/gfx-block-component.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
blocksuite/framework/std/src/view/element/gfx-block-component.ts (4)
blocksuite/affine/blocks/root/src/edgeless/edgeless-root-service.ts (2)
  • viewport (103-105)
  • zoom (107-109)
blocksuite/affine/blocks/embed/src/common/to-edgeless-embed-block.ts (1)
  • bound (33-35)
tests/blocksuite/e2e/utils/asserts.ts (1)
  • Bound (106-106)
blocksuite/framework/std/src/gfx/viewport.ts (3)
  • viewScale (216-224)
  • translateX (230-232)
  • translateY (234-236)
🔇 Additional comments (1)
blocksuite/framework/std/src/view/element/gfx-block-component.ts (1)

222-224: Good reuse of base getCSSTransform in wrapper

Delegating toGfxBlockComponent’s getCSSTransform to GfxBlockComponent.prototype.getCSSTransform.call(this) removes duplication and guarantees wrapper-based gfx blocks stay in sync with the core transform logic (including future viewScale tweaks). This is a solid refactor for maintainability.

@codecov
Copy link

codecov bot commented Dec 9, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 56.53%. Comparing base (2efb41f) to head (7d3a590).
⚠️ Report is 2 commits behind head on canary.

Additional details and impacted files
@@            Coverage Diff             @@
##           canary   #14074      +/-   ##
==========================================
- Coverage   56.53%   56.53%   -0.01%     
==========================================
  Files        2757     2757              
  Lines      138059   138052       -7     
  Branches    21048    21052       +4     
==========================================
- Hits        78053    78045       -8     
- Misses      57741    58319     +578     
+ Partials     2265     1688     -577     
Flag Coverage Δ
server-test 77.02% <ø> (ø)
unittest 31.96% <100.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@darkskygit darkskygit changed the title fix: incorrect positioning and size of non-canvas blocks in embed-edgeless-doc when viewport zoom ≠ 1 fix(editor): non-canvas block size/position in embed-edgeless-doc at non-1 zoom Dec 9, 2025
@darkskygit darkskygit requested review from CatsJuice and L-Sun December 9, 2025 16:04
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
blocksuite/framework/std/src/view/element/gfx-block-component.ts (1)

222-224: Excellent refactoring to eliminate code duplication.

Delegating to the base class implementation ensures consistency and reduces maintenance overhead. This change automatically benefits from the viewScale fix in the base getCSSTransform method.

Consider applying the same delegation pattern to other methods in the wrapper that duplicate base class logic, such as getRenderingRect (lines 227-246) and scheduleUpdate (lines 269-281), if they remain identical to the base implementation.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7d3a590 and 77de029.

📒 Files selected for processing (1)
  • blocksuite/framework/std/src/view/element/gfx-block-component.ts (2 hunks)
🔇 Additional comments (1)
blocksuite/framework/std/src/view/element/gfx-block-component.ts (1)

108-119: Verify that viewScale is always positive and non-zero.

The division operations using viewScale on lines 113, 114, and 118 could produce Infinity or NaN if viewScale is 0, or incorrect visual behavior if it's negative. Please ensure the viewport guarantees viewScale > 0.

@darkskygit darkskygit enabled auto-merge January 7, 2026 03:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants