Skip to content

feat(dia): support HTML element bounding rect in getNodeBoundingRect#3258

Open
Geliogabalus wants to merge 11 commits intoclientIO:masterfrom
Geliogabalus:html-node-bbox
Open

feat(dia): support HTML element bounding rect in getNodeBoundingRect#3258
Geliogabalus wants to merge 11 commits intoclientIO:masterfrom
Geliogabalus:html-node-bbox

Conversation

@Geliogabalus
Copy link
Copy Markdown
Contributor

@Geliogabalus Geliogabalus commented Mar 31, 2026

Problem

Two related issues when using HTML element magnets (elements inside <foreignObject>) with links:

  1. getNodeBoundingRect on HTMLElement used V(magnet).getBBox(), which returns the SVG bounding box of the foreignObject wrapper — not the actual HTML node. On rotated elements this inflates the dimensions incorrectly (the SVG bbox of a rotated rect is larger than the unrotated rect), causing wrong connection point calculations.

  2. rectangleIntersection used bboxWORotation.center() as the rotation pivot, which is the magnet's center. For port or HTML magnets that are not at the element's center, this is the wrong pivot — JointJS always rotates elements around their own model center.

  3. boundaryIntersection fell back to returning the raw anchor point when the node was not an SVGGraphicsElement (e.g. an HTMLElement). This skipped intersection calculation entirely, attaching links at the anchor rather than on the element's boundary.

Changes

dia/CellView.mjsgetNodeBoundingRect HTML support

  • Detects HTMLElement magnets and measures them via getBoundingClientRect() + clientToLocalPoint() to get the center in local paper coordinates
  • Applies the inverse of the translate+rotate matrix to strip the element's rotation, yielding the pre-rotation center
  • Uses offsetWidth / offsetHeight (intrinsic, non-inflated dimensions) for width/height — avoiding the inflation that the SVG bbox incurs on rotated elements
  • When the HTML node is invisible (checkVisibility() returns false), returns a zero rect and emits a console.warn instead of silently producing wrong geometry

connectionPoints/index.mjs

  • rectangleIntersection: pivot fixed to view.model.getBBox().center() — the element's actual rotation origin — instead of the magnet's bbox center
  • boundaryIntersection: non-SVG (HTML) magnets now route through rectangleIntersection instead of returning the raw anchor, giving a proper boundary connection point

examples/foreign-object-magnet-js

  • New standalone example demonstrating links connecting to HTML badge magnets on a rotated element (via foreignObject), exercising both the rotated HTML bbox measurement and rectangleIntersection pivot fix

Test plan

  • Link targeting an HTML magnet on an unrotated element attaches at the correct boundary point
  • Link targeting an HTML magnet on a rotated element attaches at the correct boundary point and the bbox is not inflated
  • Invisible HTML magnet logs a warning to the console and does not crash
  • measureNode paper option still takes precedence over built-in HTML measurement
  • Links using connectionPoint: { name: 'rectangle' } on a rotated element with a port magnet connect to the correct side (rotation pivot fix)
  • boundaryIntersection on an HTML magnet produces a boundary intersection (not the raw anchor)

🤖 Generated with Claude Code

@Geliogabalus Geliogabalus marked this pull request as draft March 31, 2026 12:57
@Geliogabalus Geliogabalus marked this pull request as ready for review April 1, 2026 12:37
@Geliogabalus Geliogabalus requested a review from Copilot April 1, 2026 12:37
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds support for measuring HTML magnets (e.g. inside <foreignObject>) in CellView#getNodeBoundingRect() so bounding rectangles can be computed for non-SVG nodes.

Changes:

  • Updated getNodeBoundingRect() to use HTMLElement#getBoundingClientRect() for visible HTML magnets and fall back to an SVG ancestor bbox for invisible ones.
  • Added QUnit tests covering SVG magnets, measureNode, visible/invisible HTML magnets, and caching behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
packages/joint-core/src/dia/CellView.mjs Implements new HTML-element measurement logic in getNodeBoundingRect().
packages/joint-core/test/jointjs/cellView.js Adds test coverage for the new HTML measurement branches and caching.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Geliogabalus Geliogabalus requested a review from kumilingus April 9, 2026 08:33
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Geliogabalus Geliogabalus requested a review from kumilingus April 10, 2026 11:53
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.

3 participants