mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-05 20:32:00 -05:00
Implement match.inside and match.overlapping in #getItems(match).
Closes #275
This commit is contained in:
parent
99ef521af4
commit
e7707cd354
2 changed files with 71 additions and 10 deletions
|
@ -1905,15 +1905,26 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
||||||
* of the full object, not partial matching (e.g. only providing the x-
|
* of the full object, not partial matching (e.g. only providing the x-
|
||||||
* coordinate to match all points with that x-value). Partial matching
|
* coordinate to match all points with that x-value). Partial matching
|
||||||
* does work for {@link Item#data}.
|
* does work for {@link Item#data}.
|
||||||
|
*
|
||||||
|
* Matching items against a rectangular area is also possible, by setting
|
||||||
|
* either {@code match.inside} or {@code match.overlapping} to a rectangle
|
||||||
|
* describing the area in which the items either have to be fully or partly
|
||||||
|
* contained.
|
||||||
|
*
|
||||||
* See {@link Project#getItems(match)} for a selection of illustrated
|
* See {@link Project#getItems(match)} for a selection of illustrated
|
||||||
* examples.
|
* examples.
|
||||||
*
|
*
|
||||||
|
* @option match.inside {Rectangle} the rectangle in which the items need to
|
||||||
|
* be fully contained.
|
||||||
|
* @option match.overlapping {Rectangle} the rectangle with which the need
|
||||||
|
* to be at least partly overlap.
|
||||||
|
*
|
||||||
* @see #matches(match)
|
* @see #matches(match)
|
||||||
* @param {Object} match the criteria to match against.
|
* @param {Object} match the criteria to match against.
|
||||||
* @return {Item[]} the list of matching descendant items.
|
* @return {Item[]} the list of matching descendant items.
|
||||||
*/
|
*/
|
||||||
getItems: function(match) {
|
getItems: function(match) {
|
||||||
return Item._getItems(this._children, match);
|
return Item._getItems(this._children, match, this._matrix);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1932,25 +1943,66 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
||||||
* @return {Item} the first descendant item matching the given criteria.
|
* @return {Item} the first descendant item matching the given criteria.
|
||||||
*/
|
*/
|
||||||
getItem: function(match) {
|
getItem: function(match) {
|
||||||
return Item._getItems(this._children, match, true)[0] || null;
|
return Item._getItems(this._children, match, this._matrix, null, true)
|
||||||
|
[0] || null;
|
||||||
},
|
},
|
||||||
|
|
||||||
statics: {
|
statics: {
|
||||||
// NOTE: We pass children instead of item as first argument so the
|
// NOTE: We pass children instead of item as first argument so the
|
||||||
// method can be used for Project#layers as well in Project.
|
// method can be used for Project#layers as well in Project.
|
||||||
_getItems: function _getItems(children, match, firstOnly) {
|
_getItems: function _getItems(children, match, matrix, param,
|
||||||
var items = [];
|
firstOnly) {
|
||||||
|
if (!param) {
|
||||||
|
// Set up a couple of "side-car" values for the recursive calls
|
||||||
|
// of _getItems below, mainly related to the handling of
|
||||||
|
// inside // overlapping:
|
||||||
|
var overlapping = match.overlapping,
|
||||||
|
inside = match.inside,
|
||||||
|
// If overlapping is set, we also perform the inside check:
|
||||||
|
bounds = overlapping || inside,
|
||||||
|
rect = bounds && Rectangle.read([bounds]);
|
||||||
|
param = {
|
||||||
|
items: [], // The list to contain the results.
|
||||||
|
inside: rect,
|
||||||
|
overlapping: overlapping && new Path.Rectangle({
|
||||||
|
rectangle: rect,
|
||||||
|
insert: false
|
||||||
|
})
|
||||||
|
};
|
||||||
|
// Create a copy of the match object that doesn't contain the
|
||||||
|
// `inside` and `overlapping` properties.
|
||||||
|
if (bounds)
|
||||||
|
match = Base.set({}, match,
|
||||||
|
{ inside: true, overlapping: true });
|
||||||
|
}
|
||||||
|
var items = param.items,
|
||||||
|
inside = param.inside,
|
||||||
|
overlapping = param.overlapping;
|
||||||
|
matrix = inside && (matrix || new Matrix());
|
||||||
for (var i = 0, l = children && children.length; i < l; i++) {
|
for (var i = 0, l = children && children.length; i < l; i++) {
|
||||||
var child = children[i];
|
var child = children[i],
|
||||||
if (child.matches(match)) {
|
childMatrix = matrix && matrix.chain(child._matrix),
|
||||||
|
add = true;
|
||||||
|
if (inside) {
|
||||||
|
var bounds = child.getBounds(childMatrix);
|
||||||
|
// Regardless of the setting of inside / overlapping, if the
|
||||||
|
// bounds don't even overlap, we can skip this child.
|
||||||
|
if (!inside.intersects(bounds))
|
||||||
|
continue;
|
||||||
|
if (!(inside && inside.contains(bounds)) && !(overlapping
|
||||||
|
&& overlapping.intersects(child, childMatrix)))
|
||||||
|
add = false;
|
||||||
|
}
|
||||||
|
if (add && child.matches(match)) {
|
||||||
items.push(child);
|
items.push(child);
|
||||||
if (firstOnly)
|
if (firstOnly)
|
||||||
return items;
|
break;
|
||||||
}
|
}
|
||||||
var res = _getItems(child._children, match, firstOnly);
|
_getItems(child._children, match,
|
||||||
items.push.apply(items, res);
|
childMatrix, param,
|
||||||
|
firstOnly);
|
||||||
if (firstOnly && items.length > 0)
|
if (firstOnly && items.length > 0)
|
||||||
return items;
|
break;
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,6 +348,15 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{
|
||||||
* of the full object, not partial matching (e.g. only providing the x-
|
* of the full object, not partial matching (e.g. only providing the x-
|
||||||
* coordinate to match all points with that x-value). Partial matching
|
* coordinate to match all points with that x-value). Partial matching
|
||||||
* does work for {@link Item#data}.
|
* does work for {@link Item#data}.
|
||||||
|
* Matching items against a rectangular area is also possible, by setting
|
||||||
|
* either {@code match.inside} or {@code match.overlapping} to a rectangle
|
||||||
|
* describing the area in which the items either have to be fully or partly
|
||||||
|
* contained.
|
||||||
|
*
|
||||||
|
* @option match.inside {Rectangle} the rectangle in which the items need to
|
||||||
|
* be fully contained.
|
||||||
|
* @option match.overlapping {Rectangle} the rectangle with which the need
|
||||||
|
* to be at least partly overlap.
|
||||||
*
|
*
|
||||||
* @example {@paperscript} // Fetch all selected path items:
|
* @example {@paperscript} // Fetch all selected path items:
|
||||||
* var path1 = new Path.Circle({
|
* var path1 = new Path.Circle({
|
||||||
|
|
Loading…
Reference in a new issue