fix: resize anchored at start (no jump) — absolute target from RESIZE_START anchor

This commit is contained in:
Hermes Agent committed 2026-09-09 19:36:53 +02:00
1 parent 3c0ab7a67c
commit c8df3b8054
2 files changed
+37 -24

No files matched your search

+34 -14
View File
@@ -122,8 +122,15 @@ export default function () {
}
// Live-ресайз во время drag'а (кастомные ручки по периметру в UI).
// dir + dx/dy (смещение курсора в px). Для right/bottom — только resize.
// Для left/top — resize + сдвиг окна через reposition (иначе окно "уедет" вправо/вниз).
// Якорь: при RESIZE_START фиксируем старт-позицию (canvas) и старт-размер (px).
// При RESIZE_WINDOW_DRAG считаем АБСОЛЮТНУЮ цель от якоря (dx/dy — смещение курсора в px):
// w = startW + (right? +dx : left? -dx : 0)
// h = startH + (bottom? +dy : top? -dy : 0)
// x = startX + (left? dx/zoom : 0) — противоположный край остаётся на месте
// y = startY + (top? dy/zoom : 0)
// Это устраняет "скачки": позиция не зависит от текущего кадра, а размер и позиция
// переведены в одни единицы (px для размера, canvas/zoom для позиции).
let resizeAnchor: { x: number; y: number; w: number; h: number; dir: string } | null = null
function getPos () {
try {
const p = (figma.ui as any).getPosition()
@@ -132,24 +139,37 @@ export default function () {
return { x: 0, y: 0 }
}
}
on('RESIZE_WINDOW_DRAG', function (payload: { width: number; height: number; dx: number; dy: number; dir: string }) {
const { width, height, dx, dy, dir } = payload
const size = clampWindowSize({ width, height })
on('RESIZE_START', function (payload: { dir: string }) {
const p = getPos()
resizeAnchor = {
x: p.x,
y: p.y,
w: window.innerWidth,
h: window.innerHeight,
dir: payload.dir
}
})
on('RESIZE_WINDOW_DRAG', function (payload: { dx: number; dy: number; dir: string }) {
if (resizeAnchor == null) return
const { dx, dy, dir } = payload
const zoom = figma.viewport.zoom || 1
let w = resizeAnchor.w
let h = resizeAnchor.h
let nx = resizeAnchor.x
let ny = resizeAnchor.y
if (dir.indexOf('right') !== -1) w = resizeAnchor.w + dx
if (dir.indexOf('left') !== -1) { w = resizeAnchor.w - dx; nx = resizeAnchor.x + dx / zoom }
if (dir.indexOf('bottom') !== -1) h = resizeAnchor.h + dy
if (dir.indexOf('top') !== -1) { h = resizeAnchor.h - dy; ny = resizeAnchor.y + dy / zoom }
const size = clampWindowSize({ width: w, height: h })
figma.ui.resize(size.width, size.height)
lastSize = { width: size.width, height: size.height }
if (dir.indexOf('left') !== -1 || dir.indexOf('top') !== -1) {
const zoom = figma.viewport.zoom || 1
const p = getPos()
let nx = p.x
let ny = p.y
if (dir.indexOf('left') !== -1) nx = p.x - dx / zoom
if (dir.indexOf('top') !== -1) ny = p.y - dy / zoom
figma.ui.reposition(nx, ny)
}
figma.ui.reposition(nx, ny)
})
// Ресайз окна плагина (кастомные ручки по периметру -> RESIZE_WINDOW по pointerup)
on('RESIZE_WINDOW', function (windowSize: { width: number; height: number }) {
resizeAnchor = null
const { width, height } = clampWindowSize(windowSize)
lastSize = { width, height }
figma.ui.resize(width, height)
+3 -10
View File
@@ -74,6 +74,8 @@ function Plugin () {
resizeRef.current.startY = e.clientY
resizeRef.current.startW = window.innerWidth
resizeRef.current.startH = window.innerHeight
// Сообщаем main зафиксировать якорь (старт-позиция + старт-размер) ДО первого движения.
emit('RESIZE_START', { dir: dir })
}
function onPointerMove (e: PointerEvent) {
@@ -81,16 +83,7 @@ function Plugin () {
const dir = resizeRef.current.dir
const dx = e.clientX - resizeRef.current.startX
const dy = e.clientY - resizeRef.current.startY
let w = resizeRef.current.startW
let h = resizeRef.current.startH
if (dir.indexOf('right') !== -1) w = resizeRef.current.startW + dx
if (dir.indexOf('left') !== -1) w = resizeRef.current.startW - dx
if (dir.indexOf('bottom') !== -1) h = resizeRef.current.startH + dy
if (dir.indexOf('top') !== -1) h = resizeRef.current.startH - dy
w = Math.max(320, w)
h = Math.max(200, h)
setCurrentWindowSize({ width: w, height: h })
emit('RESIZE_WINDOW_DRAG', { width: w, height: h, dx: dx, dy: dy, dir: dir })
emit('RESIZE_WINDOW_DRAG', { dx: dx, dy: dy, dir: dir })
}
function onPointerUpResize () {