feat: edge fix-size editable via manual resize; center one-shot; corners keep size
This commit is contained in:
1 parent
61577b01cd
commit
ab6a2e879f
1 file changed
+30
-12
+30
-12
@@ -26,12 +26,13 @@ export default function () {
|
||||
const PLUGIN_HEADER_PX = 38
|
||||
|
||||
// Вычислить целевое состояние окна для позиции докинга:
|
||||
// - Лево/Право: ширина 320px, высота = макс (весь viewport по вертикали минус шапка)
|
||||
// - Верх/Низ: высота 320px, ширина = макс (весь viewport по горизонтали)
|
||||
// - Углы: НЕ меняют размер, только прижимают к соответствующему углу viewport
|
||||
// - Центр: размер = 50% viewport (по ширине и высоте), центрируется
|
||||
// - Лево/Право: ширина = dockEdgeSize (редактируемая, по умолч. 320), высота = макс (весь viewport по вертикали минус шапка)
|
||||
// - Верх/Низ: высота = dockEdgeSize, ширина = макс (весь viewport по горизонтали)
|
||||
// - Углы: размер НЕ фиксируется (редактируется вручную), только прижимают к углу (с клампом в пределах viewport)
|
||||
// - Центр: размер = 50% viewport (по ширине и высоте), центрируется (one-shot, не удерживает)
|
||||
// Возвращает размер (экранные px) и позицию (canvas-space, прижатую к нужному краю).
|
||||
const DOCK_EDGE_SIZE = 320
|
||||
const DEFAULT_DOCK_EDGE = 320
|
||||
let dockEdgeSize = DEFAULT_DOCK_EDGE // редактируемая фикс-сторона для edge-позиций (320 по умолч.)
|
||||
function computeDock (position: DockPosition, currentWidth: number, currentHeight: number) {
|
||||
const b = figma.viewport.bounds
|
||||
const zoom = figma.viewport.zoom || 1
|
||||
@@ -39,22 +40,25 @@ export default function () {
|
||||
const maxH = Math.round(b.height * zoom) - PLUGIN_HEADER_PX
|
||||
const isLeftRight = position === 'center-left' || position === 'center-right'
|
||||
const isTopBottom = position === 'top-center' || position === 'bottom-center'
|
||||
const isCorner = position === 'top-left' || position === 'top-right' || position === 'bottom-left' || position === 'bottom-right'
|
||||
const isCenter = position === 'center'
|
||||
|
||||
let targetW = currentWidth
|
||||
let targetH = currentHeight
|
||||
if (isLeftRight) {
|
||||
targetW = DOCK_EDGE_SIZE
|
||||
targetW = dockEdgeSize
|
||||
targetH = maxH
|
||||
} else if (isTopBottom) {
|
||||
targetW = maxW
|
||||
targetH = DOCK_EDGE_SIZE
|
||||
targetH = dockEdgeSize
|
||||
} else if (isCenter) {
|
||||
targetW = Math.round(maxW / 2)
|
||||
targetH = Math.round(maxH / 2)
|
||||
} else if (isCorner) {
|
||||
// размер редактируется вручную, только клампим в пределы viewport
|
||||
targetW = Math.min(currentWidth, maxW)
|
||||
targetH = Math.min(currentHeight, maxH)
|
||||
}
|
||||
// Углы (top-left/right, bottom-left/right): размер НЕ меняем (targetW/targetH = current),
|
||||
// только позиция прижимается к соответствующему углу viewport.
|
||||
// canvas-units от целевого размера
|
||||
const wCanvas = targetW / zoom
|
||||
const hCanvas = (PLUGIN_HEADER_PX + targetH) / zoom
|
||||
@@ -117,18 +121,32 @@ export default function () {
|
||||
const { width, height } = clampWindowSize(windowSize)
|
||||
lastSize = { width, height }
|
||||
figma.ui.resize(width, height)
|
||||
// Если окно задокено — держим прижатым к краю при смене размера
|
||||
// Если окно задокено — держим прижатым к краю при смене размера.
|
||||
// При этом фикс-сторона edge-позиции (dockEdgeSize) ОБНОВЛЯЕТСЯ из ручного
|
||||
// ресайза, чтобы пользователь мог менять её (а не была заблокирована на 320).
|
||||
if (dockedPosition !== null) {
|
||||
const isLeftRight = dockedPosition === 'center-left' || dockedPosition === 'center-right'
|
||||
const isTopBottom = dockedPosition === 'top-center' || dockedPosition === 'bottom-center'
|
||||
if (isLeftRight) dockEdgeSize = width
|
||||
else if (isTopBottom) dockEdgeSize = height
|
||||
applyDock(dockedPosition, width, height)
|
||||
}
|
||||
})
|
||||
|
||||
// Эмуляция докинга: растянуть окно на зону и прижать к её краю (9 позиций).
|
||||
on('DOCK_WINDOW', function (payload: { position: DockPosition; width: number; height: number }) {
|
||||
const { position } = payload
|
||||
const { position, width, height } = payload
|
||||
// Центр — это one-shot: применяем 50% по центру ОДИН раз, НЕ включаем поллинг
|
||||
// (окно не "приклеено", ручной ресайз/драг работают свободно после).
|
||||
if (position === 'center') {
|
||||
dockedPosition = null
|
||||
applyDock('center', width, height)
|
||||
return
|
||||
}
|
||||
// Остальные позиции — удерживаем прижатым (поллинг пересчитывает при зуме/пане).
|
||||
dockedPosition = position
|
||||
lastBoundsKey = '' // форсируем пересчёт на ближайшем тике
|
||||
applyDock(position, payload.width, payload.height)
|
||||
applyDock(position, width, height)
|
||||
})
|
||||
|
||||
// Останавливаем поллинг при закрытии плагина, чтобы не висел в памяти.
|
||||
|
||||
Reference in new issue
Block a user