Implement options.curvesoption for hit-testing curves regardless of stroke settings.

This commit is contained in:
Jürg Lehni 2014-04-11 14:57:58 +02:00
parent d12607dd44
commit a931a2530c
4 changed files with 39 additions and 27 deletions

View file

@ -39,8 +39,8 @@ var HitResult = Base.extend(/** @lends HitResult# */{
*
* @name HitResult#type
* @property
* @type String('segment', 'handle-in', 'handle-out', 'stroke', 'fill',
* 'bounds', 'center', 'pixel')
* @type String('segment', 'handle-in', 'handle-out', 'curve', 'stroke',
* 'fill', 'bounds', 'center', 'pixel')
*/
/**
@ -62,8 +62,8 @@ var HitResult = Base.extend(/** @lends HitResult# */{
*/
/**
* If the HitResult has a type of 'stroke', this property gives more
* information about the exact position that was hit on the path.
* If the HitResult has a type of 'curve' or 'stroke', this property gives
* more information about the exact position that was hit on the path.
*
* @name HitResult#location
* @property

View file

@ -296,6 +296,9 @@ var Item = Base.extend(Callback, /** @lends Item# */{
* });
*/
set: function(props) {
// Filter out `insert` since that only makes sense at creation time and
// is handled separately in the constructor.Also avoids overriding
// Path#insert().
if (props)
this._set(props, { insert: true });
return this;
@ -1658,10 +1661,12 @@ var Item = Base.extend(Callback, /** @lends Item# */{
* {@code Group, Layer, Path, CompoundPath, Shape, Raster, PlacedSymbol,
* PointText}, etc.
* <b>options.fill:</b> {@code Boolean} hit test the fill of items.
* <b>options.stroke:</b> {@code Boolean} hit test the curves of path
* items, taking into account stroke width.
* <b>options.segment:</b> {@code Boolean} hit test for
* <b>options.stroke:</b> {@code Boolean} hit test the stroke of path
* items, taking into account the setting of stroke color and width.
* <b>options.segments:</b> {@code Boolean} hit test for
* {@link Segment#point} of {@link Path} items.
* <b>options.curves:</b> {@code Boolean} hit test the curves of path
* items, without taking the stroke color or width into account.
* <b>options.handles:</b> {@code Boolean} hit test for the handles
* ({@link Segment#handleIn} / {@link Segment#handleOut}) of path segments.
* <b>options.ends:</b> {@code Boolean} only hit test for the first or

View file

@ -1756,13 +1756,17 @@ var Path = PathItem.extend(/** @lends Path# */{
strokePadding = tolerancePadding,
join, cap, miterLimit,
area, loc, res,
hasStroke = options.stroke && style.hasStroke(),
hasFill = options.fill && style.hasFill(),
radius = hasStroke ? style.getStrokeWidth() / 2
// Set radius to 0 so when we're hit-testing, the tolerance
// is used for fill too, through stroke functionality.
: hasFill ? 0 : null;
if (radius != null) {
hitStroke = options.stroke && style.hasStroke(),
hitFill = options.fill && style.hasFill(),
hitCurves = options.curves,
radius = hitStroke
? style.getStrokeWidth() / 2
// Set radius to 0 when we're hit-testing fills with
// tolerance, to handle tolerance through stroke hit-test
// functionality. Also use 0 when hit-testing curves.
: hitFill && options.tolerance > 0 || hitCurves
? 0 : null;
if (radius !== null) {
if (radius > 0) {
join = style.getStrokeJoin();
cap = style.getStrokeCap();
@ -1858,7 +1862,7 @@ var Path = PathItem.extend(/** @lends Path# */{
return res;
}
// If we're querying for stroke, perform that before fill
if (radius != null) {
if (radius !== null) {
loc = this.getNearestLocation(point);
// Note that paths need at least two segments to have an actual
// stroke. But we still check for segments with the radius fallback
@ -1891,16 +1895,17 @@ var Path = PathItem.extend(/** @lends Path# */{
// Don't process loc yet, as we also need to query for stroke after fill
// in some cases. Simply skip fill query if we already have a matching
// stroke. If we have a loc and no stroke then it's a result for fill.
return !loc && hasFill && this._contains(point) || loc && !hasStroke
? new HitResult('fill', this)
: loc
? new HitResult('stroke', this, {
location: loc,
// It's fine performance wise to call getPoint() again
// since it was already called before.
point: loc.getPoint()
})
: null;
return !loc && hitFill && this._contains(point)
|| loc && !hitStroke && !hitCurves
? new HitResult('fill', this)
: loc
? new HitResult(hitStroke ? 'stroke' : 'curve', this, {
location: loc,
// It's fine performance wise to call getPoint()
// again since it was already called before.
point: loc.getPoint()
})
: null;
}
// TODO: intersects(item)

View file

@ -272,10 +272,12 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{
* {@code Group, Layer, Path, CompoundPath, Shape, Raster, PlacedSymbol,
* PointText}, etc.
* <b>options.fill:</b> {@code Boolean} hit test the fill of items.
* <b>options.stroke:</b> {@code Boolean} hit test the curves of path
* items, taking into account stroke width.
* <b>options.stroke:</b> {@code Boolean} hit test the stroke of path
* items, taking into account the setting of stroke color and width.
* <b>options.segments:</b> {@code Boolean} hit test for
* {@link Segment#point} of {@link Path} items.
* <b>options.curves:</b> {@code Boolean} hit test the curves of path
* items, without taking the stroke color or width into account.
* <b>options.handles:</b> {@code Boolean} hit test for the handles
* ({@link Segment#handleIn} / {@link Segment#handleOut}) of path segments.
* <b>options.ends:</b> {@code Boolean} only hit test for the first or