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
|
const PLUGIN_HEADER_PX = 38
|
||||||
|
|
||||||
// Вычислить целевое состояние окна для позиции докинга:
|
// Вычислить целевое состояние окна для позиции докинга:
|
||||||
// - Лево/Право: ширина 320px, высота = макс (весь viewport по вертикали минус шапка)
|
// - Лево/Право: ширина = dockEdgeSize (редактируемая, по умолч. 320), высота = макс (весь viewport по вертикали минус шапка)
|
||||||
// - Верх/Низ: высота 320px, ширина = макс (весь viewport по горизонтали)
|
// - Верх/Низ: высота = dockEdgeSize, ширина = макс (весь viewport по горизонтали)
|
||||||
// - Углы: НЕ меняют размер, только прижимают к соответствующему углу viewport
|
// - Углы: размер НЕ фиксируется (редактируется вручную), только прижимают к углу (с клампом в пределах viewport)
|
||||||
// - Центр: размер = 50% viewport (по ширине и высоте), центрируется
|
// - Центр: размер = 50% viewport (по ширине и высоте), центрируется (one-shot, не удерживает)
|
||||||
// Возвращает размер (экранные px) и позицию (canvas-space, прижатую к нужному краю).
|
// Возвращает размер (экранные 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) {
|
function computeDock (position: DockPosition, currentWidth: number, currentHeight: number) {
|
||||||
const b = figma.viewport.bounds
|
const b = figma.viewport.bounds
|
||||||
const zoom = figma.viewport.zoom || 1
|
const zoom = figma.viewport.zoom || 1
|
||||||
@@ -39,22 +40,25 @@ export default function () {
|
|||||||
const maxH = Math.round(b.height * zoom) - PLUGIN_HEADER_PX
|
const maxH = Math.round(b.height * zoom) - PLUGIN_HEADER_PX
|
||||||
const isLeftRight = position === 'center-left' || position === 'center-right'
|
const isLeftRight = position === 'center-left' || position === 'center-right'
|
||||||
const isTopBottom = position === 'top-center' || position === 'bottom-center'
|
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'
|
const isCenter = position === 'center'
|
||||||
|
|
||||||
let targetW = currentWidth
|
let targetW = currentWidth
|
||||||
let targetH = currentHeight
|
let targetH = currentHeight
|
||||||
if (isLeftRight) {
|
if (isLeftRight) {
|
||||||
targetW = DOCK_EDGE_SIZE
|
targetW = dockEdgeSize
|
||||||
targetH = maxH
|
targetH = maxH
|
||||||
} else if (isTopBottom) {
|
} else if (isTopBottom) {
|
||||||
targetW = maxW
|
targetW = maxW
|
||||||
targetH = DOCK_EDGE_SIZE
|
targetH = dockEdgeSize
|
||||||
} else if (isCenter) {
|
} else if (isCenter) {
|
||||||
targetW = Math.round(maxW / 2)
|
targetW = Math.round(maxW / 2)
|
||||||
targetH = Math.round(maxH / 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 от целевого размера
|
// canvas-units от целевого размера
|
||||||
const wCanvas = targetW / zoom
|
const wCanvas = targetW / zoom
|
||||||
const hCanvas = (PLUGIN_HEADER_PX + targetH) / zoom
|
const hCanvas = (PLUGIN_HEADER_PX + targetH) / zoom
|
||||||
@@ -117,18 +121,32 @@ export default function () {
|
|||||||
const { width, height } = clampWindowSize(windowSize)
|
const { width, height } = clampWindowSize(windowSize)
|
||||||
lastSize = { width, height }
|
lastSize = { width, height }
|
||||||
figma.ui.resize(width, height)
|
figma.ui.resize(width, height)
|
||||||
// Если окно задокено — держим прижатым к краю при смене размера
|
// Если окно задокено — держим прижатым к краю при смене размера.
|
||||||
|
// При этом фикс-сторона edge-позиции (dockEdgeSize) ОБНОВЛЯЕТСЯ из ручного
|
||||||
|
// ресайза, чтобы пользователь мог менять её (а не была заблокирована на 320).
|
||||||
if (dockedPosition !== null) {
|
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)
|
applyDock(dockedPosition, width, height)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Эмуляция докинга: растянуть окно на зону и прижать к её краю (9 позиций).
|
// Эмуляция докинга: растянуть окно на зону и прижать к её краю (9 позиций).
|
||||||
on('DOCK_WINDOW', function (payload: { position: DockPosition; width: number; height: number }) {
|
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
|
dockedPosition = position
|
||||||
lastBoundsKey = '' // форсируем пересчёт на ближайшем тике
|
lastBoundsKey = '' // форсируем пересчёт на ближайшем тике
|
||||||
applyDock(position, payload.width, payload.height)
|
applyDock(position, width, height)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Останавливаем поллинг при закрытии плагина, чтобы не висел в памяти.
|
// Останавливаем поллинг при закрытии плагина, чтобы не висел в памяти.
|
||||||
|
|||||||
Reference in new issue
Block a user