Selection Plugin for Knotx
npm install @knotx/plugins-selection选择插件,为 KnotX 提供元素选择功能。
``bash`
npm install @knotx/plugins-selection
Selection 插件为 KnotX 提供了强大的元素选择功能,支持鼠标框选、键盘操作和程序化选择。该插件基于 @knotx/viselect 库实现,提供了灵活的选择规则和丰富的选择事件。
Selection 插件的核心实现原理:
1. 选择区域管理:使用 @knotx/viselect 库创建选择区域,支持拖拽选择
2. 规则系统:通过规则系统定义不同类型元素的选择行为
3. 事件处理:提供完整的选择事件生命周期管理
4. 状态同步:与画布变换状态同步,确保选择区域的准确性
:提供基础插件架构
- @knotx/decorators:提供装饰器支持
- @knotx/viselect:提供选择区域功能$3
- @knotx/plugins-canvas:获取画布变换状态和容器信息(可选)API 文档
$3
#### Selection
选择插件的主要类,继承自
BasePlugin。`typescript
export class Selection extends BasePlugin<'selection', SelectionConfig> {
name = 'selection' as const
}
`$3
#### SelectionConfig
`typescript
export interface SelectionConfig {
/* 选择区域的类名 /
selectionAreaClassName?: string
/* 是否启用拖拽选择 /
enableDrag?: boolean
/* 选择规则 /
rules?: SelectionRule[]
/* 是否禁用默认规则 /
disableDefaultRules?: boolean
/* 选择容器 /
container?: string
}
`#### SelectionRule
`typescript
export interface SelectionRule {
/* 资源类型 /
type: string
/* 元素的类名 /
className: string
/* ID 获取函数 /
idGetter: (element: Element) => string
/* 激活状态的类名 /
activeClassName?: string
/* 选择回调函数 /
onSelected?: (context: SelectionContext) => boolean
/* 数据选择器类型 /
dataSelectorType?: string
/* 是否启用规则 /
enabled?: boolean
}
`$3
Selection 插件提供以下数据:
`typescript
interface PluginData {
selection: {
selected: SelectionSelectedItem[]
registerRules: (rules: SelectionRule[]) => () => void
setRuleEnabled: (type: string, enabled: boolean) => void
setClearSelectionBeforeStart: (isClearSelectionBeforeStart: boolean) => void
setElementOverlap: (overlap: OverlapMode) => void
resolveSelectables: () => void
}
}
`$3
Selection 插件提供以下工具方法:
`typescript
interface PluginTools {
selection: {
select: (items: SelectionSelectedItem[]) => void
deselect: (items: SelectionSelectedItem[]) => void
getSelected: () => SelectionSelectedItem[]
clearSelection: () => void
}
}
`$3
#### SelectionSelectedItem
`typescript
export interface SelectionSelectedItem {
type: string
id: string
}
`使用示例
$3
`typescript
import { Selection } from '@knotx/plugins-selection'const engine = new Engine({
plugins: [Selection],
pluginConfig: {
selection: {
enableDrag: true,
},
},
})
`$3
`typescript
const engine = new Engine({
plugins: [Selection],
pluginConfig: {
selection: {
rules: [
{
type: 'custom-node',
className: 'custom-node-wrapper',
idGetter: element => element.getAttribute('data-node-id') || '',
activeClassName: 'custom-node-selected',
onSelected: (context) => {
console.log('Custom node selected:', context.id)
return true // 返回 true 表示允许选择
},
},
],
},
},
})
`$3
`typescript
// 选择特定元素
engine.callTool('selection', 'select', [
{ type: 'node', id: 'node-1' },
{ type: 'node', id: 'node-2' },
])// 取消选择特定元素
engine.callTool('selection', 'deselect', [
{ type: 'node', id: 'node-1' },
])
// 获取当前选择的元素
const selected = engine.callTool('selection', 'getSelected')
console.log('Selected items:', selected)
// 清空所有选择
engine.callTool('selection', 'clearSelection')
`$3
`typescript
// 获取插件数据
const selectionData = engine.getPluginData('selection')// 注册新规则
const unregister = selectionData.registerRules([
{
type: 'edge',
className: 'edge-wrapper',
idGetter: element => element.getAttribute('data-edge-id') || '',
activeClassName: 'edge-selected',
},
])
// 启用/禁用规则
selectionData.setRuleEnabled('edge', false)
// 设置重叠模式
selectionData.setElementOverlap('invert') // 'keep' | 'drop' | 'invert'
// 取消注册规则
unregister()
`$3
`typescript
class MyPlugin extends BasePlugin {
@inject.selection.selected()
selected!: SelectionSelectedItem[] @subscribe.selection.selected()
onSelectedChange(selected: SelectionSelectedItem[]) {
console.log('Selection changed:', selected)
}
}
`$3
`typescript
import { Canvas } from '@knotx/plugins-canvas'
import { Selection } from '@knotx/plugins-selection'const engine = new Engine({
plugins: [Canvas, Selection],
pluginConfig: {
canvas: {
minScale: 0.1,
maxScale: 3,
},
selection: {
enableDrag: true,
container: '.canvas-container', // 指定选择容器
},
},
})
`高级功能
$3
`typescript
const engine = new Engine({
plugins: [Selection],
pluginConfig: {
selection: {
rules: [
{
type: 'node',
className: 'node-wrapper',
idGetter: element => element.getAttribute('data-node-id') || '',
onSelected: (context) => {
const { element, type, id, isDragging, getSelectedElements, select, deselect } = context // 自定义选择逻辑
if (isDragging) {
// 拖拽选择时的逻辑
return true
}
// 单击选择时的逻辑
const selectedElements = getSelectedElements()
if (selectedElements.node && selectedElements.node.length > 0) {
// 已有选择,执行多选逻辑
return true
}
return true
},
},
],
},
},
})
`$3
`typescript
const engine = new Engine({
plugins: [Selection],
pluginConfig: {
selection: {
selectionAreaClassName: 'custom-selection-area',
},
},
})
``css
.custom-selection-area {
background: rgba(74, 144, 226, 0.1);
border: 2px dashed #4A90E2;
border-radius: 4px;
}
`文件目录结构
`
packages/plugins-selection/
├── src/
│ ├── selection.tsx # 主要实现文件
│ └── index.ts # 导出文件
├── dist/ # 构建输出目录
├── package.json # 包配置文件
├── build.config.ts # 构建配置
├── tsconfig.json # TypeScript 配置
├── eslint.config.mjs # ESLint 配置
└── CHANGELOG.md # 更新日志
``- selection.tsx:包含 Selection 插件的主要实现,包括选择区域管理、规则系统和事件处理
- index.ts:导出 Selection 类和相关类型定义
1. 性能考虑:大量元素时,选择操作可能影响性能,建议使用虚拟化或分页
2. 事件冲突:与其他交互插件(如拖拽)可能存在事件冲突,注意事件优先级
3. 内存管理:及时清理不需要的选择规则,避免内存泄漏
4. 浏览器兼容性:依赖现代浏览器的 DOM API,注意兼容性
MIT