Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .codesandbox/templates/vanilla/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as fabric from 'fabric';
import './styles.css';
import { testCase } from './testcases/clipPathSelection';
import { testCase } from './testcases/selections';

const el = document.getElementById('canvas');
const canvas = (window.canvas = new fabric.Canvas(el, {
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## [next]

- fix(): Impossible to select object above the Active selection [#10483](https://github.com/fabricjs/fabric.js/pull/10483)
- ci(): fix Coverage is not being reported anymore [#10617](https://github.com/fabricjs/fabric.js/pull/10617)
- refactor(tests): move free draw rendering tests from qunit to playwright [#10616](https://github.com/fabricjs/fabric.js/pull/10616)
- refactor(tests): move resize filter test cases from qunit to playwright [#10615](https://github.com/fabricjs/fabric.js/pull/10615)
Expand Down
2 changes: 1 addition & 1 deletion src/canvas/SelectableCanvas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ describe('Selectable Canvas', () => {
});
const groupB = new Group([object], {
id: 'b',
interactive: true,
interactive: false,
subTargetCheck: true,
});
const groupC = new Group([groupB], {
Expand Down
30 changes: 21 additions & 9 deletions src/canvas/SelectableCanvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -720,17 +720,28 @@ export class SelectableCanvas<EventSpec extends CanvasEvents = CanvasEvents>

this.targets = [];

// a lot of special cases for when the object is already active
if (activeObject && aObjects.length >= 1) {
// it there is an active object and we click its corner
if (activeObject.findControl(pointer, isTouchEvent(e))) {
// if we hit the corner of the active object, let's return that.
// let's keep the target on the corner.
// This is a common sense thing that works for everyone
return activeObject;
} else if (
}
// We need to look for this in many cases, doesn't make sense to skip it.
const globalTarget = this.searchPossibleTargets(this._objects, pointer);
if (
// otherwise if is an active selection
aObjects.length > 1 &&
// check pointer is over active selection and possibly perform `subTargetCheck`
this.searchPossibleTargets([activeObject], pointer)
activeObject === this._searchPossibleTargets([activeObject], pointer)
) {
// active selection does not select sub targets like normal groups
return activeObject;
if (globalTarget && globalTarget.group === activeObject) {
// active selection does not select sub targets like normal groups
return activeObject;
} else {
return globalTarget ?? activeObject;
}
} else if (
activeObject === this.searchPossibleTargets([activeObject], pointer)
) {
Expand All @@ -740,7 +751,7 @@ export class SelectableCanvas<EventSpec extends CanvasEvents = CanvasEvents>
} else {
const subTargets = this.targets;
this.targets = [];
const target = this.searchPossibleTargets(this._objects, pointer);
const target = globalTarget;
if (
e[this.altSelectionKey as ModifierKey] &&
target &&
Expand All @@ -755,7 +766,6 @@ export class SelectableCanvas<EventSpec extends CanvasEvents = CanvasEvents>
}
}
}

return this.searchPossibleTargets(this._objects, pointer);
}

Expand Down Expand Up @@ -833,7 +843,7 @@ export class SelectableCanvas<EventSpec extends CanvasEvents = CanvasEvents>
}

/**
* Internal Function used to search inside objects an object that contains pointer in bounding box or that contains pointerOnCanvas when painted
* Internal Function used to search inside objects an object that contains pointer in bounding box
* @param {Array} [objects] objects array to look into
* @param {Object} [pointer] x,y object of point coordinates we want to check.
* @return {FabricObject} **top most object from given `objects`** that contains pointer
Expand All @@ -855,6 +865,8 @@ export class SelectableCanvas<EventSpec extends CanvasEvents = CanvasEvents>
target._objects as FabricObject[],
pointer,
);
// being recursive this targets is filled up in reverse.
// target[0] is the last found target deep in the stack
subTarget && this.targets.push(subTarget);
}
return target;
Expand All @@ -863,7 +875,7 @@ export class SelectableCanvas<EventSpec extends CanvasEvents = CanvasEvents>
}

/**
* Function used to search inside objects an object that contains pointer in bounding box or that contains pointerOnCanvas when painted
* Function used to search inside objects an object that could be selected
* @see {@link _searchPossibleTargets}
* @param {FabricObject[]} [objects] objects array to look into
* @param {Point} [pointer] coordinates from viewport to check.
Expand Down
Loading