fix: resize anchored at start (no jump) — absolute target from RESIZE_START anchor
This commit is contained in:
1 parent
3c0ab7a67c
commit
c8df3b8054
2 files changed
+37
-24
No files matched your search
+34
-14
@@ -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
@@ -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 () {
|
||||
|
||||
Reference in new issue
Block a user