2011-07-13 11:35:54 -04:00
|
|
|
/*
|
2013-01-28 21:03:27 -05:00
|
|
|
* Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
|
2011-07-13 11:35:54 -04:00
|
|
|
* http://paperjs.org/
|
|
|
|
*
|
2015-12-27 12:09:25 -05:00
|
|
|
* Copyright (c) 2011 - 2016, Juerg Lehni & Jonathan Puckey
|
2014-01-03 19:47:16 -05:00
|
|
|
* http://scratchdisk.com/ & http://jonathanpuckey.com/
|
2011-07-13 11:35:54 -04:00
|
|
|
*
|
|
|
|
* Distributed under the MIT license. See LICENSE file for details.
|
|
|
|
*
|
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2016-01-27 13:57:07 -05:00
|
|
|
QUnit.module('HitResult');
|
2011-07-13 11:35:54 -04:00
|
|
|
|
2015-12-27 19:05:54 -05:00
|
|
|
test('Hit-testing options', function() {
|
2015-04-12 09:14:03 -04:00
|
|
|
var defaultOptions = {
|
|
|
|
type: null,
|
|
|
|
tolerance: paper.settings.hitTolerance,
|
|
|
|
fill: true,
|
|
|
|
stroke: true,
|
|
|
|
segments: true,
|
|
|
|
handles: false,
|
|
|
|
ends: false,
|
|
|
|
center: false,
|
|
|
|
bounds: false,
|
|
|
|
guides: false,
|
|
|
|
selected: false
|
|
|
|
};
|
|
|
|
equals(HitResult.getOptions(), defaultOptions, 'Default options');
|
|
|
|
});
|
|
|
|
|
2011-07-13 11:35:54 -04:00
|
|
|
test('hitting a filled shape', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path.Circle([50, 50], 50);
|
|
|
|
|
|
|
|
var hitResult = path.hitTest([75, 75]);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult == null;
|
|
|
|
}, true, 'Since the path is not filled, the hit-test should return null');
|
|
|
|
|
|
|
|
path.fillColor = 'red';
|
|
|
|
hitResult = path.hitTest([75, 75]);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.type == 'fill';
|
|
|
|
}, true);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.item == path;
|
|
|
|
}, true);
|
2011-07-13 11:35:54 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('the item on top should be returned', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path.Circle([50, 50], 50);
|
|
|
|
path.fillColor = 'red';
|
2011-07-13 11:35:54 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
// The cloned path is lying above the path:
|
|
|
|
var copy = path.clone();
|
2011-07-13 11:35:54 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
var hitResult = paper.project.hitTest([75, 75]);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.item == copy;
|
|
|
|
}, true);
|
2011-07-13 11:35:54 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('hitting a stroked path', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path([0, 0], [50, 0]);
|
|
|
|
|
2014-10-20 17:33:28 -04:00
|
|
|
// We are hit-testing with an offset of 5pt on a path with a stroke width
|
2014-08-16 13:24:54 -04:00
|
|
|
// of 10:
|
|
|
|
|
|
|
|
var hitResult = paper.project.hitTest([25, 5]);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult == null;
|
|
|
|
}, true, 'Since the path is not stroked yet, the hit-test should return null');
|
|
|
|
|
|
|
|
path.strokeColor = 'black';
|
|
|
|
path.strokeWidth = 10;
|
|
|
|
hitResult = path.hitTest([25, 5]);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.type == 'stroke';
|
|
|
|
}, true);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.item == path;
|
|
|
|
}, true);
|
2011-07-13 11:35:54 -04:00
|
|
|
});
|
|
|
|
|
2011-07-14 08:24:32 -04:00
|
|
|
test('hitting a selected path', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path.Circle([50, 50], 50);
|
|
|
|
path.fillColor = 'red';
|
|
|
|
|
|
|
|
var hitResult = paper.project.hitTest([75, 75], {
|
|
|
|
selected: true
|
|
|
|
});
|
|
|
|
equals(function() {
|
|
|
|
return hitResult == null;
|
|
|
|
}, true, 'Since the path is not selected, the hit-test should return null');
|
|
|
|
|
|
|
|
path.selected = true;
|
|
|
|
hitResult = paper.project.hitTest([75, 75]);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.type == 'fill';
|
|
|
|
}, true);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.item == path;
|
|
|
|
}, true);
|
2011-07-14 08:24:32 -04:00
|
|
|
});
|
|
|
|
|
2011-07-13 12:19:00 -04:00
|
|
|
test('hitting path segments', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path([0, 0], [10, 10], [20, 0]);
|
2011-07-13 12:19:00 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
var hitResult = paper.project.hitTest([10, 10]);
|
2014-04-06 07:48:03 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
equals(function() {
|
|
|
|
return !!hitResult;
|
|
|
|
}, true, 'A HitResult should be returned.');
|
2014-04-06 07:48:03 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
if (hitResult) {
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.type;
|
|
|
|
}, 'segment');
|
2014-04-06 07:48:03 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
equals(function() {
|
|
|
|
return hitResult.item == path;
|
|
|
|
}, true);
|
|
|
|
}
|
2011-07-13 12:19:00 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('hitting the center of a path', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path([0, 0], [100, 100], [200, 0]);
|
|
|
|
path.closed = true;
|
|
|
|
|
|
|
|
var hitResult = paper.project.hitTest(path.position, {
|
|
|
|
center: true
|
|
|
|
});
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return !!hitResult;
|
|
|
|
}, true, 'A HitResult should be returned.');
|
|
|
|
|
|
|
|
if (hitResult) {
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.point.toString();
|
|
|
|
}, path.position.toString());
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.type;
|
|
|
|
}, 'center');
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.item !== paper.project.activeLayer;
|
|
|
|
}, true, 'We should not be hitting the active layer.');
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.item == path;
|
|
|
|
}, true, 'We should be hitting the path.');
|
|
|
|
}
|
2011-07-13 12:19:00 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('hitting the center of a path with tolerance', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path([0, 0], [100, 100], [200, 0]);
|
|
|
|
path.closed = true;
|
|
|
|
var offset = new Point(1, 1);
|
|
|
|
var hitResult = paper.project.hitTest(path.position.add(offset), {
|
|
|
|
tolerance: offset.length,
|
|
|
|
center: true
|
|
|
|
});
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return !!hitResult;
|
|
|
|
}, true, 'A HitResult should be returned.');
|
|
|
|
|
|
|
|
if (hitResult) {
|
|
|
|
equals(function() {
|
|
|
|
return !!hitResult.point;
|
|
|
|
}, true, 'HitResult#point should not be empty');
|
|
|
|
|
|
|
|
if (hitResult.point) {
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.point.toString();
|
|
|
|
}, path.position.toString());
|
|
|
|
}
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.type;
|
|
|
|
}, 'center');
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.item !== paper.project.activeLayer;
|
|
|
|
}, true, 'We should not be hitting the active layer.');
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.item == path;
|
|
|
|
}, true, 'We should be hitting the path.');
|
|
|
|
}
|
2011-07-13 12:19:00 -04:00
|
|
|
});
|
|
|
|
|
2011-07-13 11:35:54 -04:00
|
|
|
test('hitting path handles', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path.Circle(new Point(), 10);
|
|
|
|
path.firstSegment.handleIn = [-50, 0];
|
|
|
|
path.firstSegment.handleOut = [50, 0];
|
|
|
|
var firstPoint = path.firstSegment.point;
|
|
|
|
var hitResult = paper.project.hitTest(firstPoint.add(50, 0), {
|
|
|
|
handles: true
|
|
|
|
});
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return !!hitResult;
|
|
|
|
}, true, 'A HitResult should be returned (1)');
|
|
|
|
|
|
|
|
if (hitResult) {
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.type;
|
|
|
|
}, 'handle-out');
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.item == path;
|
|
|
|
}, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
var hitResult = paper.project.hitTest(firstPoint.add(-50, 0), {
|
|
|
|
handles: true
|
|
|
|
});
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return !!hitResult;
|
|
|
|
}, true, 'A HitResult should be returned (2)');
|
|
|
|
|
|
|
|
if (hitResult) {
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.type;
|
|
|
|
}, 'handle-in');
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.item == path;
|
|
|
|
}, true);
|
|
|
|
}
|
2011-07-15 08:53:54 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('hitting path handles (2)', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path(new Segment({
|
|
|
|
point: [0, 0],
|
|
|
|
handleIn: [-50, -50],
|
|
|
|
handleOut: [50, 50]
|
|
|
|
}));
|
|
|
|
|
|
|
|
var hitResult = paper.project.hitTest([50, 50], {
|
|
|
|
handles: true
|
|
|
|
});
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return !!hitResult;
|
|
|
|
}, true, 'A HitResult should be returned (1)');
|
|
|
|
|
|
|
|
if (hitResult) {
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.type;
|
|
|
|
}, 'handle-out');
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.item == path;
|
|
|
|
}, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
var hitResult = paper.project.hitTest([-50, -50], {
|
|
|
|
handles: true
|
|
|
|
});
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return !!hitResult;
|
|
|
|
}, true, 'A HitResult should be returned (2)');
|
|
|
|
|
|
|
|
if (hitResult) {
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.type;
|
|
|
|
}, 'handle-in');
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.item == path;
|
|
|
|
}, true);
|
|
|
|
}
|
2011-07-13 12:19:00 -04:00
|
|
|
});
|
|
|
|
|
2014-10-20 17:33:28 -04:00
|
|
|
test('hit-testing stroke on segment point of a path', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path([0, 0], [50, 50], [100, 0]);
|
|
|
|
path.strokeColor = 'black';
|
|
|
|
path.closed = true;
|
|
|
|
|
|
|
|
var error = null;
|
|
|
|
try {
|
|
|
|
var hitResult = paper.project.hitTest(path.firstSegment.point, {
|
|
|
|
stroke: true
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
error = e;
|
|
|
|
}
|
2014-10-20 17:33:28 -04:00
|
|
|
var description = 'This hit-test should not throw an error';
|
2014-08-16 13:24:54 -04:00
|
|
|
if (error)
|
|
|
|
description += ': ' + error;
|
|
|
|
equals(error == null, true, description);
|
2011-07-15 09:07:12 -04:00
|
|
|
});
|
|
|
|
|
2015-12-27 19:05:54 -05:00
|
|
|
test('hit-testing a point that is extremely close to a curve', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path.Rectangle([0, 0], [100, 100]);
|
|
|
|
// A point whose x value is extremely close to 0:
|
|
|
|
var point = new Point(2.842 / Math.pow(10, 14), 0);
|
|
|
|
var error;
|
|
|
|
try {
|
|
|
|
var hitResult = path.hitTest(point, {
|
|
|
|
stroke: true
|
|
|
|
});
|
|
|
|
} catch(e) {
|
|
|
|
error = e;
|
|
|
|
}
|
2014-10-20 17:33:28 -04:00
|
|
|
var description = 'This hit-test should not throw an error';
|
2014-08-16 13:24:54 -04:00
|
|
|
if (error)
|
|
|
|
description += ': ' + error;
|
|
|
|
equals(error == null, true, description);
|
2011-07-28 10:55:14 -04:00
|
|
|
});
|
|
|
|
|
2011-07-13 12:19:00 -04:00
|
|
|
test('hitting path ends', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path([0, 0], [50, 50], [100, 0]);
|
|
|
|
path.closed = true;
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return !paper.project.hitTest(path.firstSegment.point, {
|
|
|
|
ends: true
|
|
|
|
});
|
|
|
|
}, true, 'No hitresult should be returned, because the path is closed.');
|
|
|
|
|
|
|
|
path.closed = false;
|
|
|
|
|
|
|
|
var hitResult = paper.project.hitTest(path.lastSegment.point, {
|
|
|
|
ends: true
|
|
|
|
});
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return !!hitResult;
|
|
|
|
}, true, 'A HitResult should be returned (1)');
|
|
|
|
|
|
|
|
if (hitResult) {
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.type;
|
|
|
|
}, 'segment');
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.segment == path.lastSegment;
|
|
|
|
}, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return !paper.project.hitTest(path.segments[1].point, {
|
|
|
|
ends: true
|
|
|
|
});
|
|
|
|
}, true, 'No HitResult should be returned, since the second segment is not an end');
|
2011-07-13 12:19:00 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('When a path is closed, the end of a path cannot be hit.', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path([0, 0], [50, 50], [100, 0]);
|
|
|
|
path.closed = true;
|
|
|
|
|
|
|
|
var hitResult = paper.project.hitTest([0, 0], {
|
|
|
|
ends: true
|
|
|
|
});
|
|
|
|
equals(function() {
|
|
|
|
return !hitResult;
|
|
|
|
}, true, 'When a path is closed, the end of a path cannot be hit.');
|
2011-07-13 12:19:00 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('hitting path bounding box', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path.Circle({
|
|
|
|
center: [100, 100],
|
|
|
|
radius: 50,
|
|
|
|
fillColor: 'red'
|
|
|
|
});
|
|
|
|
|
|
|
|
var hitResult = paper.project.hitTest(path.bounds.topLeft, {
|
|
|
|
bounds: true
|
|
|
|
});
|
|
|
|
|
|
|
|
equals(!!hitResult, true, 'A HitResult should be returned');
|
|
|
|
|
|
|
|
if (hitResult) {
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.type;
|
|
|
|
}, 'bounds');
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.name;
|
|
|
|
}, 'top-left');
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.point;
|
|
|
|
}, path.bounds.topLeft);
|
|
|
|
}
|
2013-06-23 22:48:46 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('hitting raster bounding box', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path.Circle({
|
|
|
|
center: [100, 100],
|
|
|
|
radius: 50,
|
|
|
|
fillColor: 'red'
|
|
|
|
});
|
|
|
|
var raster = path.rasterize(72);
|
|
|
|
path.remove();
|
|
|
|
|
|
|
|
var hitResult = paper.project.hitTest(raster.bounds.topLeft, {
|
|
|
|
bounds: true
|
|
|
|
});
|
|
|
|
|
|
|
|
equals(!!hitResult, true, 'A HitResult should be returned');
|
|
|
|
|
|
|
|
if (hitResult) {
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.type;
|
|
|
|
}, 'bounds');
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.name;
|
|
|
|
}, 'top-left');
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return hitResult.point;
|
|
|
|
}, path.bounds.topLeft);
|
|
|
|
}
|
2011-07-14 08:24:32 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('hitting guides', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path.Circle({
|
|
|
|
center: [100, 100],
|
|
|
|
radius: 50,
|
|
|
|
fillColor: 'red'
|
|
|
|
});
|
|
|
|
var copy = path.clone();
|
2011-07-14 08:24:32 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
var result = paper.project.hitTest(path.position);
|
2011-07-14 08:24:32 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
equals(result && result.item, copy,
|
|
|
|
'The copy should be returned, because it is on top.');
|
2014-04-06 07:48:03 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
path.guide = true;
|
2014-04-06 07:48:03 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
var result = paper.project.hitTest(path.position, {
|
|
|
|
guides: true,
|
|
|
|
fill: true
|
|
|
|
});
|
2014-04-06 07:48:03 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
equals(result && result.item, path,
|
|
|
|
'The path should be returned, because it is a guide.');
|
2011-07-14 08:24:32 -04:00
|
|
|
});
|
|
|
|
|
2012-04-25 13:05:19 -04:00
|
|
|
test('hitting raster items', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
// Create a path, rasterize it and then remove the path:
|
|
|
|
var path = new Path.Rectangle(new Point(), new Size(320, 240));
|
|
|
|
path.fillColor = 'red';
|
|
|
|
var raster = path.rasterize(72);
|
2014-04-06 07:48:03 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
var hitResult = paper.project.hitTest(new Point(160, 120));
|
2012-04-25 13:05:19 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
equals(function() {
|
|
|
|
return hitResult && hitResult.item == raster;
|
|
|
|
}, true, 'Hit raster item before moving');
|
2014-04-06 07:48:03 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
// Move the raster:
|
|
|
|
raster.translate(100, 100);
|
2014-04-06 07:48:03 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
var hitResult = paper.project.hitTest(new Point(160, 120));
|
2012-04-25 13:05:19 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
equals(function() {
|
|
|
|
return hitResult && hitResult.item == raster;
|
|
|
|
}, true, 'Hit raster item after moving');
|
2012-04-25 13:05:19 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
test('hitting path with a text item in the project', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path.Rectangle(new Point(50, 50), new Point(100, 100));
|
|
|
|
path.fillColor = 'blue';
|
2014-04-06 07:48:03 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
var hitResult = paper.project.hitTest(new Point(75, 75));
|
2012-04-25 13:05:19 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
equals(function() {
|
|
|
|
return hitResult && hitResult.item == path;
|
|
|
|
}, true, 'Hit path item before adding text item');
|
2012-04-25 13:05:19 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
var text1 = new PointText(30, 30);
|
|
|
|
text1.content = "Text 1";
|
2012-04-25 13:05:19 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
var hitResult = paper.project.hitTest(new Point(75, 75));
|
2014-04-06 07:48:03 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
equals(function() {
|
|
|
|
return !!hitResult;
|
|
|
|
}, true, 'A hitresult should be returned.');
|
2012-04-25 13:05:19 -04:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
equals(function() {
|
|
|
|
return !!hitResult && hitResult.item == path;
|
|
|
|
}, true, 'We should have hit the path');
|
2014-04-06 07:48:03 -04:00
|
|
|
|
2012-04-25 13:05:19 -04:00
|
|
|
});
|
|
|
|
|
2015-12-27 19:05:54 -05:00
|
|
|
test('hit-testing of items that come after a transformed group.', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
paper.project.currentStyle.fillColor = 'black';
|
|
|
|
var point1 = new Point(100, 100);
|
|
|
|
var point2 = new Point(140, 100);
|
|
|
|
var delta = new Point(250, 0);
|
|
|
|
|
|
|
|
var path1 = new Path.Circle(point1, 20);
|
|
|
|
path1.name = 'path1';
|
|
|
|
var path2 = new Path.Circle(point2, 20);
|
|
|
|
path2.name = 'path2';
|
|
|
|
|
|
|
|
var group = new Group(path2);
|
|
|
|
group.name = 'group';
|
|
|
|
|
|
|
|
var hitResult = paper.project.hitTest(point1);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult && hitResult.item;
|
|
|
|
}, path1, 'Hit testing project for point1 should give us path1.');
|
|
|
|
|
|
|
|
hitResult = paper.project.hitTest(point2);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult && hitResult.item;
|
|
|
|
}, path2, 'Hit testing project for point2 should give us path2.');
|
|
|
|
|
|
|
|
hitResult = paper.project.hitTest(point2);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult && hitResult.item;
|
|
|
|
}, path2, 'Hit testing project for point2 should give us path2.');
|
|
|
|
|
2016-01-31 10:52:51 -05:00
|
|
|
group.translate(delta);
|
2014-08-16 13:24:54 -04:00
|
|
|
|
|
|
|
hitResult = paper.project.hitTest(point1);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult && hitResult.item;
|
2014-10-20 17:33:28 -04:00
|
|
|
}, path1, 'After translating group, hit-testing project for point1 should give us path1.');
|
2014-08-16 13:24:54 -04:00
|
|
|
|
|
|
|
hitResult = paper.project.hitTest(point2.add(delta));
|
|
|
|
equals(function() {
|
|
|
|
return hitResult && hitResult.item;
|
2014-10-20 17:33:28 -04:00
|
|
|
}, path2, 'After translating group, hit-testing project for point2 + delta should give us path2.');
|
2014-08-16 13:24:54 -04:00
|
|
|
|
|
|
|
hitResult = path1.hitTest(point1);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult && hitResult.item;
|
2014-10-20 17:33:28 -04:00
|
|
|
}, path1, 'After translating group, hit-testing path1 for point1 should give us path1.');
|
2014-08-16 13:24:54 -04:00
|
|
|
|
|
|
|
group.moveBelow(path1);
|
|
|
|
|
|
|
|
hitResult = paper.project.hitTest(point1);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult && hitResult.item;
|
2014-10-20 17:33:28 -04:00
|
|
|
}, path1, 'After moving group before path1, hit-testing project for point1 should give us path1.');
|
2014-08-16 13:24:54 -04:00
|
|
|
|
|
|
|
hitResult = paper.project.hitTest(point2.add(delta));
|
|
|
|
equals(function() {
|
|
|
|
return hitResult && hitResult.item;
|
2014-10-20 17:33:28 -04:00
|
|
|
}, path2, 'After moving group before path1, hit-testing project for point2 + delta should give us path2.');
|
2014-08-16 13:24:54 -04:00
|
|
|
|
|
|
|
hitResult = path1.hitTest(point1);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult && hitResult.item;
|
2014-10-20 17:33:28 -04:00
|
|
|
}, path1, 'After moving group before path1, hit-testing path1 for point1 should give us path1.');
|
2012-11-23 13:47:43 -05:00
|
|
|
});
|
2012-04-25 13:05:19 -04:00
|
|
|
|
2015-12-27 19:05:54 -05:00
|
|
|
test('hit-testing of placed symbols.', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var point = new Point(100, 100);
|
2012-11-23 14:29:36 -05:00
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path.Circle([0, 0], 20);
|
|
|
|
path.fillColor = 'black';
|
2016-01-31 10:52:51 -05:00
|
|
|
var definition = new SymbolDefinition(path);
|
|
|
|
var placedItem = definition.place(point);
|
2014-08-16 13:24:54 -04:00
|
|
|
var hitResult = placedItem.hitTest(point);
|
|
|
|
equals(function() {
|
|
|
|
return hitResult && hitResult.item == placedItem;
|
|
|
|
}, true, 'hitResult.item should be placedItem');
|
2012-11-23 14:29:36 -05:00
|
|
|
|
|
|
|
});
|
2013-06-13 14:07:43 -04:00
|
|
|
|
2015-12-27 19:05:54 -05:00
|
|
|
test('hit-testing the corner of a rectangle with miter stroke.', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var rect = new Path.Rectangle({
|
|
|
|
rectangle: [100, 100, 300, 200],
|
|
|
|
fillColor: '#f00',
|
|
|
|
strokeColor: 'blue',
|
|
|
|
strokeJoin: 'miter',
|
|
|
|
strokeWidth: 20
|
|
|
|
});
|
|
|
|
equals(function() {
|
|
|
|
return rect.hitTest(rect.strokeBounds.topRight) != null;
|
|
|
|
}, true);
|
2013-06-13 14:07:43 -04:00
|
|
|
});
|
|
|
|
|
2015-12-27 19:05:54 -05:00
|
|
|
test('hit-testing invisible items.', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var point = new Point(0, 0);
|
|
|
|
var circle1 = new Path.Circle({
|
|
|
|
center: point.subtract([25, 0]),
|
|
|
|
radius: 50,
|
|
|
|
fillColor: 'red'
|
|
|
|
});
|
|
|
|
var circle2 = new Path.Circle({
|
|
|
|
center: point.add([25, 0]),
|
|
|
|
radius: 50,
|
|
|
|
fillColor: 'blue'
|
|
|
|
});
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return paper.project.hitTest(point).item === circle2;
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
circle2.visible = false;
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return paper.project.hitTest(point).item === circle1;
|
|
|
|
}, true);
|
2013-06-23 20:52:31 -04:00
|
|
|
});
|
|
|
|
|
2015-12-27 19:05:54 -05:00
|
|
|
test('hit-testing guides.', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var point = new Point(0, 0);
|
|
|
|
var circle1 = new Path.Circle({
|
|
|
|
center: point.subtract([25, 0]),
|
|
|
|
radius: 50,
|
|
|
|
fillColor: 'red'
|
|
|
|
});
|
|
|
|
var circle2 = new Path.Circle({
|
|
|
|
center: point.add([25, 0]),
|
|
|
|
radius: 50,
|
|
|
|
fillColor: 'blue'
|
|
|
|
});
|
|
|
|
|
|
|
|
var strokePoint = circle2.bounds.leftCenter;
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return paper.project.hitTest(strokePoint).item === circle2;
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
circle2.guide = true;
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
return paper.project.hitTest(strokePoint).item === circle1;
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTest(strokePoint, {
|
|
|
|
guides: true,
|
|
|
|
fill: true
|
|
|
|
});
|
|
|
|
return result && result.item === circle2;
|
|
|
|
}, true);
|
2013-06-23 21:18:49 -04:00
|
|
|
});
|
|
|
|
|
2016-02-16 14:52:07 -05:00
|
|
|
test('hit-testing fills with tolerance', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var path = new Path.Rectangle({
|
|
|
|
from: [50, 50],
|
|
|
|
to: [200, 200],
|
|
|
|
fillColor: 'red'
|
|
|
|
});
|
|
|
|
|
2016-02-16 14:52:07 -05:00
|
|
|
var tolerance = 10;
|
|
|
|
var point = path.bounds.bottomRight.add(tolerance / Math.sqrt(2));
|
|
|
|
|
2014-08-16 13:24:54 -04:00
|
|
|
equals(function() {
|
2016-02-16 14:52:07 -05:00
|
|
|
var result = paper.project.hitTest(point, {
|
2014-08-16 13:24:54 -04:00
|
|
|
tolerance: tolerance,
|
|
|
|
fill: true
|
|
|
|
});
|
|
|
|
return result && result.item === path;
|
|
|
|
}, true);
|
2016-02-16 14:52:07 -05:00
|
|
|
|
|
|
|
var point = new Point(20, 20);
|
|
|
|
var size = new Size(40, 40);
|
|
|
|
var hitPoint = new Point(10, 10);
|
|
|
|
var options = {
|
|
|
|
fill: true,
|
|
|
|
tolerance: 20
|
|
|
|
};
|
|
|
|
|
|
|
|
var shapeRect = new Shape.Rectangle(point, size);
|
|
|
|
shapeRect.fillColor = 'black';
|
|
|
|
|
|
|
|
var pathRect = new Path.Rectangle(point, size);
|
|
|
|
pathRect.fillColor = 'black';
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
var hit = shapeRect.hitTest(hitPoint, options);
|
|
|
|
return hit && hit.type === 'fill';
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
var hit = pathRect.hitTest(hitPoint, options);
|
|
|
|
return hit && hit.type === 'fill';
|
|
|
|
}, true);
|
2013-12-08 06:26:11 -05:00
|
|
|
});
|
|
|
|
|
2015-12-27 19:05:54 -05:00
|
|
|
test('hit-testing compound-paths', function() {
|
2014-08-16 13:24:54 -04:00
|
|
|
var center = new Point(100, 100);
|
|
|
|
var path1 = new Path.Circle({
|
|
|
|
center: center,
|
|
|
|
radius: 100
|
|
|
|
});
|
|
|
|
var path2 = new Path.Circle({
|
|
|
|
center: center,
|
|
|
|
radius: 50
|
|
|
|
});
|
|
|
|
var compoundPath = new CompoundPath({
|
|
|
|
children: [path1, path2],
|
2016-07-21 09:21:45 -04:00
|
|
|
fillColor: 'blue',
|
|
|
|
fillRule: 'evenodd'
|
2014-08-16 13:24:54 -04:00
|
|
|
});
|
2015-12-28 11:54:07 -05:00
|
|
|
// When hit-testing a side, we should get a result on the torus
|
2014-08-16 13:24:54 -04:00
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTest(center.add([75, 0]), {
|
|
|
|
fill: true
|
|
|
|
});
|
|
|
|
return result && result.item === compoundPath;
|
|
|
|
}, true);
|
|
|
|
// When hit-testing the center, we should not get a result on the torus
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTest(center, {
|
|
|
|
fill: true
|
|
|
|
});
|
2016-02-09 11:02:03 -05:00
|
|
|
return result === null;
|
2014-08-16 13:24:54 -04:00
|
|
|
}, true);
|
|
|
|
// When asking specifically for paths, she should get the top-most path in
|
|
|
|
// the center (the one that cuts out the hole)
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTest(center, {
|
|
|
|
class: Path,
|
|
|
|
fill: true
|
|
|
|
});
|
|
|
|
return result && result.item === path2;
|
|
|
|
}, true);
|
2014-04-10 16:27:29 -04:00
|
|
|
});
|
|
|
|
|
2016-02-09 11:02:03 -05:00
|
|
|
test('hit-testing clipped items', function() {
|
|
|
|
var rect = new Path.Rectangle({
|
|
|
|
point: [50, 150],
|
|
|
|
size: [100, 50],
|
|
|
|
fillColor: 'red'
|
|
|
|
});
|
|
|
|
var circle = new Path.Circle({
|
|
|
|
center: [100, 200],
|
|
|
|
radius: 20,
|
|
|
|
fillColor: 'green'
|
|
|
|
});
|
|
|
|
var group = new Group({
|
|
|
|
children: [rect, circle]
|
|
|
|
});
|
|
|
|
group.clipped = true;
|
|
|
|
|
|
|
|
var point1 = new Point(100, 190);
|
|
|
|
var point2 = new Point(100, 210);
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTest(point1);
|
|
|
|
return result && result.item === circle;
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTest(point2);
|
|
|
|
return result === null;
|
|
|
|
}, true);
|
|
|
|
});
|
|
|
|
|
2016-02-14 06:39:35 -05:00
|
|
|
test('hit-testing with a match function', function() {
|
|
|
|
var point = new Point(100, 100),
|
|
|
|
red = new Color('red'),
|
|
|
|
green = new Color('green'),
|
|
|
|
blue = new Color('blue');
|
|
|
|
var c1 = new Path.Circle({
|
|
|
|
center: point,
|
|
|
|
radius: 50,
|
|
|
|
fillColor: red
|
|
|
|
});
|
|
|
|
var c2 = new Path.Circle({
|
|
|
|
center: point,
|
|
|
|
radius: 50,
|
|
|
|
fillColor: green
|
|
|
|
});
|
|
|
|
var c3 = new Path.Circle({
|
|
|
|
center: point,
|
|
|
|
radius: 50,
|
|
|
|
fillColor: blue
|
|
|
|
});
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTest(point, {
|
|
|
|
fill: true,
|
|
|
|
match: function(res) {
|
|
|
|
return res.item.fillColor == red;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return result && result.item === c1;
|
|
|
|
}, true);
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTest(point, {
|
|
|
|
fill: true,
|
|
|
|
match: function(res) {
|
|
|
|
return res.item.fillColor == green;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return result && result.item === c2;
|
|
|
|
}, true);
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTest(point, {
|
|
|
|
fill: true,
|
|
|
|
match: function(res) {
|
|
|
|
return res.item.fillColor == blue;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return result && result.item === c3;
|
|
|
|
}, true);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('hit-testing for all items', function() {
|
|
|
|
var c1 = new Path.Circle({
|
|
|
|
center: [100, 100],
|
|
|
|
radius: 40,
|
|
|
|
fillColor: 'red'
|
|
|
|
});
|
|
|
|
var c2 = new Path.Circle({
|
|
|
|
center: [120, 120],
|
|
|
|
radius: 40,
|
|
|
|
fillColor: 'green'
|
|
|
|
});
|
|
|
|
var c3 = new Path.Circle({
|
|
|
|
center: [140, 140],
|
|
|
|
radius: 40,
|
|
|
|
fillColor: 'blue'
|
|
|
|
});
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTestAll([60, 60]);
|
|
|
|
return result.length === 0;
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTestAll([80, 80]);
|
|
|
|
return result.length === 1 && result[0].item === c1;
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTestAll([100, 100]);
|
|
|
|
return result.length === 2 && result[0].item === c2
|
|
|
|
&& result[1].item === c1;
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTestAll([120, 120]);
|
|
|
|
return result.length === 3 && result[0].item === c3
|
|
|
|
&& result[1].item === c2
|
|
|
|
&& result[2].item === c1;
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTestAll([140, 140]);
|
|
|
|
return result.length === 2 && result[0].item === c3
|
|
|
|
&& result[1].item === c2;
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTestAll([160, 160]);
|
|
|
|
return result.length === 1 && result[0].item === c3;
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
equals(function() {
|
|
|
|
var result = paper.project.hitTestAll([180, 180]);
|
|
|
|
return result.length === 0;
|
|
|
|
}, true);
|
|
|
|
});
|
2016-02-16 14:52:07 -05:00
|
|
|
|
2014-04-06 07:48:03 -04:00
|
|
|
// TODO: project.hitTest(point, {type: AnItemType});
|
2014-04-10 16:27:29 -04:00
|
|
|
|