| 434 | } |
| 435 | |
| 436 | function snapMoveToElements(elementId, x, y, opts) { |
| 437 | const suppressSnap = !!(opts && opts.suppressSnap); |
| 438 | if (suppressSnap) return { x, y, gx: null, gy: null }; |
| 439 | |
| 440 | const threshold = 4; |
| 441 | const el = elements.find((e) => e.id === elementId); |
| 442 | if (!el) return { x, y, gx: null, gy: null }; |
| 443 | |
| 444 | const ptsX = [x, x + el.w / 2, x + el.w]; |
| 445 | const ptsY = [y, y + el.h / 2, y + el.h]; |
| 446 | |
| 447 | let bestDx = null; |
| 448 | let bestGx = null; |
| 449 | let bestDy = null; |
| 450 | let bestGy = null; |
| 451 | |
| 452 | for (const other of elements) { |
| 453 | if (other.hidden || other.id === elementId) continue; |
| 454 | const oxs = [other.x, other.x + other.w / 2, other.x + other.w]; |
| 455 | const oys = [other.y, other.y + other.h / 2, other.y + other.h]; |
| 456 | |
| 457 | for (let i = 0; i < ptsX.length; i++) { |
| 458 | for (let j = 0; j < oxs.length; j++) { |
| 459 | const dx = oxs[j] - ptsX[i]; |
| 460 | const adx = Math.abs(dx); |
| 461 | if (adx <= threshold && (bestDx == null || adx < Math.abs(bestDx))) { |
| 462 | bestDx = dx; |
| 463 | bestGx = oxs[j]; |
| 464 | } |
| 465 | } |
| 466 | } |
| 467 | for (let i = 0; i < ptsY.length; i++) { |
| 468 | for (let j = 0; j < oys.length; j++) { |
| 469 | const dy = oys[j] - ptsY[i]; |
| 470 | const ady = Math.abs(dy); |
| 471 | if (ady <= threshold && (bestDy == null || ady < Math.abs(bestDy))) { |
| 472 | bestDy = dy; |
| 473 | bestGy = oys[j]; |
| 474 | } |
| 475 | } |
| 476 | } |
| 477 | } |
| 478 | |
| 479 | for (const g of guides) { |
| 480 | if (!g) continue; |
| 481 | if (g.orient === "v") { |
| 482 | const pos = g.pos; |
| 483 | for (let i = 0; i < ptsX.length; i++) { |
| 484 | const dx = pos - ptsX[i]; |
| 485 | const adx = Math.abs(dx); |
| 486 | if (adx <= threshold && (bestDx == null || adx < Math.abs(bestDx))) { |
| 487 | bestDx = dx; |
| 488 | bestGx = pos; |
| 489 | } |
| 490 | } |
| 491 | } else { |
| 492 | const pos = g.pos; |
| 493 | for (let i = 0; i < ptsY.length; i++) { |