370 lines
16 KiB
Markdown
370 lines
16 KiB
Markdown
|
|
# 鼠标输入处理
|
|||
|
|
|
|||
|
|
<cite>
|
|||
|
|
**本文档引用的文件**
|
|||
|
|
- [inputremoting.js](file://client/src/inputremoting.js)
|
|||
|
|
- [inputdevice.js](file://client/src/inputdevice.js)
|
|||
|
|
- [mousebutton.js](file://client/src/mousebutton.js)
|
|||
|
|
- [pointercorrect.js](file://client/src/pointercorrect.js)
|
|||
|
|
- [sender.js](file://client/src/sender.js)
|
|||
|
|
- [memoryhelper.js](file://client/src/memoryhelper.js)
|
|||
|
|
- [register-events.js](file://client/public/videoplayer/js/register-events.js)
|
|||
|
|
- [main.js(视频播放器)](file://client/public/videoplayer/js/main.js)
|
|||
|
|
</cite>
|
|||
|
|
|
|||
|
|
## 目录
|
|||
|
|
1. [简介](#简介)
|
|||
|
|
2. [项目结构](#项目结构)
|
|||
|
|
3. [核心组件](#核心组件)
|
|||
|
|
4. [架构总览](#架构总览)
|
|||
|
|
5. [详细组件分析](#详细组件分析)
|
|||
|
|
6. [依赖关系分析](#依赖关系分析)
|
|||
|
|
7. [性能考量](#性能考量)
|
|||
|
|
8. [故障排查指南](#故障排查指南)
|
|||
|
|
9. [结论](#结论)
|
|||
|
|
10. [附录](#附录)
|
|||
|
|
|
|||
|
|
## 简介
|
|||
|
|
本文件聚焦于鼠标输入处理的技术文档,涵盖鼠标事件的捕获、转换与转发机制,包括鼠标移动、点击、滚轮等事件类型。文档详细说明鼠标坐标系统、按钮状态映射与事件数据结构,并给出时间戳同步、坐标变换与延迟补偿策略。同时提供具体代码路径示例,展示如何捕获鼠标事件、序列化为二进制消息并通过网络传输,在远端设备上进行重放。
|
|||
|
|
|
|||
|
|
## 项目结构
|
|||
|
|
该仓库包含客户端与服务端两部分。与鼠标输入直接相关的核心代码位于 client/src 与 client/public/videoplayer/js 目录中:
|
|||
|
|
- 输入设备建模与事件序列化:client/src/inputdevice.js
|
|||
|
|
- 输入远程转发与消息封装:client/src/inputremoting.js
|
|||
|
|
- 鼠标按钮常量定义:client/src/mousebutton.js
|
|||
|
|
- 坐标矫正与视频适配:client/src/pointercorrect.js
|
|||
|
|
- 本地事件监听与状态队列:client/src/sender.js
|
|||
|
|
- 内存位写入工具:client/src/memoryhelper.js
|
|||
|
|
- 前端事件注册与消息发送(另一套实现):client/public/videoplayer/js/register-events.js
|
|||
|
|
- 视频播放器入口与事件注册:client/public/videoplayer/js/main.js
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph TB
|
|||
|
|
subgraph "客户端"
|
|||
|
|
A["事件监听<br/>sender.js"]
|
|||
|
|
B["输入设备模型<br/>inputdevice.js"]
|
|||
|
|
C["远程转发与消息封装<br/>inputremoting.js"]
|
|||
|
|
D["坐标矫正<br/>pointercorrect.js"]
|
|||
|
|
E["内存位写入<br/>memoryhelper.js"]
|
|||
|
|
F["鼠标按钮常量<br/>mousebutton.js"]
|
|||
|
|
G["前端事件注册(替代实现)<br/>register-events.js"]
|
|||
|
|
end
|
|||
|
|
A --> B
|
|||
|
|
A --> D
|
|||
|
|
A --> C
|
|||
|
|
B --> E
|
|||
|
|
B --> F
|
|||
|
|
G --> |"注册鼠标/滚轮/触摸事件"| A
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [sender.js:14-188](file://client/src/sender.js#L14-L188)
|
|||
|
|
- [inputdevice.js:91-272](file://client/src/inputdevice.js#L91-L272)
|
|||
|
|
- [inputremoting.js:63-169](file://client/src/inputremoting.js#L63-L169)
|
|||
|
|
- [pointercorrect.js:6-124](file://client/src/pointercorrect.js#L6-L124)
|
|||
|
|
- [memoryhelper.js:1-28](file://client/src/memoryhelper.js#L1-L28)
|
|||
|
|
- [mousebutton.js:1-7](file://client/src/mousebutton.js#L1-L7)
|
|||
|
|
- [register-events.js:161-281](file://client/public/videoplayer/js/register-events.js#L161-L281)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [sender.js:14-188](file://client/src/sender.js#L14-L188)
|
|||
|
|
- [inputdevice.js:91-272](file://client/src/inputdevice.js#L91-L272)
|
|||
|
|
- [inputremoting.js:63-169](file://client/src/inputremoting.js#L63-L169)
|
|||
|
|
- [pointercorrect.js:6-124](file://client/src/pointercorrect.js#L6-L124)
|
|||
|
|
- [memoryhelper.js:1-28](file://client/src/memoryhelper.js#L1-L28)
|
|||
|
|
- [mousebutton.js:1-7](file://client/src/mousebutton.js#L1-L7)
|
|||
|
|
- [register-events.js:161-281](file://client/public/videoplayer/js/register-events.js#L161-L281)
|
|||
|
|
|
|||
|
|
## 核心组件
|
|||
|
|
- LocalInputManager:本地输入管理基类,负责事件分发与时间基准。
|
|||
|
|
- Sender:具体实现,注册鼠标/键盘/手柄/触摸事件,构建输入设备状态,派发 StateEvent/TextEvent。
|
|||
|
|
- Mouse/MouseState:鼠标设备与状态,包含位置、相对位移、滚轮、按钮位图等字段。
|
|||
|
|
- InputRemoting:将本地事件序列化为消息并转发给订阅者(如 RTC 数据通道)。
|
|||
|
|
- Message/NewEventsMsg/NewDeviceMsg:消息封装与序列化。
|
|||
|
|
- PointerCorrector:将页面坐标映射到视频画布坐标,处理留边距与缩放。
|
|||
|
|
- MemoryHelper:按位写入布尔状态,用于按钮位图。
|
|||
|
|
- MouseButton:按钮枚举。
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [inputremoting.js:9-49](file://client/src/inputremoting.js#L9-L49)
|
|||
|
|
- [inputremoting.js:63-169](file://client/src/inputremoting.js#L63-L169)
|
|||
|
|
- [inputdevice.js:91-272](file://client/src/inputdevice.js#L91-L272)
|
|||
|
|
- [sender.js:14-188](file://client/src/sender.js#L14-L188)
|
|||
|
|
- [pointercorrect.js:6-124](file://client/src/pointercorrect.js#L6-L124)
|
|||
|
|
- [memoryhelper.js:1-28](file://client/src/memoryhelper.js#L1-L28)
|
|||
|
|
- [mousebutton.js:1-7](file://client/src/mousebutton.js#L1-L7)
|
|||
|
|
|
|||
|
|
## 架构总览
|
|||
|
|
鼠标事件从 DOM 事件开始,经由 Sender 注册监听,转换为 MouseState,再包装为 StateEvent,通过 InputRemoting 序列化为 Message 并发送至远端。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant U as "用户"
|
|||
|
|
participant DOM as "DOM事件"
|
|||
|
|
participant S as "Sender"
|
|||
|
|
participant M as "Mouse/MouseState"
|
|||
|
|
participant PC as "PointerCorrector"
|
|||
|
|
participant IR as "InputRemoting"
|
|||
|
|
participant MSG as "Message/NewEventsMsg"
|
|||
|
|
participant NET as "网络/数据通道"
|
|||
|
|
U->>DOM : "鼠标移动/点击/滚轮"
|
|||
|
|
DOM->>S : "事件回调"
|
|||
|
|
S->>M : "queueEvent(event)"
|
|||
|
|
M-->>S : "currentState"
|
|||
|
|
S->>PC : "map(position)"
|
|||
|
|
PC-->>S : "矫正后坐标"
|
|||
|
|
S->>IR : "派发 StateEvent"
|
|||
|
|
IR->>MSG : "NewEventsMsg.create(stateEvent)"
|
|||
|
|
MSG-->>IR : "Message"
|
|||
|
|
IR->>NET : "发送 buffer"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [sender.js:121-129](file://client/src/sender.js#L121-L129)
|
|||
|
|
- [inputdevice.js:91-98](file://client/src/inputdevice.js#L91-L98)
|
|||
|
|
- [inputdevice.js:195-272](file://client/src/inputdevice.js#L195-L272)
|
|||
|
|
- [pointercorrect.js:20-40](file://client/src/pointercorrect.js#L20-L40)
|
|||
|
|
- [inputremoting.js:138-141](file://client/src/inputremoting.js#L138-L141)
|
|||
|
|
- [inputremoting.js:258-277](file://client/src/inputremoting.js#L258-L277)
|
|||
|
|
|
|||
|
|
## 详细组件分析
|
|||
|
|
|
|||
|
|
### 鼠标事件捕获与转换
|
|||
|
|
- 事件监听:在视频元素上注册 click/mousedown/mouseup/mousemove/wheel 回调。
|
|||
|
|
- 状态构建:将 MouseEvent/WheelEvent 转换为 MouseState,记录绝对坐标、相对位移、滚轮增量与按钮位图。
|
|||
|
|
- 按钮映射:使用位图存储左右中及其他扩展按钮状态,通过 MemoryHelper.writeSingleBit 写入。
|
|||
|
|
- 坐标矫正:使用 PointerCorrector 将页面坐标(clientX/Y)映射到视频画布坐标,考虑留边距与缩放。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TD
|
|||
|
|
Start(["事件到达"]) --> Type{"事件类型"}
|
|||
|
|
Type --> |mousemove| BuildMove["构建 MouseState<br/>position/delta/buttons"]
|
|||
|
|
Type --> |click/mousedown/mouseup| BuildBtn["构建 MouseState<br/>position/buttons"]
|
|||
|
|
Type --> |wheel| BuildWheel["构建 MouseState<br/>scroll"]
|
|||
|
|
BuildMove --> BtnMap["按钮位图写入"]
|
|||
|
|
BuildBtn --> BtnMap
|
|||
|
|
BuildWheel --> BtnMap
|
|||
|
|
BtnMap --> Correct["PointerCorrector.map(position)"]
|
|||
|
|
Correct --> Queue["派发 StateEvent"]
|
|||
|
|
Queue --> End(["完成"])
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [sender.js:121-129](file://client/src/sender.js#L121-L129)
|
|||
|
|
- [inputdevice.js:195-272](file://client/src/inputdevice.js#L195-L272)
|
|||
|
|
- [memoryhelper.js:7-20](file://client/src/memoryhelper.js#L7-L20)
|
|||
|
|
- [pointercorrect.js:20-40](file://client/src/pointercorrect.js#L20-L40)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [sender.js:31-49](file://client/src/sender.js#L31-L49)
|
|||
|
|
- [sender.js:121-129](file://client/src/sender.js#L121-L129)
|
|||
|
|
- [inputdevice.js:91-98](file://client/src/inputdevice.js#L91-L98)
|
|||
|
|
- [inputdevice.js:195-272](file://client/src/inputdevice.js#L195-L272)
|
|||
|
|
- [memoryhelper.js:7-20](file://client/src/memoryhelper.js#L7-L20)
|
|||
|
|
- [pointercorrect.js:20-40](file://client/src/pointercorrect.js#L20-L40)
|
|||
|
|
|
|||
|
|
### 鼠标坐标系统与按钮状态
|
|||
|
|
- 坐标系统
|
|||
|
|
- 绝对坐标:clientX/clientY 来源于 DOM 事件。
|
|||
|
|
- 相对位移:movementX/movementY 由浏览器提供;Y 方向取负以匹配常见坐标系。
|
|||
|
|
- 留边距与缩放:通过 PointerCorrector 的 contentRect 与 video 尺寸计算映射。
|
|||
|
|
- 按钮状态
|
|||
|
|
- 使用 16 字节位图存储多按钮状态,左/右/中/前进/后退分别对应不同位。
|
|||
|
|
- 通过 MemoryHelper.writeSingleBit 写入位图。
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [inputdevice.js:222-244](file://client/src/inputdevice.js#L222-L244)
|
|||
|
|
- [inputdevice.js:249-264](file://client/src/inputdevice.js#L249-L264)
|
|||
|
|
- [memoryhelper.js:7-20](file://client/src/memoryhelper.js#L7-L20)
|
|||
|
|
- [mousebutton.js:1-7](file://client/src/mousebutton.js#L1-L7)
|
|||
|
|
|
|||
|
|
### 事件数据结构与时序
|
|||
|
|
- InputEvent:统一事件头,包含类型、大小、设备 ID、时间戳。
|
|||
|
|
- StateEvent:封装 IInputState,携带状态格式与状态数据。
|
|||
|
|
- Message:封装 participant_id、type、length 与 data,作为网络传输单元。
|
|||
|
|
- 时间戳:LocalInputManager 提供基于秒的时间基准,Sender 在派发时使用 timeSinceStartup。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
classDiagram
|
|||
|
|
class InputEvent {
|
|||
|
|
+number type
|
|||
|
|
+number sizeInBytes
|
|||
|
|
+number deviceId
|
|||
|
|
+number time
|
|||
|
|
+buffer
|
|||
|
|
}
|
|||
|
|
class IInputState {
|
|||
|
|
+buffer
|
|||
|
|
+format
|
|||
|
|
}
|
|||
|
|
class MouseState {
|
|||
|
|
+float32 position[2]
|
|||
|
|
+float32 delta[2]
|
|||
|
|
+float32 scroll[2]
|
|||
|
|
+uint16 buttons
|
|||
|
|
+uint16 displayIndex
|
|||
|
|
+uint16 clickCount
|
|||
|
|
+buffer
|
|||
|
|
+format
|
|||
|
|
}
|
|||
|
|
class StateEvent {
|
|||
|
|
+baseEvent : InputEvent
|
|||
|
|
+stateFormat : number
|
|||
|
|
+stateData : ArrayBuffer
|
|||
|
|
+buffer
|
|||
|
|
}
|
|||
|
|
class Message {
|
|||
|
|
+number participant_id
|
|||
|
|
+number type
|
|||
|
|
+number length
|
|||
|
|
+ArrayBuffer data
|
|||
|
|
+buffer
|
|||
|
|
}
|
|||
|
|
MouseState ..|> IInputState
|
|||
|
|
StateEvent --> InputEvent : "组合"
|
|||
|
|
Message --> StateEvent : "承载"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [inputdevice.js:129-178](file://client/src/inputdevice.js#L129-L178)
|
|||
|
|
- [inputdevice.js:180-193](file://client/src/inputdevice.js#L180-L193)
|
|||
|
|
- [inputdevice.js:195-272](file://client/src/inputdevice.js#L195-L272)
|
|||
|
|
- [inputremoting.js:184-232](file://client/src/inputremoting.js#L184-L232)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [inputdevice.js:129-178](file://client/src/inputdevice.js#L129-L178)
|
|||
|
|
- [inputdevice.js:180-193](file://client/src/inputdevice.js#L180-L193)
|
|||
|
|
- [inputdevice.js:195-272](file://client/src/inputdevice.js#L195-L272)
|
|||
|
|
- [inputremoting.js:184-232](file://client/src/inputremoting.js#L184-L232)
|
|||
|
|
|
|||
|
|
### 网络传输与远端重放
|
|||
|
|
- 发送侧
|
|||
|
|
- InputRemoting 订阅 LocalInputManager 的事件,将 StateEvent 包装为 NewEventsMsg,再封装为 Message。
|
|||
|
|
- 通过订阅者(如 RTC 数据通道)发送二进制 buffer。
|
|||
|
|
- 接收侧
|
|||
|
|
- 远端需解析 Message,识别事件类型与状态格式,重建 MouseState 并应用到目标设备或渲染层。
|
|||
|
|
- 由于未在仓库中发现接收与重放的具体实现,建议遵循以下原则:
|
|||
|
|
- 使用与发送端一致的格式标识与字段顺序。
|
|||
|
|
- 使用时间戳进行本地重放缓冲与插值(见“性能考量”)。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant L as "本地 Sender"
|
|||
|
|
participant IR as "InputRemoting"
|
|||
|
|
participant CH as "数据通道"
|
|||
|
|
participant R as "远端接收器"
|
|||
|
|
L->>IR : "StateEvent"
|
|||
|
|
IR->>IR : "NewEventsMsg.create()"
|
|||
|
|
IR->>CH : "Message.buffer"
|
|||
|
|
CH-->>R : "二进制数据"
|
|||
|
|
R->>R : "解析格式/重建状态"
|
|||
|
|
R-->>R : "重放到目标设备"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [inputremoting.js:138-141](file://client/src/inputremoting.js#L138-L141)
|
|||
|
|
- [inputremoting.js:258-277](file://client/src/inputremoting.js#L258-L277)
|
|||
|
|
- [sender.js:170-182](file://client/src/sender.js#L170-L182)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [inputremoting.js:63-169](file://client/src/inputremoting.js#L63-L169)
|
|||
|
|
- [inputremoting.js:184-232](file://client/src/inputremoting.js#L184-L232)
|
|||
|
|
- [sender.js:170-182](file://client/src/sender.js#L170-L182)
|
|||
|
|
|
|||
|
|
### 坐标变换与延迟补偿策略
|
|||
|
|
- 坐标变换
|
|||
|
|
- 将 clientX/Y 减去元素边界矩形偏移,反转 Y 轴,减去留边距,再按内容矩形与视频尺寸比例映射。
|
|||
|
|
- 通过 PointerCorrector 的 contentRect 动态计算留边类型(水平/垂直)与尺寸。
|
|||
|
|
- 延迟补偿
|
|||
|
|
- 使用 timeSinceStartup 作为事件时间戳,远端可据此进行缓冲与插值,减少抖动。
|
|||
|
|
- 若网络存在抖动,可在接收端维护一个环形缓冲队列,按时间戳排序后重放。
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [pointercorrect.js:20-40](file://client/src/pointercorrect.js#L20-L40)
|
|||
|
|
- [pointercorrect.js:78-119](file://client/src/pointercorrect.js#L78-L119)
|
|||
|
|
- [sender.js:39-41](file://client/src/sender.js#L39-L41)
|
|||
|
|
- [sender.js:170-172](file://client/src/sender.js#L170-L172)
|
|||
|
|
|
|||
|
|
### 另一套前端事件注册实现(对比参考)
|
|||
|
|
- register-events.js 提供了另一种前端事件注册方式,同样处理鼠标、滚轮与触摸事件,并将坐标与按钮状态打包为二进制消息发送。
|
|||
|
|
- 该实现与 sender.js 的差异在于:
|
|||
|
|
- 事件监听对象不同(视频元素 vs 文档/窗口)。
|
|||
|
|
- 坐标映射逻辑略有差异(考虑 videoOriginX/Y 与 videoScale)。
|
|||
|
|
- 未使用 InputRemoting/Message 体系,而是直接构造 DataView 发送。
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [register-events.js:161-281](file://client/public/videoplayer/js/register-events.js#L161-L281)
|
|||
|
|
- [main.js(视频播放器):132-142](file://client/public/videoplayer/js/main.js#L132-L142)
|
|||
|
|
|
|||
|
|
## 依赖关系分析
|
|||
|
|
- Sender 依赖 Mouse/MouseState、PointerCorrector、LocalInputManager、StateEvent。
|
|||
|
|
- MouseState 依赖 MemoryHelper 与 MouseButton。
|
|||
|
|
- InputRemoting 依赖 Message/NewEventsMsg/RemoveDeviceMsg/ChangeUsageMsg 与订阅者。
|
|||
|
|
- register-events.js 与 main.js 形成独立的事件注册与发送链路。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph LR
|
|||
|
|
Sender["sender.js"] --> Mouse["inputdevice.js: Mouse/MouseState"]
|
|||
|
|
Sender --> PC["pointercorrect.js"]
|
|||
|
|
Sender --> LIM["inputremoting.js: LocalInputManager"]
|
|||
|
|
Sender --> SE["inputdevice.js: StateEvent"]
|
|||
|
|
Mouse --> MH["memoryhelper.js"]
|
|||
|
|
Mouse --> MB["mousebutton.js"]
|
|||
|
|
IR["inputremoting.js"] --> MSG["inputremoting.js: Message/NewEventsMsg"]
|
|||
|
|
RE["register-events.js"] --> |"事件注册/发送"| Sender
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [sender.js:14-188](file://client/src/sender.js#L14-L188)
|
|||
|
|
- [inputdevice.js:91-272](file://client/src/inputdevice.js#L91-L272)
|
|||
|
|
- [inputremoting.js:63-169](file://client/src/inputremoting.js#L63-L169)
|
|||
|
|
- [memoryhelper.js:1-28](file://client/src/memoryhelper.js#L1-L28)
|
|||
|
|
- [mousebutton.js:1-7](file://client/src/mousebutton.js#L1-L7)
|
|||
|
|
- [register-events.js:161-281](file://client/public/videoplayer/js/register-events.js#L161-L281)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [sender.js:14-188](file://client/src/sender.js#L14-L188)
|
|||
|
|
- [inputdevice.js:91-272](file://client/src/inputdevice.js#L91-L272)
|
|||
|
|
- [inputremoting.js:63-169](file://client/src/inputremoting.js#L63-L169)
|
|||
|
|
- [memoryhelper.js:1-28](file://client/src/memoryhelper.js#L1-L28)
|
|||
|
|
- [mousebutton.js:1-7](file://client/src/mousebutton.js#L1-L7)
|
|||
|
|
- [register-events.js:161-281](file://client/public/videoplayer/js/register-events.js#L161-L281)
|
|||
|
|
|
|||
|
|
## 性能考量
|
|||
|
|
- 事件采样与节流
|
|||
|
|
- 对高频 mousemove 可采用节流/降采样策略,避免带宽与 CPU 压力。
|
|||
|
|
- 时间戳与缓冲
|
|||
|
|
- 使用 timeSinceStartup 作为单调递增时间戳,远端按时间戳排序与重放。
|
|||
|
|
- 建议在接收端维护环形缓冲,按目标帧率进行插值。
|
|||
|
|
- 坐标计算优化
|
|||
|
|
- 将 contentRect 缓存并在 resize 时更新,避免重复计算。
|
|||
|
|
- 位图写入
|
|||
|
|
- 使用 MemoryHelper.writeSingleBit 批量写入按钮状态,减少内存拷贝。
|
|||
|
|
|
|||
|
|
## 故障排查指南
|
|||
|
|
- 事件未触发
|
|||
|
|
- 检查事件监听是否绑定到正确的元素(视频元素)。
|
|||
|
|
- 确认 PointerCorrector 的 videoWidth/videoHeight 已正确初始化。
|
|||
|
|
- 坐标错位
|
|||
|
|
- 核对 contentRect 与留边距计算,确认 videoScale 与 originX/Y 设置。
|
|||
|
|
- 按钮状态异常
|
|||
|
|
- 检查按钮位图写入逻辑,确认 MouseButton 枚举与位索引一致。
|
|||
|
|
- 网络发送失败
|
|||
|
|
- 确认订阅者 readyState 为 open,Message.buffer 构造无误。
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [sender.js:114-120](file://client/src/sender.js#L114-L120)
|
|||
|
|
- [pointercorrect.js:71-76](file://client/src/pointercorrect.js#L71-L76)
|
|||
|
|
- [memoryhelper.js:7-20](file://client/src/memoryhelper.js#L7-L20)
|
|||
|
|
- [inputremoting.js:202-208](file://client/src/inputremoting.js#L202-L208)
|
|||
|
|
|
|||
|
|
## 结论
|
|||
|
|
本项目提供了完整的鼠标输入捕获、转换与转发链路:DOM 事件 → MouseState → StateEvent → Message → 网络传输。通过 PointerCorrector 实现跨设备坐标一致性,MemoryHelper 提供高效的按钮位图写入。若需在远端重放,应严格遵循格式标识与字段顺序,并结合时间戳进行缓冲与插值,以获得流畅体验。
|
|||
|
|
|
|||
|
|
## 附录
|
|||
|
|
- 代码路径示例(不展示具体代码内容)
|
|||
|
|
- 鼠标事件监听与状态派发:[sender.js:121-129](file://client/src/sender.js#L121-L129)
|
|||
|
|
- MouseState 构建与位图写入:[inputdevice.js:222-244](file://client/src/inputdevice.js#L222-L244)
|
|||
|
|
- 坐标矫正:[pointercorrect.js:20-40](file://client/src/pointercorrect.js#L20-L40)
|
|||
|
|
- 事件序列化为 Message:[inputremoting.js:258-277](file://client/src/inputremoting.js#L258-L277)
|
|||
|
|
- 前端事件注册(对比实现):[register-events.js:161-281](file://client/public/videoplayer/js/register-events.js#L161-L281)
|