Last active
June 8, 2022 01:59
-
-
Save steveruizok/99c7d3f99d94bb9aed10a9b4a70366cb to your computer and use it in GitHub Desktop.
A second iteration on finding snap points. Includes lines for rendering snap points.
This file contains hidden or 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
interface BBox { | |
minX: number | |
midX: number | |
maxX: number | |
minY: number | |
midY: number | |
maxY: number | |
width: number | |
height: number | |
} | |
function findSnapPoints( | |
bounds: BBox, | |
others: BBox[], | |
isCareful: boolean | |
) { | |
const A = { ...bounds } // We'll mutate this | |
const offset = [0, 0] | |
const snapLines: TLSnapLine[] = [] | |
// 1. | |
// Find the snap points for the x and y axes | |
const fxs = isCareful ? [A.midX, A.minX, A.maxX] : [A.midX] | |
const fys = isCareful ? [A.midY, A.minY, A.maxY] : [A.midY] | |
let xs = null as { B: BoundsWithCenter; i: number } | null | |
let ys = null as { B: BoundsWithCenter; i: number } | null | |
for (const B of others) { | |
if (!xs) { | |
const txs = isCareful ? [B.midX, B.minX, B.maxX] : [B.midX] | |
fxs.forEach((f, i) => | |
txs.forEach((t) => { | |
if (xs) return | |
if (Math.abs(t - f) < SNAP_DISTANCE) { | |
xs = { B, i } | |
offset[0] = [ | |
// How far to offset the delta on the x axis in | |
// order to "snap" the selection to the right place | |
A.midX - t, | |
A.midX - (t + A.width / 2), | |
A.midX - (t - A.width / 2), | |
][i] | |
// Also apply the offset to bounds A, so that our snap lines are correct | |
A.minX -= offset[0] | |
A.midX -= offset[0] | |
A.maxX -= offset[0] | |
} | |
}) | |
) | |
} | |
if (!ys) { | |
const tys = isCareful ? [B.midY, B.minY, B.maxY] : [B.midY] | |
fys.forEach((f, i) => | |
tys.forEach((t) => { | |
if (ys) return | |
if (Math.abs(t - f) < SNAP_DISTANCE) { | |
ys = { B, i } | |
offset[1] = [ | |
// | |
A.midY - t, | |
A.midY - (t + A.height / 2), | |
A.midY - (t - A.height / 2), | |
][i] | |
A.minY -= offset[1] | |
A.midY -= offset[1] | |
A.maxY -= offset[1] | |
} | |
}) | |
) | |
} | |
if (xs && ys) break | |
} | |
// 2. | |
// Calculcate snap lines based on adjusted bounds A. This has | |
// to happen after we've adjusted both dimensions x and y of | |
// the bounds A! | |
if (xs) { | |
const { i, B } = xs | |
const x = [A.midX, A.minX, A.maxX][i % 3] | |
// If A is snapped at its center, show include only the midY; | |
// otherwise, include both its minY and maxY. | |
snapLines.push({ | |
points: | |
i === 0 | |
? [ | |
[x, A.midY], | |
[x, B.minY], | |
[x, B.maxY], | |
] | |
: [ | |
[x, A.minY], | |
[x, A.maxY], | |
[x, B.minY], | |
[x, B.maxY], | |
], | |
}) | |
} | |
if (ys) { | |
const { i, B } = ys | |
const y = [A.midY, A.minY, A.maxY][i % 3] | |
snapLines.push({ | |
points: | |
i === 0 | |
? [ | |
[A.midX, y], | |
[B.minX, y], | |
[B.maxX, y], | |
] | |
: [ | |
[A.minX, y], | |
[A.maxX, y], | |
[B.minX, y], | |
[B.maxX, y], | |
], | |
}) | |
} | |
return { offset, snapLines } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment