前端桌面应用图像处理【免费下载链接】jspaint Classic MS Paint, ✨Extras项目地址https://gitcode.com/gh_mirrors/js/jspaint点击查看免费下载本篇指南以 jspaint 仓库内嵌的 Tracky Mouse 开源项目为核心系统讲解这套头部跟踪 鼠标控制无障碍方案它既是可嵌入任意 Web 应用的 JavaScript 库也是可下载的 Electron 桌面应用还是 JS Paint Eye Gaze Mode 背后的技术底座。读完本文你将掌握桌面应用的安装与使用、CLI 外部集成、Head Tracking / Dwell Clicking 两套 API 的完整配置与源码级原理以及这套 monorepo 的架构设计与发布流程。Tracky Mouse 是一个面向无障碍输入的开源项目通过摄像头跟踪你的头部动作来控制鼠标并内置驻留点击dwell clicker——光标在某处停留片刻即触发点击让无法或不方便使用鼠标的人可以动手不动手地操作电脑。它最初正是为了支撑 JS Paint 的 Eye Gaze Mode凝视模式而诞生的作者收到用户咨询如何调整 JS Paint 界面适配眼动追踪于是决定直接构建一个官方功能连驻留点击一起做进去。该项目位于当前仓库的 lib/tracky-mouse 目录下包含核心库、桌面应用、官网三个子包完整源码均可直接阅读。项目定位一个项目三种形态从 README 的项目定位可以看出Tracky Mouse 被设计成三位一体桌面应用desktop-app基于 Electron可下载安装后控制整个电脑的鼠标功能类似 eViacam 一类的头部跟踪软件JavaScript 库core可嵌入任意 Web 应用让网页拥有完整的面部鼠标UI 与驻留点击能力JS Paint 的 Eye Gaze Mode 就是它的落地场景浏览器扩展构想阶段README 中明确说明扩展仍处于设想阶段计划承担三件事——桥接桌面应用与 Web 应用避免在桌面应用中禁用驻留点击才能使用提供驻留点击的网页、为 Chrome OS 提供桌面应用等价能力、自动优化网页对手势/面部鼠标输入的友好度如防止菜单因悬停关闭、放大元素等。这种共享同一套核心代码的形态意味着对核心库的任何改进可以同时惠及桌面应用、Web 库与未来的扩展三个产品而库的存在也让用户能在网页里立刻体验完整的面部鼠标 UI从而对头部跟踪产生兴趣。项目还设想在三个产品之间导出/导入甚至同步设置项。桌面应用安装、使用与故障排查安装方式Windows下载官方安装包并运行安装程序即可安装包通过 Squirrel 安装器分发electron-main.js 中通过app.setAppUserModelId(io.isaiahodhner.tracky-mouse)注册应用身份并处理安装/卸载时的快捷方式与 PATH 修改。macOS / LinuxREADME 说明由于 Electron Forge 打包问题目前没有预编译二进制需要从源码运行详见下文开发环境一节。使用前的环境准备面部要有充足的光线把台灯放在显示器旁边往往效果显著背光back-lighting会带来麻烦尤其是使用中头部前后移动遮挡光源时。摄像头应居中正对头部坐姿舒适时整个头部完全可见。开始使用点击Start按钮开始移动鼠标与点击也可使用键盘快捷键F9。桌面应用里 F9 是全局快捷键——即使应用窗口不在前台也能生效。这一点在源码中有明确印证electron-main.js 通过globalShortcut.register(F9, ...)注册注册失败时会弹出错误提示框。驻留点击光标在一个位置停留dwell即触发点击。想避免误点就必须持续移动头部或按 F9 暂停应用。使用技巧与行为细节调整设置直到能较准确地把鼠标移动到屏幕边缘。光标感觉偏移时把头部移到光标碰到屏幕边缘的位置即可重新校准。头部转动和平移左右、上下、前后都会带动鼠标。一个细节摄像头位于头部上方时前倾通常使指针向下移动摄像头在头部下方时前倾通常使指针向上移动。手动接管manual takeback桌面应用允许你直接移动鼠标夺回控制权暂停摄像头控制待鼠标停止移动一段时间后自动恢复。从 electron-main.js 可以看到其实现思路setMouseLocation是异步的因此用mousePosHistory维护最近 5000ms 内程序设置过的鼠标位置队列在move-mouse事件处理中L410-L453每次移动前先getMouseLocation()取回当前位置与历史队列比较距离超过thresholdToRegainControl 10像素就判定为手动移动暂停摄像头控制并启动 2000ms 的regainControlForTime定时器鼠标静止后自动恢复。鼠标移动与点击最终由serenade-driver库的setMouseLocation/getMouseLocation/click完成electron-main.js点击时若开启swapMouseButtons左手用户则触发右键。故障排查清单摄像头画面全黑检查是否有隐私/防尘盖确认光线充足并在其他应用中验证摄像头是否正常。完全无法访问摄像头确认没有被其他应用占用点击应用内 Allow Camera Access 按钮外接摄像头可尝试拔插重连或重启电脑。Linux 上安装有时只需运行guvcview可能神奇地修复摄像头不出现的问题README 引用了 Linux Mint 论坛的讨论作为依据。自动对焦 / 自动亮度会造成跟踪中断建议关闭自动对焦并手动调焦关闭自动亮度后光线变化时需要手动调整亮度尤其房间有自然光时。多摄像头当前应用尚不支持选择摄像头需要禁用系统设置里的其他摄像头或拔掉外接摄像头以锁定目标摄像头。用 CLI 集成外部软件语音命令系统等场景Tracky Mouse 自带命令行接口任何能启动其他程序的程序典型如语音命令系统都可以通过它控制桌面应用。完整说明见 lib/tracky-mouse/CLI.md。安装 CLIWindows 上安装桌面应用时tracky-mouse命令自动安装。其他平台需要在.bashrc或对应 shell 配置文件中扩展PATH例如export PATH$PATH:/path/to/tracky-mouse/bin然后执行source ~/.bashrc或重启终端。命令用法usage: tracky-mouse [-h] [--start] [--stop] [-v] Control your mouse hands-free. This CLI controls the running Tracky Mouse app. Its meant for external programs like a voice command system to toggle Tracky Mouse and adjust settings on the fly. optional arguments: -h, --help show this help message and exit --start Start head tracking. --stop Stop head tracking. -v, --version Show the version number.--start/--stop分别开始与停止头部跟踪CLI 目前仅支持这两个动作README 说明未来将支持运行时修改设置。CLI 解析由 cli.js 中的argparse完成其中还以注释形式保留了--profile、--set、--adjust、--get的构想用于按配置档案加载、精确设置、相对调节、读取设置项并隐藏处理了 Squirrel 安装器传入的--squirrel-firstrun参数。从 electron-main.js 可以看到--start/--stop等参数只在应用已运行时受支持未运行时 CLI 会输出明确提示。CLI 与运行中应用的通信机制源码细节这是理解 CLI 如何控制正在运行的应用的关键应用通过app.requestSingleInstanceLock()获取单实例锁electron-main.js同时把arguments命令行参数和tempFilePath作为additionalData传入——因为 Electron 的second-instance事件自带的argv参数已知不可靠。当再次执行tracky-mouse --start时新进程拿不到锁成为第二实例触发主实例的second-instance事件L599-L735。主实例解析参数后若--start/--stop与当前状态不一致就向应用窗口发送shortcut事件模拟 F9 切换并把结果文本写入临时文件先写.tmp再 rename避免竞态条件。第二实例则轮询等待该临时文件出现将其内容流式转发到自己的标准输出后退出L75-L11610 秒超时则报错退出。--version有特殊处理输出 CLI 版本 正在运行应用的版本。添加到你的项目安装与基础接线安装核心库发布在 npm 上包名tracky-mouse版本 1.2.0core/package.jsonnpm install tracky-mouse完整 API 文档见 lib/tracky-mouse/core/README.md。脚本引入与依赖路径目前库仍以 script 标签方式使用core/package.json 中发布的files为tracky-mouse.js、tracky-mouse.css、facemesh.worker.js与lib/script srcpath/to/tracky-mouse/tracky-mouse.js/script随后必须告诉库从哪里加载相关文件路径不要带结尾斜杠TrackyMouse.dependenciesRoot path/to/tracky-mouse;同目录下的样式表也要引入link relstylesheet hrefpath/to/tracky-mouse/tracky-mouse.cssHead Tracking API从加载依赖到模拟指针移动Tracky Mouse 简化了头部跟踪的搭建但拿运动数据做什么需要你自己决定当前需要在页面上模拟鼠标/指针事件库尚未内置这一逻辑README 表示未来会内置因此需要定义回调TrackyMouse.onPointerMove(x, y)。以下代码可直接复制起步TrackyMouse.loadDependencies().then(function() { TrackyMouse.init(); // Pointer event simulation logic should be built into tracky-mouse in the future. // These simulated events connect the Tracky Mouse head tracker to the Tracky Mouse dwell clicker, // as well as any other pointermove/pointerenter/pointerleave handlers on the page. const getEventOptions ({ x, y }) { return { view: window, // needed so the browser can calculate offsetX/Y from the clientX/Y clientX: x, clientY: y, pointerId: 1234567890, // a special value so other code can detect these simulated events pointerType: mouse, isPrimary: true, }; }; let last_el_over null; TrackyMouse.onPointerMove (x, y) { const target document.elementFromPoint(x, y) || document.body; if (target ! last_el_over) { if (last_el_over) { const event new PointerEvent(pointerleave, Object.assign(getEventOptions({ x, y }), { button: 0, buttons: 1, bubbles: false, cancelable: false, })); last_el_over.dispatchEvent(event); } const event new PointerEvent(pointerenter, Object.assign(getEventOptions({ x, y }), { button: 0, buttons: 1, bubbles: false, cancelable: false, })); target.dispatchEvent(event); last_el_over target; } const event new PointerEvent(pointermove, Object.assign(getEventOptions({ x, y }), { button: 0, buttons: 1, bubbles: true, cancelable: true, })); target.dispatchEvent(event); }; });代码中通过document.elementFromPoint定位元素、在元素进出间派发pointerleave/pointerenter、随后派发pointermove特意使用pointerId: 1234567890特殊值让页面其他代码可以识别这是 Tracky Mouse 的模拟事件。API 逐项说明TrackyMouse.dependenciesRoot指向安装目录无结尾斜杠。TrackyMouse.loadDependencies([options])加载头部跟踪所需依赖驻留点击不需要它。可选参数statsJsboolean是否加载 stats.js 性能监控默认false。返回一个 Promise依赖加载完成后 resolve。TrackyMouse.init([element, options])初始化头部跟踪驻留点击不需要。会创建 UI新建div classtracky-mouse-ui追加到body或使用并修改传入的现有元素传入的元素应为空的div库会为其补上classtracky-mouse-ui。可选参数statsJsboolean默认false。返回带dispose方法的对象调用dispose()可移除 UI 并清理 Web Worker 与摄像头流。TrackyMouse.useCamera()请求摄像头权限并启动摄像头流。可选——也可以让用户点击界面里的大号 Allow Camera Access 按钮。TrackyMouse.onPointerMove(x, y)需要你来定义的回调x、y为当前鼠标位置像素用于模拟指针移动。Dwell Clicking API让驻留点击可配置化TrackyMouse.initDwellClicking(config)启动驻留点击器。所有参数均来自 core/README.md 的官方定义整理如下参数必填说明config.targets是CSS 选择器指定可被点击的元素其余元素一律忽略config.shouldDrag(el)否返回 true 表示该元素应被拖拽而非简单点击config.noCenter(el)否返回 true 表示该元素可在任意位置点击而非总在中心config.retarget否{ from, to, withinMargin }对象数组定义鼠标悬停在其他元素上时动态把悬停/点击目标改到另一元素的规则。from必填为被替换的原始元素可为 CSS 选择器、元素或返回是否应重定向的函数to必填为目标元素可为from的祖先/后代选择器、元素或返回目标元素或 null 表示忽略该元素的函数withinMargin可选为像素数表示鼠标距离to元素多少像素内视为悬停其上默认无穷大config.isEquivalentTarget(el1, el2)否返回 true 表示两个元素应视为同一控件的组成部分点击任一效果相同。相等的元素即使返回 false 也总是视为等价。用于防止系统把遮挡元素误判为独立控件而拒绝点击检测到遮挡时会闪烁红框提示config.dwellClickEvenIfPaused(el)否返回 true 表示即使驻留点击暂停也要点击该元素。典型用途是恢复驻留点击切换按钮——暂停时你总得能点它来恢复config.click({x, y, target})是对给定目标元素触发点击的函数config.beforeDispatch()否在派发指针事件前调用用于在事件处理器之外检测不可信的用户手势config.afterDispatch()否在派发指针事件后调用同上config.beforePointerDownDispatch()否在派发pointerdown事件前调用未来可能与beforeDispatch()合并config.afterReleaseDrag()否拖拽释放后调用未来可能与afterDispatch()合并返回值包含paused读写属性控制驻留点击是否暂停。配合config.dwellClickEvenIfPaused实现暂停/恢复按钮。dispose清理驻留点击器的方法。完整配置示例源自 JS Paint 的实际用法// This example is based off of how JS Paint uses the Tracky Mouse API. // Its simplified a bit, but includes various settings. const config { // The elements to click. Anything else is ignored. targets: button:not([disabled]), input, textarea, label, a, details summary, .radio-or-checkbox-wrapper, .drawing-canvas, .window:not(.maximized) .window-titlebar , // Filter for elements to drag. They must be included in the targets first. shouldDrag: (target) ( target.matches(.window-titlebar) || (target.matches(.drawing-canvas) current_tool.supports_drag) ), // Instead of clicking in the center of these elements, click at any point within the element. // This is useful for drag offsets, like for a window titlebar, // and position-based inputs like sliders or color pickers, or a drawing canvas. noCenter: (target) ( target.matches( input[typerange], .drawing-canvas, .window-titlebar ) ), // Nudge hovers near the edges of an element onto the element itself, // to make it easier to click on the element. // More specifically it makes it easier to click on the edge of an element, // useful for a drawing canvas. retarget: [ { from: .canvas-container, to: .drawing-canvas, withinMargin: 50 }, ], // Elements that are equivalent are considered the same control. // This is useful for forms if you want the label of a radio button or checkbox // to be highlighted together with the radio button or checkbox. isEquivalentTarget: (apparent_hover_target, hover_target) ( apparent_hover_target.closest(label) hover_target || apparent_hover_target.closest(.radio-or-checkbox-wrapper) hover_target ), // Allow dwell clicking on a Resume Dwell Clicking button, while paused. dwellClickEvenIfPaused: (target) ( target.matches(.toggle-dwell-clicking-button) ), // Define how to click on an element. click: ({ target, x, y }) { if (target.matches(input[typerange])) { // Special handling for sliders const rect target.getBoundingClientRect(); const vertical target.getAttribute(orient) vertical || (getCurrentRotation(target) ! 0) || rect.height rect.width; const min Number(target.min); const max Number(target.max); target.value ( vertical ? (y - rect.top) / rect.height : (x - rect.left) / rect.width ) * (max - min) min; target.dispatchEvent(new Event(input, { bubbles: true })); target.dispatchEvent(new Event(change, { bubbles: true })); } else { // Normal click target.click(); if (target.matches(input, textarea)) { target.focus(); } } }, // Handle untrusted gestures specially in external code. // Somewhere else, for example, you might do something like: // if (window.untrusted_gesture) { // // show download window // } else { // // show save file dialog with FS Access API // } // Recommended: use event.isTrusted instead, where possible. beforeDispatch: () { window.untrusted_gesture true; }, afterDispatch: () { window.untrusted_gesture false; }, // Some extra hooks for JS Paint, likely to be generalized in the future, // especially beforePointerDownDispatch which could be supplanted by passing an Event to beforeDispatch. beforePointerDownDispatch: () { window.pointers []; }, afterReleaseDrag: () { window.pointers []; }, }; const dwellClicker TrackyMouse.initDwellClicking(config); // dwellClicker.paused !dwellClicker.paused; // toggle // dwellClicker.dispose(); // clean up // Source: https://stackoverflow.com/a/54492696/2624876 function getCurrentRotation(el) { const st window.getComputedStyle(el, null); const tm st.getPropertyValue(-webkit-transform) || st.getPropertyValue(-moz-transform) || st.getPropertyValue(-ms-transform) || st.getPropertyValue(-o-transform) || st.getPropertyValue(transform) || none; if (tm ! none) { const [a, b] tm.split(()[1].split())[0].split(,); return Math.round(Math.atan2(a, b) * (180 / Math.PI)); } return 0; }这个示例体现了几个关键设计思想滑块特判click回调对input[typerange]按坐标换算取值支持垂直滑块与旋转变换派发input/change事件普通元素则target.click()输入类元素额外focus()。不可信手势检测beforeDispatch/afterDispatch用于在事件处理器之外标记不可信手势官方建议能用时优先用event.isTrusted。等价目标与重定向isEquivalentTarget让单选/复选的 label 与控件视为一体retarget让画布容器边缘 50px 内的悬停吸附到画布上方便点中画布边缘。弃用的清理方法TrackyMouse.cleanupDwellClicking()已弃用自 1.2.0 起应改为调用initDwellClicking()返回对象的dispose()方法。旧方法仍会停止驻留点击器且已修复为可处理多个驻留点击器实例。软件架构从 monorepo 到双渲染进程的桌面端设计README 的 Software Architecture 一节 完整描述了整体架构结合源码可以进一步拆解如下。仓库结构三包 monorepolib/tracky-mouse/ ├── core/ # 核心库tracky-mouse.js、tracky-mouse.css、facemesh.worker.js、lib/ 依赖 ├── desktop-app/ # Electron 桌面应用src/electron-main、src/screen-overlay.js 等 └── website/ # 官网含 demo.js、index.html、eval-is-evil.html根 package.json 是私有包承载共享脚本npm run website/npm run desktop-app等通过cd pkg 包装的in-website、in-desktop-app、in-core脚本进入子包执行命令tracky-mouse的 bin 指向 desktop-app/src/tracky-mouse-bin.js它用spawnSync启动 Electron 并透传参数。项目曾尝试 npm workspaces但与 Electron Forge 打包不兼容故放弃采用上述手工脚本方案README 明确记录了这一取舍。core 的第三方依赖与安全处理核心库使用三个第三方库完成人脸与点跟踪jsfeatMIT 许可用于点跟踪clmtrackr.jsMIT 许可快速轻量但精度一般的人脸跟踪facemeshMediaPipe Facemesh TensorFlow.jsApache License 2.0高精度人脸跟踪一旦加载完成就取代 clmtrackr.js。一个值得注意的实现细节是CSP 安全为了在 Content Security Policy 中免去unsafe-eval项目必须消除 clmtrackr.js 中eval及Function构造的使用。解决方案是 core/lib/no-eval.js——用自定义函数覆盖eval只处理 clmtrackr.js 里那几个特定场景的eval调用。这个文件由 website/eval-is-evil.html 工具生成运行时对eval插桩收集 clmtrackr.js 尝试求值的代码后自动生成。如果你手动引入依赖不通过loadDependencies()必须额外引入no-eval.js通过loadDependencies()则自动包含。网站部署官网在开发期用符号链接引用核心库与共享资源images部署时执行npm run in-website -- npm run deploy先用cp -rL解引用符号链接再用gh-pages包发布到 GitHub Pages。README 说明原因是GitHub Pages 虽支持符号链接但当docs作为站点根目录时不支持指向docs之外的路径所以需要部署脚本若把网站文件放仓库根目录则可以省去。桌面应用应用窗口控制移动屏幕覆盖层控制点击桌面应用是这套架构中最有趣的部分README 直言其架构有点搞笑但它确实高效复用了代码Electron 应用是多进程程序主进程创建浏览器窗口渲染进程渲染窗口内容。Tracky Mouse 桌面应用有两个渲染进程主应用窗口app window与屏幕覆盖窗口screen overlay window。覆盖窗口是全屏、透明、置顶、不可交互的electron-main.js 中以fullscreen、transparent、alwaysOnTop、setIgnoreMouseEvents(true)等选项创建其唯一视觉职责是用一个收缩的圆圈预览驻留点击。传统理智的架构会把覆盖窗口做成纯视觉输出状态放在主进程或主渲染进程。但作者已经有现成的驻留点击器代码希望库与桌面应用表现一致、共用同一套计时逻辑和圆圈绘制于是直接把整个驻留点击器含业务逻辑嵌入覆盖窗口——反正渲染一个圆圈本来就承载了一整个页面Electron 下谈不上高效。最终架构是应用窗口控制鼠标移动覆盖窗口控制鼠标点击。桌面端确实需要一个铺满屏幕的隐形大按钮好让驻留点击器以为有东西可点。这一设计在 screen-overlay.js 中有直接证据脚本创建了一个覆盖全屏的透明button idbutton-that-takes-up-the-entire-screenL5-L14随后TrackyMouse.initDwellClicking({ targets: #button-that-takes-up-the-entire-screen, noCenter: ..., click: ({x, y}) electronAPI.mouseClick(x, y) })L16-L22——驻留点击器被原样复用点击时经 preload 暴露的electronAPI通知主进程真正移动并点击系统鼠标。onChangeDwellClicking回调L42-L71还会根据主进程下发的是否启用、是否手动接管、摄像头诊断状态切换覆盖层的显示文案与样式类。README 补充说明图中未画出的一点两个渲染进程都各有preload 脚本preload-app-window.js、preload-screen-overlay.js它们比渲染进程其余代码拥有更高权限所有系统功能访问都经过 preload 中转。此外桌面端设置持久化由主进程完成设置存于用户数据目录下的tracky-mouse-settings.json带formatName/formatVersion校验与升级机制electron-main.js支持从 UI 通过 IPC 增量更新。开发环境搭建与调试开发设置从源码运行Windows 用户克隆前务必设置git config --global core.symlinks true否则符号链接会出问题。克隆仓库后安装 Node.js在项目根目录运行npm install网站web UI / 库的演示npm run in-website -- npm install # 安装 website 子包依赖 npm run website # 启动开发服务器文件变更自动刷新桌面应用npm run in-desktop-app -- npm install npm run desktop-app # 启动应用测试 CLInpx tracky-mouse --help或npm link让tracky-mouse全局可用注意可能与已安装的应用冲突。若想走完整的 Electron Forge 链路测试 CLI需要npm run desktop-app -- -- -- --help——README 特意解释了这一长串--参数依次穿透 npm、子目录内的 npm、Electron Forge 三层每层工具都有各自的--help与--透传机制。构建分发版npm run in-desktop-app -- npm run make构建产物在desktop-app/out/目录。核心库本身暂不使用 npm 依赖依赖直接放在core/lib目录也没有 npm scripts。调试仓库提供了 VS Code launch 配置可分别调试 Chrome 中的 Web 版与 Electron 主进程。覆盖窗口调试从主窗口菜单栏选择View Toggle Developer Tools (Screen Overlay)。质量保证、发布流程与版本演进质量保证运行npm run lint检查拼写cspell与代码eslint问题。README 明确说明目前还没有测试。发布流程依据 README 的 Release Process 章节运行质量检查npm run lint更新 CLI 文档npm run update-cli-docs该脚本会自动执行tracky-mouse --help并把输出回填到 CLI.md 的HELP_OUTPUT代码块中见 package.json统一提升版本号在 bash 类 shell 中README 备注该步尚未跨平台自动化VERSION1.1.0 npm run in-core -- npm version $VERSION --no-git-tag-version npm run in-website -- npm version $VERSION --no-git-tag-version npm run in-desktop-app -- npm version $VERSION --no-git-tag-version npm version $VERSION --no-git-tag-version更新 CHANGELOG.md核对所有重要变更已记录在 Unreleased 下方新增带版本号与日期的标题更新底部用于版本对比的链接并在 Unreleased 下加一行 No changes here yet.更新下载链接README.md 与 website/index.html 中的 release 下载路径README 给出了基于 Node 的正则替换脚本。在所有支持的平台上执行npm run in-desktop-app -- npm run make构建桌面应用必须在提升版本号之后、发布库之前。创建desktop-app/.env并写入GITHUB_TOKEN...需有创建 release 的内容权限执行npm run in-desktop-app -- npm run publish自动上传分发文件把 changelog 条目粘贴进 release 草稿说明安装并实测安装版应用。提交、打标签并推送git add . git commit -m Release $VERSION git tag v$VERSION git push git push origin tag v$VERSION发布库到 npmnpm run in-core -- npm publish --dry-run预览后npm run in-core -- npm publish。发布 GitHub release 草稿最后随时可做但随版本发布更佳执行npm run in-website -- npm run deploy部署官网。版本演进要点CHANGELOG.md1.0.02021-05-20基于 Clmtrackr、Facemesh、jsfeat 的头部跟踪驻留点击器 API 从 JS Paint 提取并泛化Electron 桌面应用尚未打包分发。1.1.02024-10-20新增 Start/Stop 按钮桌面应用同时切换驻留点击Web 库中驻留点击独立设置、不受该按钮与 F9 控制桌面应用支持驻留点击、设置持久化、导入导出设置、记忆窗口位置、手动接管恢复控制面向不同摄像头失败场景的友好错误处理命令行接口--start/--stopAPI 文档与官网参数校验beforeDispatch/afterDispatch、beforePointerDownDispatch/afterReleaseDrag回调initDwellClicking返回{paused}软件默认启动时禁用避免安装器无人值守启动后立即乱点。1.2.02024-12-17cleanupDwellClicking()弃用改用dispose()UI 默认不再附带 stats.js 性能监控可通过{statsJs: true}显式开启init()与initDwellClicking()均返回带dispose()的对象修复cleanupDwellClicking()对多个驻留点击器的处理。结语从 JS Paint 的 Eye Gaze Mode 看这套方案的适用场景Tracky Mouse 的诞生动机README 的 Why did I make this? 一节本身就是最好的使用场景说明有人写信询问如何让 JS Paint 的界面适配眼动追踪放大调色板、隐藏无关 UI 等作者决定更进一步把面部鼠标做成官方功能并内置驻留点击随后又因购买眼动仪过于昂贵、eViacam 在他的电脑上无法正常工作转而亲自开发跨平台头部跟踪软件。项目中 JS Paint 的 Eye Gaze Mode 相关实现位于 src/eye-gaze-mode.jsREADME 提到它未来可能改名为 Hands-Free Mode 或 Facial Mouse Mode。无论你是想在网页里为无障碍用户提供头部移动 驻留点击的完整交互核心库 API还是想让你开发的任何桌面软件都能被面部鼠标操作桌面应用 CLI本文覆盖的架构、API 与开发流程都能让你快速上手桌面应用架构中应用窗口管移动、覆盖窗口管点击、大按钮喂给驻留点击器的设计也是复用库代码于桌面环境的绝佳参考样例。赞分享前端桌面应用图像处理【免费下载链接】jspaint Classic MS Paint, ✨Extras项目地址https://gitcode.com/gh_mirrors/js/jspaint点击查看免费下载相关推荐Tracky Mouse CLI 命令行接口实战用外部程序与语音指令控制头部追踪桌面应用Tracky Mouse CLI 命令行接口实战用外部程序与语音指令控制头部追踪桌面应用 Tracky Mouse 是一款通过头部移动来控制电脑鼠标的桌面应用前端桌面应用图像处理Mac Mouse Fix无障碍焦点设置优化界面导航的选项Mac Mouse Fix无障碍焦点设置优化界面导航的选项 无障碍功能痛点与解决方案 你是否曾在使用Mac时遇到鼠标操作不便的问题尤其是当系统焦点无法正确响桌面应用系统编程Mac Mouse Fix无障碍键盘控制终极指南完全用键盘配置鼠标Mac Mouse Fix无障碍键盘控制终极指南完全用键盘配置鼠标 Mac Mouse Fix是一款强大的开源软件能够让你的鼠标变得更加好用。这款软件提供了桌面应用系统编程上一篇技术深潜解锁Windows隐藏功能的专业图形化工具下一篇LavinMQ 开源项目安装与使用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
