fix: keep docked window pinned to edge across zoom/pan via viewport poll
This commit is contained in:
1 parent
106f21b2c4
commit
9f9349efb6
1 file changed
+53
-15
+53
-15
@@ -4,24 +4,20 @@ export default function () {
|
||||
// Глобальный ярлык relaunch в правой панели Figma (команда runAI из manifest.json)
|
||||
figma.root.setRelaunchData({ runAI: '' })
|
||||
|
||||
// Последнее известное состояние окна (позиция в canvas-space + размер),
|
||||
// чтобы UI могла запросить его через GET_WINDOW_INFO.
|
||||
// Последнее известное состояние окна (размер), чтобы пересчитывать позицию
|
||||
// при ресайзе/зуме, пока активен dock-режим.
|
||||
let lastSize = { width: 320, height: 200 }
|
||||
|
||||
// Ресайз окна плагина (drag за угол в UI -> useWindowResize -> RESIZE_WINDOW)
|
||||
on('RESIZE_WINDOW', function (windowSize: { width: number; height: number }) {
|
||||
const { width, height } = windowSize
|
||||
lastSize = { width, height }
|
||||
figma.ui.resize(width, height)
|
||||
})
|
||||
// Текущий режим докинга. null = окно свободно (не прижато).
|
||||
// Пока не null — позиция пересчитывается при каждом изменении viewport
|
||||
// (через поллинг, т.к. события viewportchange в API нет), иначе
|
||||
// canvas-space-точка "уплывает" на экране при смене зума/пана.
|
||||
let dockedPosition: 'left' | 'right' | 'center' | null = null
|
||||
|
||||
// Эмуляция докинга: прижать окно плагина к краям canvas (left/right/center).
|
||||
// reposition() принимает canvas-space координаты (как figma.viewport.center).
|
||||
// Ширину панелей Figma API не отдаёт, поэтому прижимаем к bounds видимой области.
|
||||
on('DOCK_WINDOW', function (payload: { position: 'left' | 'right' | 'center'; width: number; height: number }) {
|
||||
const { position, width, height } = payload
|
||||
lastSize = { width, height }
|
||||
figma.ui.resize(width, height)
|
||||
// Прижать окно к краю видимой области canvas (bounds) в canvas-space.
|
||||
// reposition() интерпретирует x/y как canvas-space, поэтому окно визуально
|
||||
// остаётся у края ЭКРАНА только пока мы пересчитываем его при изменении viewport.
|
||||
function applyDock (position: 'left' | 'right' | 'center', width: number, height: number) {
|
||||
const b = figma.viewport.bounds
|
||||
let x = b.x
|
||||
let y = b.y
|
||||
@@ -32,6 +28,48 @@ export default function () {
|
||||
y = b.y + (b.height - height) / 2
|
||||
}
|
||||
figma.ui.reposition(x, y)
|
||||
}
|
||||
|
||||
// Поллинг viewport: держим окно прижатым к краю при любом зуме/панорамировании.
|
||||
// События viewportchange в Figma API НЕТ (нельзя подписаться через figma.on),
|
||||
// поэтому опрашиваем bounds и репозиционируем только когда он реально изменился.
|
||||
// Это предотвращает "уплывание" окна на экране: reposition() работает в canvas-space,
|
||||
// а bounds при зуме сжимается/растягивается — без пересчёта точка уезжает.
|
||||
let lastBoundsKey = ''
|
||||
const dockInterval = setInterval(function () {
|
||||
if (dockedPosition === null) return
|
||||
const b = figma.viewport.bounds
|
||||
const key = `${b.x}|${b.y}|${b.width}|${b.height}`
|
||||
if (key !== lastBoundsKey) {
|
||||
lastBoundsKey = key
|
||||
applyDock(dockedPosition, lastSize.width, lastSize.height)
|
||||
}
|
||||
}, 250)
|
||||
|
||||
// Ресайз окна плагина (drag за угол в UI -> useWindowResize -> RESIZE_WINDOW)
|
||||
on('RESIZE_WINDOW', function (windowSize: { width: number; height: number }) {
|
||||
const { width, height } = windowSize
|
||||
lastSize = { width, height }
|
||||
figma.ui.resize(width, height)
|
||||
// Если окно задокено — держим прижатым к краю при смене размера
|
||||
if (dockedPosition !== null) {
|
||||
applyDock(dockedPosition, width, height)
|
||||
}
|
||||
})
|
||||
|
||||
// Эмуляция докинга: прижать окно к краям canvas (left/right/center).
|
||||
on('DOCK_WINDOW', function (payload: { position: 'left' | 'right' | 'center'; width: number; height: number }) {
|
||||
const { position, width, height } = payload
|
||||
lastSize = { width, height }
|
||||
figma.ui.resize(width, height)
|
||||
dockedPosition = position
|
||||
lastBoundsKey = '' // форсируем пересчёт на ближайшем тике
|
||||
applyDock(position, width, height)
|
||||
})
|
||||
|
||||
// Останавливаем поллинг при закрытии плагина, чтобы не висел в памяти.
|
||||
figma.on('close', function () {
|
||||
clearInterval(dockInterval)
|
||||
})
|
||||
|
||||
// UI запрашивает текущие x/y (canvas-space) и размеры окна для отладочного вывода,
|
||||
|
||||
Reference in new issue
Block a user