scratch-paint/src/helper/snapping.js

60 lines
2 KiB
JavaScript
Raw Normal View History

2017-10-18 14:08:03 -04:00
import paper from '@scratch/paper';
2017-10-24 13:21:57 -04:00
import {getItems} from './selection';
2017-10-18 14:08:03 -04:00
/**
* @param {paper.Point} point1 point 1
* @param {paper.Point} point2 point 2
* @param {number} tolerance Distance allowed between points that are "touching"
* @return {boolean} true if points are within the tolerance distance.
*/
const touching = function (point1, point2, tolerance) {
return point1.getDistance(point2, true) < Math.pow(tolerance / paper.view.zoom, 2);
};
/**
* @param {!paper.Point} point Point to check line endpoint hits against
* @param {!number} tolerance Distance within which it counts as a hit
* @param {?paper.Path} excludePath Path to exclude from hit test, if any. For instance, you
* are drawing a line and don't want it to snap to its own start point.
* @return {object} data about the end point of an unclosed path, if any such point is within the
* tolerance distance of the given point, or null if none exists.
*/
const endPointHit = function (point, tolerance, excludePath) {
2017-10-24 13:21:57 -04:00
const lines = getItems({
2017-10-18 14:08:03 -04:00
class: paper.Path
});
// Prefer more recent lines
for (let i = lines.length - 1; i >= 0; i--) {
if (lines[i].closed) {
continue;
}
if (!(lines[i].parent instanceof paper.Layer)) {
// Don't connect to lines inside of groups
continue;
}
if (excludePath && lines[i] === excludePath) {
continue;
}
if (lines[i].firstSegment && touching(lines[i].firstSegment.point, point, tolerance)) {
return {
path: lines[i],
segment: lines[i].firstSegment,
isFirst: true
};
}
if (lines[i].lastSegment && touching(lines[i].lastSegment.point, point, tolerance)) {
return {
path: lines[i],
segment: lines[i].lastSegment,
isFirst: false
};
}
}
return null;
};
export {
endPointHit,
touching
};