Viewer 是bpmn.js的只读模式,用于加载和展示流程图。本文讲解Viewer的核心功能——加载XML、缩放、导航、高亮与选中,以及常见的交互场景。
Viewer的初始化与基础加载
创建实例
1 2 3 4 5 6 7 8 9 10 11 12 13
| const viewer = new BpmnJS({ container: '#canvas' });
viewer.importXML(bpmnXml).then(() => { console.log('✓ 流程图加载成功'); const canvas = viewer.get('canvas'); canvas.zoom('fit-viewport'); }).catch(err => { console.error('✗ 加载失败:', err.message); });
|
错误处理
加载可能失败的常见原因:
1 2 3 4 5 6 7 8 9 10 11
| viewer.importXML(bpmnXml) .then(() => { }) .catch(err => { console.error('XML格式错误:', err); showErrorDialog(err.message); });
|
视图控制:缩放与导航
缩放操作
1 2 3 4 5 6 7 8 9 10 11 12
| const canvas = viewer.get('canvas');
canvas.zoom('fit-viewport');
canvas.zoom(1.0); canvas.zoom(1.5); canvas.zoom(0.5);
const currentZoom = canvas.zoom();
|
视图导航
1 2 3 4 5 6 7 8
| const canvas = viewer.get('canvas');
const element = viewer.get('elementRegistry').get('TaskId_123'); canvas.viewbox(element);
canvas.zoom('fit-viewport');
|
元素查询与高亮
获取元素
1 2 3 4 5 6 7 8 9 10 11
| const registry = viewer.get('elementRegistry');
const element = registry.get('Task_1');
const allElements = registry.getAll();
const tasks = allElements.filter(el => el.type === 'bpmn:UserTask'); const gateways = allElements.filter(el => el.type === 'bpmn:Gateway');
|
选中与高亮
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const selection = viewer.get('selection'); const canvas = viewer.get('canvas');
selection.select(element);
selection.deselect();
canvas.addMarker(element, 'highlight'); canvas.removeMarker(element, 'highlight');
canvas.addMarker(element, 'selected'); canvas.addMarker(element, 'approved'); canvas.addMarker(element, 'rejected');
|
自定义高亮样式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <style> .djs-element.highlight { background: #f0f0f0 !important; outline: 2px solid #ffc107; } .djs-element.approved { background: #e8f5e9 !important; outline: 2px solid #4caf50; } .djs-element.rejected { background: #ffebee !important; outline: 2px solid #f44336; } </style>
<script> canvas.addMarker(approveTask, 'approved'); canvas.addMarker(rejectTask, 'rejected'); </script>
|
流程追踪:高亮执行路径
场景:展示一个订单在流程中的执行位置。
1 2 3 4 5 6 7 8 9 10 11 12
| const currentTask = registry.get('ApproveTask_1'); const path = ['StartEvent_1', 'ApproveTask_1'];
path.forEach(id => { const element = registry.get(id); canvas.addMarker(element, 'executed'); });
canvas.addMarker(currentTask, 'current-task');
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <style> .djs-element.executed { background: #c8e6c9 !important; } .djs-element.current-task { background: #fff9c4 !important; outline: 3px solid #fbc02d; animation: pulse 1.5s infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.7; } } </style>
|
事件监听
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const eventBus = viewer.get('eventBus');
eventBus.on('element.click', function(event) { const element = event.element; console.log('点击了:', element.id, '类型:', element.type); showProperties(element); });
eventBus.on('selection.changed', function(event) { const newSelection = event.newSelection; console.log('选中元素个数:', newSelection.length); });
eventBus.on('element.dblclick', function(event) { console.log('双击了:', event.element.id); });
|
常见场景:流程审计
需求:加载流程XML,显示某个订单的执行历史与当前状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| async function loadProcessWithHistory(processXml, executionHistory) { await viewer.importXML(processXml); viewer.get('canvas').zoom('fit-viewport'); const registry = viewer.get('elementRegistry'); const canvas = viewer.get('canvas'); executionHistory.forEach((step, index) => { const element = registry.get(step.elementId); if (!element) return; if (index < executionHistory.length - 1) { canvas.addMarker(element, 'executed'); } else { canvas.addMarker(element, 'current-task'); } }); viewer.get('eventBus').on('element.click', (event) => { const el = event.element; const history = executionHistory.find(h => h.elementId === el.id); if (history) { showExecutionDetails(el, history); } }); }
const bpmnXml = '...'; const history = [ { elementId: 'StartEvent_1', status: 'completed', time: '2025-12-24 10:00' }, { elementId: 'ApproveTask_1', status: 'active', time: '2025-12-24 10:05' } ];
loadProcessWithHistory(bpmnXml, history);
|
Viewer API速查表
| 方法 |
用途 |
importXML(xml) |
加载BPMN XML |
get('canvas') |
获取画布 |
get('elementRegistry') |
获取元素注册表 |
get('selection') |
获取选中管理器 |
get('eventBus') |
获取事件总线 |
canvas.zoom('fit-viewport') |
自动适配视窗 |
canvas.addMarker(el, class) |
添加CSS类高亮 |
selection.select(el) |
选中元素 |
selection.deselect() |
取消选中元素 |
小结
掌握Viewer:
- ✓ importXML 加载流程
- ✓ canvas 操作视图与缩放
- ✓ elementRegistry 查询元素
- ✓ 通过 marker 与 CSS 高亮显示
- ✓ eventBus 监听交互事件
便能构建专业的流程审查与追踪界面。
参考资料