Skip to content

Показ портов и роли ​

Порт — это то, чем заканчивается линия и за что пользователь берётся, чтобы начать соединение. Здесь описано, как порты рисуются, чем источник отличается от приёмника, как линия останавливается у порта и как сохранить рабочими кнопки внутри блоков.

Один порт — один кружок ​

Порт — это один кружок. Он же конец линии и он же ручка, которую тянет пользователь; его размер, обводка и цвета не меняются, когда соединение появляется или исчезает. Во время жеста сверху применяются только поля из ports.connect.*, зависящие от состояния.

Если порт нарисован кружком, отдельная точка-ручка для того же порта скрывается, поэтому ничего не рисуется дважды.

Какие порты рисуются ​

Решает ports.show:

  • false — кружков нет.
  • true или 'connected' — кружок на каждом порту, у которого есть хотя бы одно соединение. Это значение по умолчанию.
  • 'all' — кружок на каждом объявленном нескрытом порту, соединён он или нет. Нужен, когда у каждой строки списка должно быть видно, куда можно подключить линию.

Порты строк, прокрученных за край, подчиняются clipToScrollParents, как и раньше. ports.fadeEdge (px) гасит порт на этом расстоянии до видимого края прокручиваемой области, чтобы порт не появлялся и не пропадал рывком.

Стили по ролям ​

Кружок порта оформляется слоями, каждый перекрывает предыдущий:

  1. ports.* — стиль группы.
  2. ports.source / ports.target — по роли (connect: 'source' | 'target' у порта). Каждый — стиль с состояниями, как и ports.
  3. ports.connected — порты, у которых есть хотя бы одно соединение.
  4. style в описании порта (v-vl-port="{ id, style: { fill } }").
  5. ports.sync: 'marker' — обводка кружка берётся от маркера соединения, включая его состояние hover.
  6. ports.connect.<состояние> — состояние жеста: source, candidate, target, invalid.

Кружок получает классы vl-port--source / vl-port--target, vl-port--connected, vl-port--<состояние> и собственный className порта. Классы роли и connected добавляются, когда включено создание соединений, ports.show равен 'all' или задан один из ports.source, ports.target, ports.connected; иначе разметка такая же, как без этих возможностей.

Порт, нарисованный вами ​

  • ports.render: 'svg' — по умолчанию: кружок рисует библиотека.
  • ports.render: 'dom' — библиотека не рисует ни кружок, ни ручку. Порт — ваш собственный элемент (цель v-vl-port, обычно маленький <span> в строке). Библиотека запускает жест с него, ставит на него data-vl-connect-state и aria-pressed="true" на источник. Требует interaction.connect.enabled. Концы линий по-прежнему считаются по положению порта.
  • Слот #port — в компоненте Vue отрисовывается для каждого подключаемого порта, а не только для соединённых. Параметры слота: { blockId, portId, point, role, connected, state, hovered }; role — 'source' | 'target' | 'both', connected — число соединений, state — 'idle' или состояние жеста, hovered — находится ли указатель над блоком порта. state и hovered заполняются, когда включено создание соединений или ports.show равен 'all'. ports.slotPointerEvents: false делает содержимое слота прозрачным для указателя.

Линия останавливается у порта ​

По умолчанию линия идёт в центр порта, под кружок. Чтобы остановить её у края:

  • lines.endGap — число или { start, end } в px: линия заканчивается на этом расстоянии до порта вдоль нормали стороны.
  • ports.clearance — число в px или 'auto', то есть радиус кружка плюс ширина его обводки. Прибавляется к endGap.

Сам порт остаётся на месте: укорачивается только линия. События layout по-прежнему сообщают настоящую точку порта.

Стороны по ролям ​

ports.sides: { source: 'right', target: 'left' } задаёт сторону по роли, а не для каждого порта. Применяется к портам без своего side, к концу соединения, перешедшему на целый блок, и к линии предпросмотра жеста, начатого с блока.

Концы, перенесённые на запасной блок ​

Соединение, у которого конец оказался на запасном блоке (Запасные концы), можно пометить:

ts
lines: { proxied: { start: 'circle', end: { shape: 'diamond', size: 8 } } }

proxied.start / proxied.end — описания маркеров, применяемые только к перенесённому концу. Блок, принявший линии, получает data-vl-proxy-count="N" с числом перенесённых на него линий, чтобы значок вроде «+3» можно было нарисовать в CSS или в шаблоне.

Кнопки и ссылки внутри блоков ​

Сам блок может быть источником или приёмником соединения (from: 'block', to: 'block'). Интерактивные элементы внутри него должны продолжать работать, поэтому нажатие или клик, начавшиеся на элементе, подходящем под interaction.connect.ignore, не начинают, не завершают и не отменяют соединение. Селектор по умолчанию:

button, a, input, select, textarea, [contenteditable], [data-vl-ignore]

Задайте свой селектор строкой или false, чтобы отключить проверку. stopPropagation в ваших обработчиках не нужен.

Роли блоков ​

connect: 'source' | 'target' | 'both' | false у блока проверяется при начале и при завершении жеста, для from: 'block' и to: 'block' во всех режимах, включая клавиатуру и startConnect / completeConnect. Блок без роли берёт её из своих портов, если роль задана у каждого порта; иначе он 'both'.

Атрибуты на блоках ​

Чтобы оформить всю строку без :has(), библиотека ставит атрибуты на элемент блока:

  • data-vl-connect-state — source, candidate, target или invalid во время жеста (побеждает самое сильное состояние блока или его портов).
  • data-vl-hover — pointer, пока указатель над блоком, line, пока указатель над линией, которая в него входит. Ставится, только если включены interaction.hover, interaction.highlight или создание соединений.
  • data-vl-connecting — на контейнере, пока идёт жест.
  • data-vl-proxy-count — см. выше.

Атрибуты снимаются, когда состояние заканчивается и при уничтожении движка.

Группы линий и совпадающие линии ​

  • connection.kind вместе с lines.kinds: { [kind]: ConnectionStyle } — один стиль для группы соединений. Он лежит между стилем группы и собственным style соединения.
  • lines.overlap: 'offset' — линия, совпадающая с другой (те же концы и путь), сдвигается в сторону на 3 px за шаг (чередуя стороны; для bezier и прямых линий), чтобы были видны обе. По умолчанию 'stack': линии рисуются друг поверх друга.
  • markers.<позиция>.units: 'px' — size маркера в пикселях, не зависит от толщины линии. По умолчанию 'stroke' масштабируется вместе с толщиной.

Обратная связь жеста ​

  • interaction.connect.dimOthers — true (прозрачность 0,35) или число: остальные линии притушены, пока идёт жест.
  • Событие движка connect:candidate — { from, candidate, valid } при каждой смене кандидата (candidate равен null, если под указателем ничего нет). В connect:start приходит via ('drag', 'click', 'keyboard' или 'api').
  • block:mouseenter / block:mouseleave несут via: 'line', когда вызваны наведением на линию, входящую в блок. Когда указатель заходит в сам блок, данные — только { blockId }.
  • В Vue useVisualLinkerConnect(linker) возвращает жест в виде ref-ов; см. Низкоуровневый composable.