原生鸿蒙像素画板实战 22:快捷键与鼠标交互

手机像素画板的核心输入是触控,大屏和二合一设备却能提供键盘、鼠标和滚轮。把桌面快捷键原封不动搬到手机上,只会让界面多出一套无用设置;反过来完全忽略键盘,又会让大屏编辑效率很低。bitArt 的处理方式是把快捷键配置持久化,但只在大屏布局且开关允许时响应;鼠标滚轮则仍归到画布视口逻辑,围绕当前光标缩放。

++快捷键配置可以保存,但响应范围必须受布局约束++

快捷键实现最常见的问题有两个。第一,直接在页面里判断 keyCode,随着撤销、导出、工具切换和弹窗关闭不断增加,代码很快无法维护;第二,在设置弹窗、项目命名输入框或素材库打开时仍响应 B、E、S 等单键,用户输入文本会意外切换工具或触发导出。

++按键解析和命令执行为什么要拆开++

键盘和鼠标应该增强现有工作流,而不是制造另一套编辑器状态。所有输入最终仍要回到同一份工具、历史和视口规则。

++按键先解析成动作,再决定怎样执行++

KeyboardShortcutService 维护动作列表、默认绑定、格式化显示、冲突移除和查找。EditorShortcutActionService 则负责根据 KeyEvent 更新 Ctrl、Shift 状态,判断是否处于大屏、是否正在录制快捷键、是否允许单键,再返回 actionId。真正的执行交给工作流:工具动作映射到 activeTool,缩放动作映射到视口,关闭动作按叠层优先级处理。

默认方案既支持 Ctrl+Z、Ctrl+Y、Ctrl+Shift+Z 这类组合,也支持 B、E、F、P、M 等工具键。冲突分配时 withAssignedShortcut 会从其他动作移除相同绑定,避免一个按键同时触发两个命令。

默认快捷键只是配置数据,真正是否响应还需要后续的布局和面板状态判断。

复制代码
static createDefaultShortcuts(): KeyboardShortcutSettings {
  const result: KeyboardShortcutSettings = {};
  result.undo = [KeyboardShortcutService.createBinding(KeyCode.KEYCODE_Z, true, false)];
  result.redo = [KeyboardShortcutService.createBinding(KeyCode.KEYCODE_Y, true, false),
    KeyboardShortcutService.createBinding(KeyCode.KEYCODE_Z, true, true)];
  result.pencil = [KeyboardShortcutService.createBinding(KeyCode.KEYCODE_B, false, false)];
  result.eraser = [KeyboardShortcutService.createBinding(KeyCode.KEYCODE_E, false, false)];
  result.fill = [KeyboardShortcutService.createBinding(KeyCode.KEYCODE_F, false, false)];
  result.closeOverlay = [KeyboardShortcutService.createBinding(KeyCode.KEYCODE_ESCAPE, false, false)];
  return result;
}

++单键快捷键要避开正在输入文字的面板++

按键处理先更新修饰键状态,再忽略仅有 Ctrl 或 Shift 的事件;随后根据事件和回退状态判断组合键。若正在录制快捷键,普通按键会被转成新的 binding;否则用 findActionId 搜索匹配项。对于不带 Ctrl 与 Shift 的动作,还要调用 canUseSingleKeyShortcuts,确保没有新建、项目管理、设置、颜色、主菜单、历史或素材面板处于打开状态。

复制代码
if (!EditorShortcutActionService.isLargeScreenShortcutEnabled(state.largeScreenLayout,
  state.keyboardShortcutsEnabled)) {
  const result = EditorShortcutActionService.createResult(state, false);
  result.shortcutCtrlDown = false;
  result.shortcutShiftDown = false;
  return result;
}
const actionId = KeyboardShortcutService.findActionId(nextState.keyboardShortcuts, event.keyCode,
  ctrlPressed, shiftPressed);
if (!ctrlPressed && !shiftPressed && actionId !== 'closeOverlay' &&
  !EditorShortcutActionService.canUseSingleKeyShortcuts(nextState)) return createResult(nextState, false);

++输入会话状态与快捷键配置分开保存++

快捷键状态包含开关、绑定表、正在编辑的动作和修饰键按下状态。它是项目可保存配置,但当前 Ctrl/Shift 按下状态是瞬态 UI 状态,不能持久化。大屏条件不满足时服务返回未处理结果,同时清理修饰键状态,手机界面不会因为外接键盘残留状态而出现异常。

快捷键绑定可以随项目保存,按下 Ctrl 或 Shift 则只属于当前输入会话,离开事件后不应残留。

复制代码
static withAssignedShortcut(settings: KeyboardShortcutSettings, actionId: string,
  binding: KeyboardShortcutBinding): KeyboardShortcutSettings {
  const normalized = KeyboardShortcutService.normalizeShortcuts(settings);
  const result: KeyboardShortcutSettings = {};
  for (const currentActionId of KeyboardShortcutService.ACTIONS.map((item) => item.id)) {
    const sourceBindings = normalized[currentActionId] ? normalized[currentActionId] : [];
    result[currentActionId] = currentActionId === actionId ? [KeyboardShortcutService.cloneBinding(binding)] :
      KeyboardShortcutService.removeMatchingBindings(sourceBindings, binding);
  }
  return result;
}

++大屏输入最容易和文本编辑冲突的情况++

  • 不要在所有窗口尺寸下响应单键快捷键,手机和文本输入面板必须有明确保护。
  • 重新绑定一个按键时要从其他动作移除冲突,不能让查找顺序决定谁"碰巧获胜"。
  • Ctrl、Shift 等修饰键需要有回退状态,不能只依赖某些设备不一定提供的事件查询接口。

鼠标和键盘不是另一套编辑器。它们最终仍调用已有的工具状态、撤销历史和视口约束。这样用户用 B 切到画笔、用滚轮缩放、用 Esc 关闭选区时,不会走出触控路径之外的分叉逻辑。输入方式增加了,数据源和业务规则没有增加。

++键盘输入先尊重当前焦点++

快捷键测试要把焦点场景列在第一位。先在画布空闲状态按 B、E、F、Ctrl+Z,再打开项目重命名、设置输入框、颜色输入框和素材面板重复按同一组键。正确结果不是所有地方都响应,而是只有没有文本输入和覆盖层的工作区响应单键。Esc 可以按叠层优先级关闭当前最高层界面,但也不能越过用户正在编辑的重要输入。

鼠标滚轮还要与快捷键分开验证。它不应因为某个快捷键被禁用就失效,而应始终由视口判断当前缩放和边界。在大屏用光标指向一处像素后滚动,目标像素应尽量留在指针下方;切回手机布局时,键盘动作停止,触控和视口规则仍保持原有行为。这样多输入设备共存时才不会出现一方覆盖另一方的意外。

++怎样确认快捷键只在正确场景响应++

快捷键检查需要在面板打开和布局切换时重复按键,确认保护条件真的生效。

  • 在大屏布局下验证 Ctrl+Z、Ctrl+Y、Ctrl+Shift+Z、保存、导出和常用工具键。

  • 打开设置、项目管理、颜色弹窗、素材库和文本输入后按 B、E、S,确认不会误触发单键命令。

  • 重新给两个动作分配相同按键,确认旧动作的绑定被移除且格式化显示正确。

  • 切换到手机布局或关闭快捷键开关,确认按键不再修改编辑器状态;滚轮缩放仍受视口边界约束。

    快捷键与鼠标检查记录
    大屏开启时组合键与工具键可用
    输入和弹窗打开时单键不误触发
    重新绑定自动去除冲突
    手机布局或关闭开关时快捷键保持无副作用

++快捷键功能的使用边界++

当前快捷键覆盖编辑器主动作,不尝试复刻桌面绘图软件的全部组合键、宏录制或系统级全局热键。它的目标是在键盘可用的大屏上减少常见操作的重复点击,同时不破坏手机上的触控主路径。

这一篇的重点是把键盘和鼠标接入现有编辑器规则,而不是另起一套行为。至此,11 到 22 篇补齐了工具、项目、素材和大屏输入这些支线,后续若继续扩展,更适合围绕新能力或真实设备回归再开新的系列。

相关推荐
●VON2 小时前
鸿蒙 PC Markdown 编辑器图片粘贴:从系统剪贴板到标准相对链接
华为·编辑器·harmonyos·鸿蒙
●VON2 小时前
鸿蒙 PC Markdown 编辑器外部修改检测:从文件指纹到冲突决策
华为·编辑器·harmonyos·鸿蒙
●VON2 小时前
鸿蒙 PC Markdown 编辑器十兆级大文档保护模式
华为·编辑器·harmonyos·鸿蒙
●VON2 小时前
鸿蒙 PC Markdown 编辑器三方冲突处理:本地缓冲区、磁盘版本与共同基线
网络·华为·编辑器·harmonyos·鸿蒙
listening7772 小时前
HarmonyOS 6.1 性能极致调优:从“流畅”到“极致”的SmartPerf深度剖析
华为·harmonyos
轻口味2 小时前
【大展鸿图】HarmonyOS DevEco Code 入门与最佳实
华为·harmonyos·鸿蒙·月更
●VON3 小时前
鸿蒙 PC Markdown 编辑器搜索选项响应式布局:220 vp 侧栏中的完整中文控件
服务器·华为·编辑器·harmonyos·鸿蒙
Helen_cai4 小时前
HarmonyOS ArkTS 实战:实现一个外出报备晚归登记应用
华为·harmonyos
fengxinzi_zack11 小时前
HarmonyOS应用开发实战:萌宠日记 - 健康分类数据隔离
harmonyos·鸿蒙