feat: maximize window to full viewport (maxViewport = bounds*zoom), clamp drag
This commit is contained in:
1 parent
4228357a35
commit
b2ae4c44d6
2 files changed
+43
-10
No files matched your search
+26
-2
@@ -51,9 +51,24 @@ export default function () {
|
||||
}
|
||||
}, 250)
|
||||
|
||||
// Кламп размера окна: не меньше минимума и не больше видимого viewport.
|
||||
// Видимый viewport в ЭКРАННЫХ пикселях = bounds * zoom (bounds — в canvas-space,
|
||||
// zoom переводит в px). useWindowResize при drag даёт большие значения — main
|
||||
// приводит к допустимому, чтобы окно не вылезало за canvas и не ломало Figma.
|
||||
function clampWindowSize (size: { width: number; height: number }) {
|
||||
const b = figma.viewport.bounds
|
||||
const zoom = figma.viewport.zoom || 1
|
||||
const maxW = Math.max(320, Math.round(b.width * zoom))
|
||||
const maxH = Math.max(200, Math.round(b.height * zoom))
|
||||
return {
|
||||
width: Math.max(320, Math.min(maxW, Math.round(size.width))),
|
||||
height: Math.max(200, Math.min(maxH, Math.round(size.height)))
|
||||
}
|
||||
}
|
||||
|
||||
// Ресайз окна плагина (drag за угол в UI -> useWindowResize -> RESIZE_WINDOW)
|
||||
on('RESIZE_WINDOW', function (windowSize: { width: number; height: number }) {
|
||||
const { width, height } = windowSize
|
||||
const { width, height } = clampWindowSize(windowSize)
|
||||
lastSize = { width, height }
|
||||
figma.ui.resize(width, height)
|
||||
// Если окно задокено — держим прижатым к краю при смене размера
|
||||
@@ -64,7 +79,8 @@ export default function () {
|
||||
|
||||
// Эмуляция докинга: прижать окно к краям canvas (left/right/center).
|
||||
on('DOCK_WINDOW', function (payload: { position: 'left' | 'right' | 'center'; width: number; height: number }) {
|
||||
const { position, width, height } = payload
|
||||
const { position } = payload
|
||||
const { width, height } = clampWindowSize(payload)
|
||||
lastSize = { width, height }
|
||||
figma.ui.resize(width, height)
|
||||
dockedPosition = position
|
||||
@@ -109,6 +125,13 @@ export default function () {
|
||||
const cx = Math.round(x + wCanvas / 2)
|
||||
const cy = Math.round(y + hCanvas / 2)
|
||||
|
||||
// Максимальный размер окна (экранные px) = весь видимый viewport (bounds * zoom).
|
||||
// Используется кнопкой "развернуть" в UI и как верхняя граница drag-ресайза.
|
||||
const maxViewport = {
|
||||
width: Math.max(320, Math.round(b.width * zoom)),
|
||||
height: Math.max(200, Math.round(b.height * zoom))
|
||||
}
|
||||
|
||||
emit('WINDOW_INFO', {
|
||||
x,
|
||||
y,
|
||||
@@ -121,6 +144,7 @@ export default function () {
|
||||
width: Math.round(b.width),
|
||||
height: Math.round(b.height)
|
||||
},
|
||||
maxViewport,
|
||||
gapL,
|
||||
gapR,
|
||||
gapT,
|
||||
|
||||
+17
-8
@@ -17,7 +17,9 @@ import { h, Fragment } from 'preact'
|
||||
import { useState, useEffect } from 'preact/hooks'
|
||||
|
||||
const MIN_WINDOW_SIZE = { width: 320, height: 200 }
|
||||
const MAX_WINDOW_SIZE = { width: 800, height: 800 }
|
||||
// Статичного максимума нет: "развернуть" целится в весь viewport (maxViewport из main),
|
||||
// а верхняя граница drag-ресайза тоже приходит оттуда. useWindowResize ставим очень
|
||||
// большой max — реальный кламп делает main через clampWindowSize (bounds*zoom).
|
||||
|
||||
// Одна строка отладочного вывода: имя переменной из кода (как в main.ts),
|
||||
// опционально — формула расчёта, и само значение (моноширинное, по правому краю).
|
||||
@@ -49,6 +51,7 @@ function Plugin () {
|
||||
x: number; y: number; width: number; height: number
|
||||
zoom: number
|
||||
viewport: { x: number; y: number; width: number; height: number }
|
||||
maxViewport: { width: number; height: number }
|
||||
gapL: number; gapR: number; gapT: number; gapB: number
|
||||
center: { x: number; y: number }
|
||||
} | null>(null)
|
||||
@@ -65,8 +68,10 @@ function Plugin () {
|
||||
}, {
|
||||
minWidth: 320,
|
||||
minHeight: 200,
|
||||
maxWidth: 800,
|
||||
maxHeight: 800
|
||||
// Верхний предел оставляем большим — реальный кламп (весь viewport) делает main
|
||||
// через clampWindowSize (bounds * zoom), иначе на маленьком viewport окно не растянуть.
|
||||
maxWidth: 100000,
|
||||
maxHeight: 100000
|
||||
})
|
||||
|
||||
// Слушаем ответ от main с актуальными x/y (canvas-space) и размерами окна
|
||||
@@ -75,6 +80,7 @@ function Plugin () {
|
||||
x: number; y: number; width: number; height: number
|
||||
zoom: number
|
||||
viewport: { x: number; y: number; width: number; height: number }
|
||||
maxViewport: { width: number; height: number }
|
||||
gapL: number; gapR: number; gapT: number; gapB: number
|
||||
center: { x: number; y: number }
|
||||
}) {
|
||||
@@ -177,10 +183,12 @@ function Plugin () {
|
||||
}, [])
|
||||
|
||||
function toggleWindowSize () {
|
||||
const max = windowInfo != null
|
||||
? windowInfo.maxViewport
|
||||
: { width: 800, height: 800 }
|
||||
const isMaximized =
|
||||
currentWindowSize.width >= MAX_WINDOW_SIZE.width &&
|
||||
currentWindowSize.height >= MAX_WINDOW_SIZE.height
|
||||
const next = isMaximized ? { ...MIN_WINDOW_SIZE } : { ...MAX_WINDOW_SIZE }
|
||||
currentWindowSize.width >= max.width && currentWindowSize.height >= max.height
|
||||
const next = isMaximized ? { ...MIN_WINDOW_SIZE } : { ...max }
|
||||
setCurrentWindowSize(next)
|
||||
emit('RESIZE_WINDOW', next)
|
||||
refreshInfo()
|
||||
@@ -195,9 +203,9 @@ function Plugin () {
|
||||
refreshInfo()
|
||||
}
|
||||
|
||||
const max = windowInfo != null ? windowInfo.maxViewport : { width: 800, height: 800 }
|
||||
const isMaximized =
|
||||
currentWindowSize.width >= MAX_WINDOW_SIZE.width &&
|
||||
currentWindowSize.height >= MAX_WINDOW_SIZE.height
|
||||
currentWindowSize.width >= max.width && currentWindowSize.height >= max.height
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
@@ -246,6 +254,7 @@ function Plugin () {
|
||||
<Field name="figma.viewport.bounds" value={`${windowInfo.viewport.x},${windowInfo.viewport.y} · ${windowInfo.viewport.width}×${windowInfo.viewport.height}`} />
|
||||
<Field name="lastSize.width" value={windowInfo.width} />
|
||||
<Field name="lastSize.height" value={windowInfo.height} />
|
||||
<Field name="maxViewport (bounds·zoom)" formula="bounds.width*zoom, bounds.height*zoom" value={`${windowInfo.maxViewport.width}×${windowInfo.maxViewport.height}`} />
|
||||
</Section>
|
||||
{/* Расчётные — посчитаны в main.ts из вышеперечисленных raw-значений */}
|
||||
<Section title="РАСЧЁТ · в main.ts">
|
||||
|
||||
Reference in new issue
Block a user