diff --git a/src/main.ts b/src/main.ts index ca845df..5bbf155 100644 --- a/src/main.ts +++ b/src/main.ts @@ -20,16 +20,19 @@ export default function () { | 'center-left' | 'center' | 'center-right' | 'bottom-left' | 'bottom-center' | 'bottom-right' + // Высота шапки окна плагина (title bar Figma с крестиком), экранные px. + // Окно плагина = шапка (PLUGIN_HEADER_PX) + iframe (height px). getPosition().y — это + // верх шапки, поэтому полная высота окна = (PLUGIN_HEADER_PX + height) / zoom. + const PLUGIN_HEADER_PX = 38 + // Прижать окно к краю видимой области canvas (bounds) в canvas-space. // ВАЖНО: reposition()/getPosition() и bounds — в canvas-space (единицы документа), - // а figma.ui.resize(width,height) — в ЭКРАННЫХ пикселях. Размер окна в canvas-units = - // width / zoom. Без этого деления при zoom≠100% окно прижимается с ошибкой - // (px-размер вычитается из canvas-ширины → уезжает пропорционально 1/zoom). + // а figma.ui.resize(width,height) — в ЭКРАННЫХ пикселях. Размер окна в canvas-units =\n // width / zoom (по ширине) и (PLUGIN_HEADER_PX + height) / zoom (по высоте, т.к. окно\n // включает шапку). Без учёта шапки прижатый к низу/центру окно висит на 38px выше нужного. function applyDock (position: DockPosition, width: number, height: number) { const b = figma.viewport.bounds const zoom = figma.viewport.zoom || 1 const wCanvas = width / zoom - const hCanvas = height / zoom + const hCanvas = (PLUGIN_HEADER_PX + height) / zoom let x = b.x let y = b.y // По горизонтали @@ -38,7 +41,7 @@ export default function () { } else if (position === 'top-right' || position === 'center-right' || position === 'bottom-right') { x = b.x + b.width - wCanvas } - // По вертикали + // По вертикали (hCanvas учитывает шапку окна) if (position === 'center-left' || position === 'center' || position === 'center-right') { y = b.y + (b.height - hCanvas) / 2 } else if (position === 'bottom-left' || position === 'bottom-center' || position === 'bottom-right') { @@ -132,16 +135,16 @@ export default function () { // Размер окна в ЭКРАННЫХ пикселях (w/h) переводим в canvas-units через zoom, // чтобы корректно вычитать из canvas-ширины bounds при любом зуме. const wCanvas = w / zoom - const hCanvas = h / zoom - // Геометрия окна плагина относительно видимой области canvas (bounds). - // gapL/gapR/gapT/gapB — отступы окна от левого/правого/верхнего/нижнего края canvas. + // Полная высота окна = шапка (PLUGIN_HEADER_PX) + iframe (h), поэтому по вертикали + // считаем от (PLUGIN_HEADER_PX + h)/zoom, а не от h/zoom (иначе gapB/center.y неверны). + const fullHCanvas = (PLUGIN_HEADER_PX + h) / zoom const gapL = Math.round(x - b.x) const gapT = Math.round(y - b.y) const gapR = Math.round(b.x + b.width - (x + wCanvas)) - const gapB = Math.round(b.y + b.height - (y + hCanvas)) + const gapB = Math.round(b.y + b.height - (y + fullHCanvas)) const cx = Math.round(x + wCanvas / 2) - const cy = Math.round(y + hCanvas / 2) + const cy = Math.round(y + fullHCanvas / 2) // Нормализованная позиция окна относительно видимого viewport (левый верхний угол // окна в координатах bounds). relX = x − bounds.x, relY = y − bounds.y. Это те же diff --git a/src/ui.tsx b/src/ui.tsx index dace9c2..5d07041 100644 --- a/src/ui.tsx +++ b/src/ui.tsx @@ -313,8 +313,8 @@ function Plugin () { />