@knotx/plugins-selection
v0.5.8
Published
Selection Plugin for Knotx
Readme
@knotx/plugins-selection
选择插件,为 KnotX 提供元素选择功能。
安装
npm install @knotx/plugins-selection概述
Selection 插件为 KnotX 提供了强大的元素选择功能,支持鼠标框选、键盘操作和程序化选择。该插件基于 @knotx/viselect 库实现,提供了灵活的选择规则和丰富的选择事件。
实现原理
Selection 插件的核心实现原理:
- 选择区域管理:使用
@knotx/viselect库创建选择区域,支持拖拽选择 - 规则系统:通过规则系统定义不同类型元素的选择行为
- 事件处理:提供完整的选择事件生命周期管理
- 状态同步:与画布变换状态同步,确保选择区域的准确性
依赖关系
核心依赖
@knotx/core:提供基础插件架构@knotx/decorators:提供装饰器支持@knotx/viselect:提供选择区域功能
插件依赖
@knotx/plugins-canvas:获取画布变换状态和容器信息(可选)
API 文档
主要类
Selection
选择插件的主要类,继承自 BasePlugin。
export class Selection extends BasePlugin<'selection', SelectionConfig> {
name = 'selection' as const
}配置选项
SelectionConfig
export interface SelectionConfig {
/** 选择区域的类名 */
selectionAreaClassName?: string
/** 是否启用拖拽选择 */
enableDrag?: boolean
/** 选择规则 */
rules?: SelectionRule[]
/** 是否禁用默认规则 */
disableDefaultRules?: boolean
/** 选择容器 */
container?: string
}SelectionRule
export interface SelectionRule {
/** 资源类型 */
type: string
/** 元素的类名 */
className: string
/** ID 获取函数 */
idGetter: (element: Element) => string
/** 激活状态的类名 */
activeClassName?: string
/** 选择回调函数 */
onSelected?: (context: SelectionContext) => boolean
/** 数据选择器类型 */
dataSelectorType?: string
/** 是否启用规则 */
enabled?: boolean
}插件数据 (PluginData)
Selection 插件提供以下数据:
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
}
}插件工具 (PluginTools)
Selection 插件提供以下工具方法:
interface PluginTools {
selection: {
select: (items: SelectionSelectedItem[]) => void
deselect: (items: SelectionSelectedItem[]) => void
getSelected: () => SelectionSelectedItem[]
clearSelection: () => void
}
}类型定义
SelectionSelectedItem
export interface SelectionSelectedItem {
type: string
id: string
}使用示例
基本用法
import { Selection } from '@knotx/plugins-selection'
const engine = new Engine({
plugins: [Selection],
pluginConfig: {
selection: {
enableDrag: true,
},
},
})自定义选择规则
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 表示允许选择
},
},
],
},
},
})程序化选择
// 选择特定元素
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')动态管理选择规则
// 获取插件数据
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()监听选择变化
class MyPlugin extends BasePlugin {
@inject.selection.selected()
selected!: SelectionSelectedItem[]
@subscribe.selection.selected()
onSelectedChange(selected: SelectionSelectedItem[]) {
console.log('Selection changed:', selected)
}
}与 Canvas 插件集成
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', // 指定选择容器
},
},
})高级功能
自定义选择行为
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
},
},
],
},
},
})选择区域样式自定义
const engine = new Engine({
plugins: [Selection],
pluginConfig: {
selection: {
selectionAreaClassName: 'custom-selection-area',
},
},
}).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 类和相关类型定义
注意事项
- 性能考虑:大量元素时,选择操作可能影响性能,建议使用虚拟化或分页
- 事件冲突:与其他交互插件(如拖拽)可能存在事件冲突,注意事件优先级
- 内存管理:及时清理不需要的选择规则,避免内存泄漏
- 浏览器兼容性:依赖现代浏览器的 DOM API,注意兼容性
许可证
MIT
