Знали, что в плагинах фигмы есть контролы, которые можно размещать прямо на объектах? Это скрытое АПИ без открытой документации. Пока что!
createCanvasControl()
Интерактивный API canvas-хендлов для плагинов Figma. Рисует перетаскиваемые хендлы прямо на канвасе, привязанные к слою, пока плагин открыт.
⚠️ Заметка: Это приватный API, доступный только AI-агентам. Он не входит в
@figma/plugin-typingsи не описан на developers.figma.com. Источник истины — типы, встраиваемые в сборку плагина.
Доступность
Доступен у SceneNode как опциональный метод. Перед вызовом всегда проверяйте наличие:
if (typeof node.createCanvasControl === 'function') {
const control = node.createCanvasControl({ ... })
}
Сигнатура
node.createCanvasControl(options: CreateCanvasControlOptions): CanvasControl
Типы контролов
POINT
Одна перетаскиваемая точка.
{
key: string
type: 'POINT'
name?: string
unit?: 'px' | '%' // default: '%'
value: { x: number; y: number }
}
POINT_RADIUS
Точка с кольцом радиуса. Перетаскивание центра двигает точку, перетаскивание кольца меняет радиус.
{
key: string
type: 'POINT_RADIUS'
positionUnit?: 'px' | '%'
radiusUnit?: 'px' | '%'
value: { x: number; y: number; radius: number }
}
POINT_ANGLE_RADIUS
Точка с кольцом радиуса и рычагом угла. Используется для источника света или направленных контролов.
{
key: string
type: 'POINT_ANGLE_RADIUS'
positionUnit?: 'px' | '%'
radiusUnit?: 'px' | '%'
value: { x: number; y: number; radius: number; angle: number } // angle in degrees
}
POINT_POINT_LINE
Две перетаскиваемые конечные точки, соединённые линией.
{
key: string
type: 'POINT_POINT_LINE'
unit?: 'px' | '%'
value: { x: number; y: number; x2: number; y2: number }
}
COLOR_POINT
Перетаскиваемая точка с образцом цвета. Клик открывает выбор цвета.
{
key: string
type: 'COLOR_POINT'
unit?: 'px' | '%'
value: {
x: number; y: number
color: { r: number; g: number; b: number; a: number } // 0–1
}
}
Интерфейс CanvasControl
interface CanvasControl {
readonly id: string
readonly type:
| 'POINT'
| 'POINT_RADIUS'
| 'POINT_ANGLE_RADIUS'
| 'POINT_POINT_LINE'
| 'COLOR_POINT'
value: CanvasControlValue
readonly removed: boolean
on(
event: 'change',
handler: (value: CanvasControlValue, isDragging: boolean) => void,
): void
once(
event: 'change',
handler: (value: CanvasControlValue, isDragging: boolean) => void,
): void
off(
event: 'change',
handler: (value: CanvasControlValue, isDragging: boolean) => void,
): void
remove(): void
}
| Свойство | Описание |
|---|---|
id | Уникальный ID хендла |
value | Текущая позиция — доступна для чтения и записи |
removed | true после remove() |
on('change', fn) | Срабатывает во время перетаскивания; isDragging равен true во время драга и false при отпускании |
remove() | Удаляет хендл |
Единицы измерения
| Единица | Значение |
|---|---|
'%' | Относительно размера слоя — масштабируется вместе со слоем |
'px' | Абсолютные локальные пиксели узла — не масштабируется |
Пример использования
const control = node.createCanvasControl!({
key: 'light-source',
type: 'POINT_ANGLE_RADIUS',
positionUnit: '%',
radiusUnit: '%',
value: { x: 50, y: 50, radius: 30, angle: -45 },
})
control.on('change', (value, isDragging) => {
const v = value as CanvasControlPointAngleRadiusValue
myParams.light = v
figma.ui.postMessage({
type: 'spatial-param-change',
name: 'light',
value: v,
})
applyEffect(myParams)
})
// Sync handle from UI
if (!control.removed) control.value = { x, y, radius, angle }
// Cleanup
figma.on('close', () => {
if (!control.removed) control.remove()
})
Особенности поведения
- Хендлы видны только пока плагин открыт — при закрытии уничтожаются автоматически.
- Один хендл на
keyна узел — повторное использование того же key заменяет существующий хендл. - Координаты локальны для узла, а не координаты страницы.
{ x: 50, y: 50 }в%всегда означает центр слоя. - Всегда проверяйте
control.removedперед обращением к сохранённой ссылке после смены выделения. - Не создавайте скрытые слои для имитации хендлов — используйте этот API напрямую.