Skip to content

Arrows Plugin

The Arrows plugin provides elbow arrow connectors. Arrows can connect to blocks and automatically update when blocks move.

  • Select an arrow tool and drag from one shape to another to create a connection
  • Click on an arrow to select it and show edit handles

The Arrows plugin is included by default when using WovenCanvas. To configure it:

<template>
<WovenCanvas
:plugin-options="{
arrows: { elbowArrowPadding: 100 }
}"
/>
</template>
OptionTypeDefaultDescription
elbowArrowPaddingnumber50Padding around blocks when routing elbow arrows
ArrowsPlugin({
elbowArrowPadding: 100, // More space around blocks for arrow routing
})

Orthogonal (right-angle) arrows that automatically route around obstacles. The path adjusts when connected blocks move.

  • Block connections — Arrows snap to block edges and follow when blocks move
  • Transform handles — Edit arrow shape after creation
  • Automatic routing — Elbow arrows find paths around obstacles
  • Arrow heads — Configurable start and end arrow heads
  • Color support — Arrows inherit the current color
ComponentDescription
ElbowArrowOrthogonal arrow with automatic routing
ArrowHandleDraggable control point for editing
ArrowTerminalConnection snap point indicator

Arrow terminals are visual indicators that appear on blocks when dragging arrow handles, showing valid snap points for connections. When you drag an arrow endpoint near a block, terminals appear at predefined positions where the arrow can connect.

Terminals are defined per block type via the connectors option in the block definition:

import { defineBlockDef } from '@woven-canvas/core'
defineBlockDef({
tag: 'my-block',
connectors: {
enabled: true,
terminals: [
[0.5, 0], // Top center
[1, 0.5], // Right center
[0.5, 1], // Bottom center
[0, 0.5], // Left center
],
},
})

Terminal positions use UV coordinates where [0, 0] is the top-left corner and [1, 1] is the bottom-right corner of the block.

When an arrow handle is dragged within snap distance of a terminal, it automatically snaps to that position, ensuring consistent connection points.

import { ArrowHeadKind } from '@woven-canvas/plugin-arrows'
// Available arrow head styles
ArrowHeadKind.None // No arrow head
ArrowHeadKind.V // V-shaped arrow head
ArrowHeadKind.Triangle // Filled triangle
ArrowHeadKind.Diamond // Diamond shape
ArrowHeadKind.Circle // Circle
import { ElbowArrow } from '@woven-canvas/plugin-arrows'
import { defineQuery } from '@woven-canvas/core'
const elbowArrowQuery = defineQuery((q) => q.with(ElbowArrow))
// In a system
for (const entityId of elbowArrowQuery.current(ctx)) {
const arrow = ElbowArrow.read(ctx, entityId)
console.log('Start:', arrow.startX, arrow.startY)
console.log('End:', arrow.endX, arrow.endY)
}

The Vue package provides toolbar and floating menu components for arrows:

ComponentDescription
ElbowArrowToolToolbar button for orthogonal arrows
ArrowThicknessButtonFloating menu dropdown for stroke thickness (S, M, L)
ArrowHeadButtonFloating menu dropdown for arrow head style
<script setup lang="ts">
import { WovenCanvas, ElbowArrowTool, Toolbar } from '@woven-canvas/vue'
</script>
<template>
<WovenCanvas>
<template #toolbar>
<Toolbar>
<ElbowArrowTool />
</Toolbar>
</template>
</WovenCanvas>
</template>

When an arrow is selected, the floating menu automatically shows arrow-specific controls. These are included in the default FloatingMenuBar. To customize:

<script setup lang="ts">
import {
WovenCanvas,
FloatingMenu,
FloatingMenuBar,
ArrowHeadButton,
ArrowThicknessButton,
} from '@woven-canvas/vue'
</script>
<template>
<WovenCanvas>
<template #floating-menu>
<FloatingMenu>
<FloatingMenuBar>
<template #button:arrowThickness="{ entityIds }">
<ArrowThicknessButton :entity-ids="entityIds" />
</template>
<template #button:arrowHeadStart="{ entityIds }">
<ArrowHeadButton :entity-ids="entityIds" side="start" />
</template>
<template #button:arrowHeadEnd="{ entityIds }">
<ArrowHeadButton :entity-ids="entityIds" side="end" />
</template>
</FloatingMenuBar>
</FloatingMenu>
</template>
</WovenCanvas>
</template>
PropTypeDescription
entityIdsEntityId[]Selected arrow entity IDs
side'start' | 'end'Which end of the arrow to configure
PropTypeDescription
entityIdsEntityId[]Selected arrow entity IDs