-
Notifications
You must be signed in to change notification settings - Fork 715
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new(drag): Add restrictToPath as a Drag parameter (#1379)
* Add restrictToPath as a Drag parameter Allow the user to pass an SVGGeometryElement to restrict the drag area to following the path of an SVG. Useful for constrining the drag of an object to a curved line. * Performance Improvements Calculate and cache sample points along restrictToPath. This turns out to be fairly tricky as the path is a ref and we need to use the getTotalLength function as an estimate to when the path has changed. Remove getParentSvg. Turns out we can just use the DOMMatrix from the path element itself, saving the need to traverse the DOM. Fix bug with summing points for offset, rather than finding the difference. * Update packages/visx-drag/src/useDrag.ts Complete sentence for docs Co-authored-by: Chris Williams <williaster@users.noreply.github.com> Co-authored-by: Chris Williams <williaster@users.noreply.github.com>
- Loading branch information
1 parent
499e086
commit 3ac3f5e
Showing
9 changed files
with
124 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/** Gets closest point from list of points */ | ||
export default function getClosestPoint(point: { x: number; y: number }, samples: DOMPoint[]) { | ||
let closestPoint = point; | ||
let minDistance = Infinity; | ||
for (const sample of samples) { | ||
const distance = Math.sqrt((sample.x - point.x) ** 2 + (sample.y - point.y) ** 2); | ||
if (distance < minDistance) { | ||
minDistance = distance; | ||
closestPoint = { x: sample.x, y: sample.y }; | ||
} | ||
} | ||
return closestPoint; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { UseDragOptions } from '../useDrag'; | ||
import clampNumber from './clampNumber'; | ||
import getClosestPoint from './getClosestPoint'; | ||
|
||
/** Restrict a point to an area, or samples along a path. */ | ||
export default function restrictPoint( | ||
point: { x: number; y: number }, | ||
samples: DOMPoint[], | ||
restrict: UseDragOptions['restrict'] = {}, | ||
) { | ||
if (samples.length > 0) { | ||
return getClosestPoint(point, samples); | ||
} | ||
return { | ||
x: clampNumber(point.x, restrict.xMin ?? -Infinity, restrict.xMax ?? Infinity), | ||
y: clampNumber(point.y, restrict.yMin ?? -Infinity, restrict.yMax ?? Infinity), | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { useMemo } from 'react'; | ||
|
||
function getSamples(restrictToPath: SVGGeometryElement, transform?: DOMMatrix, precision = 1) { | ||
if (!restrictToPath) return []; | ||
const samples = []; | ||
const pathLength = restrictToPath.getTotalLength(); | ||
for (let sampleLength = 0; sampleLength <= pathLength; sampleLength += precision) { | ||
const sample = restrictToPath.getPointAtLength(sampleLength); | ||
const transformedSample = sample.matrixTransform(transform); | ||
samples.push(transformedSample); | ||
} | ||
return samples; | ||
} | ||
|
||
/** Return samples along a path, relative to the parent SVG */ | ||
export default function useSamplesAlongPath(restrictToPath?: SVGGeometryElement | null) { | ||
const samples = useMemo(() => { | ||
if (!restrictToPath) return []; | ||
const transform = restrictToPath.getCTM() || new DOMMatrix(); | ||
return getSamples(restrictToPath, transform); | ||
// The path can transform without triggering a re-render, | ||
// so we need to update the samples whenever the length changes. | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [restrictToPath?.getTotalLength()]); | ||
return samples; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
export { default as Point } from './Point'; | ||
export { default as sumPoints } from './sumPoints'; | ||
export { default as subtractPoints } from './subtractPoints'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import Point from './Point'; | ||
|
||
export default function subtractPoints(point1: Point, point2: Point) { | ||
return new Point({ | ||
x: point1.x - point2.x, | ||
y: point1.y - point2.y, | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import Point from './Point'; | ||
|
||
export default function sumPoints(point1: Point, point2: Point) { | ||
return new Point({ | ||
x: point1.x + point2.x, | ||
y: point1.y + point2.y, | ||
}); | ||
} |