You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

定制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;
};

关键改进点

  1. 状态变量优化:用isMouseDown记录鼠标按下状态,hasMoved标记是否产生拖拽动作,精准区分单击与拖拽行为
  2. 取消事件传播拦截:所有事件处理函数返回false,确保默认的Control+单击累加多选逻辑正常执行
  3. 动态控制框选工具:
    • 鼠标按下时默认禁用框选,保证单击动作是累加多选
    • 仅当Control键按下 + 鼠标按下 + 鼠标移动三个条件同时满足时,才激活框选工具
    • 松开鼠标或Control键时立即禁用框选,重置状态
  4. 提高工具优先级:将优先级设为10,确保自定义工具先于默认工具处理事件,避免逻辑冲突

验证逻辑

  • Control+单击:鼠标按下后无移动动作,保留默认累加多选行为
  • Control+拖拽:鼠标按下后产生移动,自动激活框选工具执行框选逻辑
  • 松开Control键/鼠标:立即终止框选,恢复初始状态

内容的提问来源于stack exchange,提问作者Michael Rayner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 10:38:13