Add an option to selection objects only when 100% intersect (#4508)

* Add an option to selection objects only when 100% intersect

* Better description

* Cache property negation

* Add unit tests

* Remove boundary tests, not specific to this option
This commit is contained in:
Jérôme Steunou 2017-11-29 12:40:17 +01:00 committed by Andrea Bogazzi
parent 0496c0d120
commit 7b64898d72
3 changed files with 52 additions and 3 deletions

View file

@ -178,6 +178,13 @@
*/
selectionLineWidth: 1,
/**
* Select only shapes that are fully contained in the dragged selection rectangle.
* @type Boolean
* @default
*/
selectionFullyContained: false,
/**
* Default cursor value used when hovering over an object on canvas
* @type String

View file

@ -124,6 +124,7 @@
y2 = y1 + this._groupSelector.top,
selectionX1Y1 = new fabric.Point(min(x1, x2), min(y1, y2)),
selectionX2Y2 = new fabric.Point(max(x1, x2), max(y1, y2)),
allowIntersect = !this.selectionFullyContained,
isClick = x1 === x2 && y1 === y2;
// we iterate reverse order to collect top first in case of click.
for (var i = this._objects.length; i--; ) {
@ -133,10 +134,10 @@
continue;
}
if (currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2) ||
if ((allowIntersect && currentObject.intersectsWithRect(selectionX1Y1, selectionX2Y2)) ||
currentObject.isContainedWithinRect(selectionX1Y1, selectionX2Y2) ||
currentObject.containsPoint(selectionX1Y1) ||
currentObject.containsPoint(selectionX2Y2)
(allowIntersect && currentObject.containsPoint(selectionX1Y1)) ||
(allowIntersect && currentObject.containsPoint(selectionX2Y2))
) {
group.push(currentObject);

View file

@ -531,6 +531,47 @@
assert.equal(collected[2], rect1, 'rect1 is collected');
});
QUnit.test('_collectObjects collects object fully contained in area', function(assert) {
canvas.selectionFullyContained = true;
var rect1 = new fabric.Rect({ width: 10, height: 10, top: 0, left: 0 });
var rect2 = new fabric.Rect({ width: 10, height: 10, top: 0, left: 10 });
var rect3 = new fabric.Rect({ width: 10, height: 10, top: 10, left: 0 });
var rect4 = new fabric.Rect({ width: 10, height: 10, top: 10, left: 10 });
canvas.add(rect1, rect2, rect3, rect4);
canvas._groupSelector = {
top: 30,
left: 30,
ex: -1,
ey: -1
};
var collected = canvas._collectObjects();
assert.equal(collected.length, 4, 'a rect that contains all objects collects them all');
assert.equal(collected[3], rect1, 'contains rect1 as last object');
assert.equal(collected[2], rect2, 'contains rect2');
assert.equal(collected[1], rect3, 'contains rect3');
assert.equal(collected[0], rect4, 'contains rect4 as first object');
canvas.selectionFullyContained = false;
});
QUnit.test('_collectObjects does not collect objects not fully contained', function(assert) {
canvas.selectionFullyContained = true;
var rect1 = new fabric.Rect({ width: 10, height: 10, top: 0, left: 0 });
var rect2 = new fabric.Rect({ width: 10, height: 10, top: 0, left: 10 });
var rect3 = new fabric.Rect({ width: 10, height: 10, top: 10, left: 0 });
var rect4 = new fabric.Rect({ width: 10, height: 10, top: 10, left: 10 });
canvas.add(rect1, rect2, rect3, rect4);
canvas._groupSelector = {
top: 20,
left: 20,
ex: 5,
ey: 5
};
var collected = canvas._collectObjects();
assert.equal(collected.length, 1, 'a rect intersecting objects does not collect those');
assert.equal(collected[0], rect4, 'contains rect1 as only one fully contained');
canvas.selectionFullyContained = false;
});
QUnit.test('_fireSelectionEvents fires multiple things', function(assert) {
var rect1Deselected = false;
var rect3Selected = false;