定制Forge Viewer工具:实现Ctrl+拖拽框选及单击累加多选
解决方案:Control键组合的累加多选与框选兼容实现
问题分析
当前实现的核心矛盾在于:在handleKeyDown中通过返回true阻止事件传播,虽能保留Control+单击的累加多选,但阻断了后续鼠标拖拽事件的触发逻辑,导致无法激活框选工具。核心问题点:
- 错误地在
handleKeyDown阶段就决定是否阻止事件传播,未结合后续鼠标操作(单击/拖拽)动态处理 isDragging的状态更新时机不合理,未区分“鼠标按下”和“产生拖拽动作”两个状态
修正后的实现代码
/** * Custom forge viewer tool to restrict box-selection to ctrl key + mouse drag action * @param viewer Reference to the forge viewer instance */ export const getCustomBoxSelectionTool = (viewer) => { if (!viewer?.toolController) return null; let isMouseDown = false; let hasMoved = false; const boxSelectionTool: NonNullable<CustomToolType> = { active: false, getName: () => 'custom-box-selection', getNames: () => ['custom-box-selection'], activate: async () => { boxSelectionTool.active = true; // 初始禁用默认框选工具,由自定义逻辑控制激活时机 viewer.toolController.deactivateTool('box-selection'); }, deactivate: () => { boxSelectionTool.active = false; viewer.toolController.activateTool('box-selection'); }, getPriority: () => 10, // 提高优先级,确保先处理自定义工具逻辑 handleKeyDown: (event) => { // 不阻止事件传播,仅在拖拽状态下激活框选 if (event.ctrlKey && isMouseDown && hasMoved) { viewer.toolController.activateTool('box-selection'); } return false; // 保留默认累加多选逻辑的事件传播 }, handleKeyUp: () => { viewer.toolController.deactivateTool('box-selection'); hasMoved = false; return false; }, handleButtonDown: (_event, button) => { if (button === 0) { isMouseDown = true; hasMoved = false; // 鼠标按下时禁用框选,确保单击行为是累加多选 viewer.toolController.deactivateTool('box-selection'); } return false; }, handleButtonUp: (_event, button) => { if (button === 0) { isMouseDown = false; // 松开鼠标后重置状态,禁用框选 viewer.toolController.deactivateTool('box-selection'); } return false; }, handleMouseMove: (event) => { if (isMouseDown && event.ctrlKey) { hasMoved = true; viewer.toolController.activateTool('box-selection'); } return false; } }; return boxSelectionTool; };
关键改进点
- 状态变量优化:用
isMouseDown记录鼠标按下状态,hasMoved标记是否产生拖拽动作,精准区分单击与拖拽行为 - 取消事件传播拦截:所有事件处理函数返回
false,确保默认的Control+单击累加多选逻辑正常执行 - 动态控制框选工具:
- 鼠标按下时默认禁用框选,保证单击动作是累加多选
- 仅当
Control键按下 + 鼠标按下 + 鼠标移动三个条件同时满足时,才激活框选工具 - 松开鼠标或Control键时立即禁用框选,重置状态
- 提高工具优先级:将优先级设为10,确保自定义工具先于默认工具处理事件,避免逻辑冲突
验证逻辑
- Control+单击:鼠标按下后无移动动作,保留默认累加多选行为
- Control+拖拽:鼠标按下后产生移动,自动激活框选工具执行框选逻辑
- 松开Control键/鼠标:立即终止框选,恢复初始状态
内容的提问来源于stack exchange,提问作者Michael Rayner
相关产品推荐
相关产品推荐

