@teachinglab/omd 0.7.18 → 0.7.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/canvas/tools/PointerTool.js +58 -39
- package/package.json +1 -1
|
@@ -669,22 +669,61 @@ export class PointerTool extends Tool {
|
|
|
669
669
|
*/
|
|
670
670
|
_getOMDElementBounds(item) {
|
|
671
671
|
try {
|
|
672
|
-
const bbox = item.getBBox();
|
|
673
672
|
const transform = item.getAttribute('transform') || '';
|
|
674
673
|
let offsetX = 0, offsetY = 0, scaleX = 1, scaleY = 1;
|
|
675
|
-
|
|
674
|
+
|
|
676
675
|
const translateMatch = transform.match(/translate\(\s*([^,]+)\s*,\s*([^)]+)\s*\)/);
|
|
677
676
|
if (translateMatch) {
|
|
678
677
|
offsetX = parseFloat(translateMatch[1]) || 0;
|
|
679
678
|
offsetY = parseFloat(translateMatch[2]) || 0;
|
|
680
679
|
}
|
|
681
|
-
|
|
680
|
+
|
|
682
681
|
const scaleMatch = transform.match(/scale\(\s*([^,)]+)(?:\s*,\s*([^)]+))?\s*\)/);
|
|
683
682
|
if (scaleMatch) {
|
|
684
683
|
scaleX = parseFloat(scaleMatch[1]) || 1;
|
|
685
684
|
scaleY = scaleMatch[2] ? parseFloat(scaleMatch[2]) : scaleX;
|
|
686
685
|
}
|
|
687
|
-
|
|
686
|
+
|
|
687
|
+
// Use clip-rect logic (same as ResizeHandleManager) to avoid
|
|
688
|
+
// getBBox() returning the full unclipped geometry for coordinate planes.
|
|
689
|
+
const content = item.firstElementChild;
|
|
690
|
+
let bbox = null;
|
|
691
|
+
|
|
692
|
+
if (content) {
|
|
693
|
+
const clipPaths = content.querySelectorAll('clipPath');
|
|
694
|
+
if (clipPaths.length > 0) {
|
|
695
|
+
let maxArea = 0;
|
|
696
|
+
for (const clipPath of clipPaths) {
|
|
697
|
+
const rect = clipPath.querySelector('rect');
|
|
698
|
+
if (rect) {
|
|
699
|
+
const w = parseFloat(rect.getAttribute('width')) || 0;
|
|
700
|
+
const h = parseFloat(rect.getAttribute('height')) || 0;
|
|
701
|
+
const x = parseFloat(rect.getAttribute('x')) || 0;
|
|
702
|
+
const y = parseFloat(rect.getAttribute('y')) || 0;
|
|
703
|
+
if (w * h > maxArea) {
|
|
704
|
+
maxArea = w * h;
|
|
705
|
+
// Account for the content group's own translate
|
|
706
|
+
const contentGroup = content.firstElementChild;
|
|
707
|
+
let tx = 0, ty = 0;
|
|
708
|
+
if (contentGroup) {
|
|
709
|
+
const t = contentGroup.getAttribute('transform');
|
|
710
|
+
if (t) {
|
|
711
|
+
const m = t.match(/translate\(\s*([^,]+)(?:,\s*([^)]+))?\s*\)/);
|
|
712
|
+
if (m) { tx = parseFloat(m[1]) || 0; ty = parseFloat(m[2]) || 0; }
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
bbox = { x: x + tx, y: y + ty, width: w, height: h };
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
if (!bbox) {
|
|
721
|
+
bbox = content.getBBox();
|
|
722
|
+
}
|
|
723
|
+
} else {
|
|
724
|
+
bbox = item.getBBox();
|
|
725
|
+
}
|
|
726
|
+
|
|
688
727
|
return {
|
|
689
728
|
x: offsetX + (bbox.x * scaleX),
|
|
690
729
|
y: offsetY + (bbox.y * scaleY),
|
|
@@ -740,41 +779,18 @@ export class PointerTool extends Tool {
|
|
|
740
779
|
continue;
|
|
741
780
|
}
|
|
742
781
|
try {
|
|
743
|
-
//
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
let offsetX = 0, offsetY = 0, scaleX = 1, scaleY = 1;
|
|
749
|
-
|
|
750
|
-
// Parse translate
|
|
751
|
-
const translateMatch = transform.match(/translate\(\s*([^,]+)\s*,\s*([^)]+)\s*\)/);
|
|
752
|
-
if (translateMatch) {
|
|
753
|
-
offsetX = parseFloat(translateMatch[1]) || 0;
|
|
754
|
-
offsetY = parseFloat(translateMatch[2]) || 0;
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
// Parse scale
|
|
758
|
-
const scaleMatch = transform.match(/scale\(\s*([^,)]+)(?:\s*,\s*([^)]+))?\s*\)/);
|
|
759
|
-
if (scaleMatch) {
|
|
760
|
-
scaleX = parseFloat(scaleMatch[1]) || 1;
|
|
761
|
-
scaleY = scaleMatch[2] ? parseFloat(scaleMatch[2]) : scaleX;
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
// Calculate the actual bounds including transform
|
|
765
|
-
const actualX = offsetX + (bbox.x * scaleX);
|
|
766
|
-
const actualY = offsetY + (bbox.y * scaleY);
|
|
767
|
-
const actualWidth = bbox.width * scaleX;
|
|
768
|
-
const actualHeight = bbox.height * scaleY;
|
|
769
|
-
|
|
782
|
+
// Reuse _getOMDElementBounds which applies clip-rect logic
|
|
783
|
+
// to avoid oversized hit areas on coordinate planes.
|
|
784
|
+
const bounds = this._getOMDElementBounds(item);
|
|
785
|
+
if (!bounds) continue;
|
|
786
|
+
|
|
770
787
|
// Add some padding for easier clicking
|
|
771
788
|
const padding = 10;
|
|
772
789
|
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
y
|
|
777
|
-
y <= actualY + actualHeight + padding) {
|
|
790
|
+
if (x >= bounds.x - padding &&
|
|
791
|
+
x <= bounds.x + bounds.width + padding &&
|
|
792
|
+
y >= bounds.y - padding &&
|
|
793
|
+
y <= bounds.y + bounds.height + padding) {
|
|
778
794
|
return item;
|
|
779
795
|
}
|
|
780
796
|
} catch (error) {
|
|
@@ -972,9 +988,12 @@ export class PointerTool extends Tool {
|
|
|
972
988
|
selectionLayer.removeChild(selectionLayer.firstChild);
|
|
973
989
|
}
|
|
974
990
|
|
|
975
|
-
// If
|
|
976
|
-
//
|
|
977
|
-
|
|
991
|
+
// If a single OMD element was directly clicked, ResizeHandleManager already draws
|
|
992
|
+
// its own selection border + handles — don't draw a second box on top of it.
|
|
993
|
+
// For drag-box selections (no active resizeHandleManager element), always draw the box.
|
|
994
|
+
if (this.selectedSegments.size === 0 &&
|
|
995
|
+
this.selectedOMDElements.size > 0 &&
|
|
996
|
+
this.resizeHandleManager?.selectedElement !== null) {
|
|
978
997
|
return;
|
|
979
998
|
}
|
|
980
999
|
|