qurle  
← to all thoughts

Контролы для плагинов прямо на канвасе Фигмы

2 июля 2026 г.

Знали, что в плагинах фигмы есть контролы, которые можно размещать прямо на объектах? Это скрытое АПИ без открытой документации. Пока что!

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Текущая позиция — доступна для чтения и записи
removedtrue после 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()
})

Особенности поведения

g
o
t
o
t
o
p