> For the complete documentation index, see [llms.txt](https://lizh.gitbook.io/knowledge/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lizh.gitbook.io/knowledge/javascript-xi-lie/01-ji-chu-pian-13-jian-pan-shu-biao-chu-mo-shi-jian.md).

# 基础篇 13 键盘、鼠标、触摸事件

## 键盘（Keyboard）事件

键盘事件继承于 KeyboardEvent 接口，描述了用户与键盘的交互。

### KeyboardEvent常量

KeyboardEvent 常量用于识别触发按键事件的键盘位置。

* DOM\_KEY\_LOCATION\_STANDARD： 0。表示键不是位于键盘的特殊区域。特殊区域不是指数字键盘上（除非它是 NumLock 键）或者位于键盘左右两侧重复的键，而是，不管什么原因，与所处位置没有关联的键。 比如， 标准 PC 101 美国键盘上的字母数字键、NumLock 键和空格键。
* DOM\_KEY\_LOCATION\_LEFT： 1。表示键可能存在于键盘上的多个位置，在当前情况下，位于键盘的左侧。 比如，左 Control 键、Macintosh 键盘上的左 Command 键或左 Shift 键。
* DOM\_KEY\_LOCATION\_RIGHT： 2。表示键可能存在于键盘上的多个位置，在当前情况下，位于键盘的右侧。 比如，右 Shift 键和右 Alt 键（Mac 键盘上的选项）。
* DOM\_KEY\_LOCATION\_NUMPAD： 3。表示键位于数字键盘上，或者是与数字键盘相关联的虚拟键。 比如，数字键盘上的数字、键盘的 “Enter” 键和键盘上的小数点。

  NumLock 键不属于这个组，并且总是使用位置 DOM\_KEY\_LOCATION\_STANDARD 进行编码。

```javascript
KeyboardEvent.DOM_KEY_LOCATION_STANDARD // 0
KeyboardEvent.DOM_KEY_LOCATION_LEFT     // 1
KeyboardEvent.DOM_KEY_LOCATION_RIGHT    // 2
KeyboardEvent.DOM_KEY_LOCATION_NUMPAD   // 3
```

### KeyboardEvent属性

KeyboardEvent 接口从 UIEvent 和 Event 接口中继承属性。

#### altKey（只读）

返回布尔值。表示事件触发时，alt 键（OS X 系统上的 Option 或 ⌥ 键）是（true）否（false）按下。

#### ctrlKey（只读）

返回布尔值。表示事件触发时，control 键是（true）否（false）按下。

#### shiftKey（只读）

返回布尔值。表示事件触发时，shift 键是（true）否（false）按下。

#### metaKey（只读）

返回布尔值。表示事件触发时，Meta 键是（true）否（false）按下。

**注意：** 在 MAC 键盘上，表示 Command 键（⌘）；在 Windows 键盘上，表示 Windows 键（⊞）。

#### code（只读）

返回字符串，表示触发事件的物理按键。

常用键的 code 属性值：

* 数字键 0 - 9：返回 Digit0 \~ Digit9。
* 字母键 A - z：返回 KeyA \~ KeyZ（不区分大小写）。
* 功能键 F1 - F12：返回 F1 \~ F12。
* 方向键：返回 ArrowDown、ArrowUp、ArrowLeft、ArrowRight。
* Alt、Shift、Ctrl 键：返回 AltLeft 或 AltRight、ShiftLeft 或 ShiftRight、ControLeft 或 ControlRight。

**注意：** 该属性会忽略用户的键盘布局。所以如果用户在 QWERTY 布局的键盘上按下 “Y” 位置（第一行字母按键的中间）的按键时，这个属性会返回 “KeyY”，即使用户使用 QWERTZ 布局的键盘（此时用户输入的就是“Z”，其他属性也会提示“Z”）或 Dvorak 键盘（此时用户输入的就是“F”）也是如此。

#### key（只读）

返回字符串，表示用户按下的物理按键的值。它还与 shiftKey 等调节性按键的状态和键盘的区域 / 和布局有关。

其值由以下因素决定：

* 如果按下**字符键**，则返回一个非空的 Unicode 字符。
* 如果按下**功能键**，则返回一个事先定义好的值，见[预定义键值列表](https://developer.mozilla.org/zh-CN/docs/Web/API/UI_Events/Keyboard_event_key_values)。
* 如果按下**死键**，则返回 `"Dead"`。
* 有些特殊键盘的键（比如多媒体键盘上用来控制媒体播放的扩展按键）在 Windows 下会触发 `WM_APPCOMMAND` 事件，而不会产生按键代码。虽然没有按键代码，这些事件将映射到 DOM 键盘事件中，并将列入 Windows 的“虚拟按键码”列表中。
* 如果按键无法识别，则返回 `"Unidentified"`。

常用键的 key 属性值：

* 数字键 0 - 9：返回 0 \~ 9。
* 字母键 A - z：返回 A \~ Z、a \~ z（区分大小写）。
* 功能键F1 - F12：返回 F1 \~ F12。
* 方向键：返回 ArrowDown、ArrowUp、ArrowLeft、ArrowRight。
* Alt、Shift、Ctrl 键：返回 Alt、Shift、Control。

#### keyCode（只读）（已废弃）

返回按下的**非字符键**的唯一标识值。其值依据于一个系统和实现相关的数字代码，通常是与密钥对应的二进制的 ASCII（RFC 20）码或 Windows 1252 码。如果这个键不能被标志，这个值为 0。

该属性值在浏览器之间不兼容，比如：

* 在 FF、Opera 中，分号键返回 59，但 IE、Chrome、Safari 返回 186。
* 在 Safari 3 之前的版本中，上、下、左、右箭头和上翻（PageUp）、下翻（PageDown）键返回大于 63000的值。

**注意：** 在处理 keydown、keyup 事件时，不应使用**字符键**的 keycode 属性。keycode 属性对字符键的输入无效，尤其是按下 shift 或 alt 键的输入。

**注意：** keyCode 属性在不同浏览器，不同事件中，其返回值有很大的兼容性问题，建议用 KeyboardEvent.code 或者 KeyboardEvent.key 属性代替。如果一定要用该属性，[请先阅读该文章](https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent/keyCode)。

#### charCode（只读）（已废弃）（非标准）

返回按下的**字符键**的字符 Unicode 值。

charCode 属性值不会在 keydown、keyup 事件中被设置。在 keypress 事件中，按键的 Unicode 值保存在 keyCode 或 charCode 属性其中之一，不会二者同时都有。如果按下的是字符键（如， 'a'），charCode 属性被设置为字符的代码值，并区分大小写； 否则，被按下的键的代码被存储在 keyCode 属性中。

**注意：** 该属性已被废弃，请使用 KeyboardEvent.key 属性代替。

```javascript
// Chrome： 依次按下 a -> 1 -> 右方向 -> F3 -> CapsLock 键，各属性的打印值如下： 
document.querySelector('input').addEventListener('keydown', event => {
    console.log(event.code) // KeyA -> Digit1 -> ArrowRight -> F3 -> CapsLock
    console.log(event.key)  // a -> 1 -> ArrowRight -> F3 -> CapsLock
    console.log(event.keyCode)  // 65 -> 49 -> 39 -> 114 -> 20
    console.log(event.charCode) // 0 -> 0 -> 0 -> 0 -> 0
}, false)
document.querySelector('input').addEventListener('keypress', event => {
    console.log(event.charCode) // 97 -> 49，其余三个功能键不会触发 keypress 事件
}, false)
```

#### location（只读）

返回一个无符号的长整型（Number 类型，0、1、3...），表示按键在键盘或其他设备上的位置。

其返回值表示的位置，可以查看上一节 **【KeyboardEvent 常量】**。

#### isComposing（只读）

返回布尔值。表示该事件是否在 compositionstart 之后和 compositionend 之前被触发。

#### repeat（只读）

返回布尔值。如果按键被一直按住，返回值为true。

### KeyboardEvent方法

KeyboardEvent 接口从 UIEvent 和 Event 接口中继承方法。

#### getModifierState()

返回布尔值，指定修饰键（区分大小写）是否处于活动状态（即被按下或锁定）。

常见的修饰键有：

```javascript
Alt、CapsLock、Control、NumLock、Shift
```

### KeyboardEvent事件

键盘事件只能由 input、textarea 以及任何具有 contentEditable 或 tabindex="-1" 属性的元素触发；此外，window、document 对象也能监听键盘事件。

```javascript
document.querySelector('input').addEventListener('keydown', event => {}, false)
window.addEventListener('keydown', event => {}, false)
document.addEventListener('keydown', event => {}, false)
```

#### keydown

当键盘按键按下时触发。当用户按下**任意键**时触发，而且按住不放的话，会重复触发此事件。

#### keypress

当用户按下**字符键**时触发，而且按住不放的话，会重复触发此事件。但是，**功能键不一定能触发该事件**。

#### keyup

在键盘按键被松开时触发。

KeyboardEvent 事件取值兼容情况：

* keydown、keyup 表现一致，keypress 与两者有差异：keydown、keyup 事件中，字符键、功能键可获取 keyCode、witch 属性值，但 charCode 属性值为 0；而 keypress 事件中，字符键可获取 keyCode、witch、charCode 属性值。但有些浏览器中，功能键不一定能触发此事件。
* keydown、keyup 事件捕获**键盘按键**的操作，对**大小写不敏感**，而 keypress 响应具体输入某个字符的值，对**大小写敏感**。比如，在 keydown、keyup 事件中，小写 `a` 和大写 `A` 输出的都是大写 `A` 的 Unicode 编码 65；而在 keypress 事件中，小写 `a` 输出的 Unicode 编码是 97，而大写 `A` 输出的 Unicode 编码是 65。
* keypress 事件的 which 属性值无法区分主键盘上的数字键和附键盘数字键的，而 keydown、keyup 的 which 属性值对主附键盘的数字键敏感。

**注意：** keyup 事件中，无法阻止浏览器默认事件。因为在 keypress 事件时，浏览器默认行为已经完成，即文字已输入到文本框了（尽管这时还没显示），此时，不管是调用 `preventDefault` 方法还是执行 `return Value = false` 都不能阻止在文本框中输入文字的行为。如要阻止默认行为，必须在 keydown 或 keypress 事件中阻止。

### 键盘键分类

键盘中的键分为**字符键**（可打印）和**功能键**（不可打印），系统功能键包括如下：

```javascript
Esc
Tab
Caps Lock
Shift
Ctrl
Alt
Enter
Backspace
Print Screen
Scroll Lock
Pause Break
Insert
Delete
Home
End
Page Up
Page Down
F1 ~ 12
Num Lock
The Arrow Keys
```

keydown、keyup 均可以对系统功能键进行有效的拦截，但事件截获的位置不同；keypress 事件**不能对系统功能键**（例如：后退、删除等）、**中文输入法**进行正常的响应。

**keypress 事件的系统功能键兼容问题：**

* Firefox： 支持 `Esc、Enter、Backspace、Pause Break、Insert、Delete、Home、End、Page Up、Page Down、F1 ~ F12、The Arrow Keys`。
* Chrome、Oprea、Safari： 支持 `Enter`、不支持 `The Arrow Keys`。
* IE： 支持 `Esc、Enter`、不支持 `The Arrow Keys`。

**中文输入法兼容问题：**

* firfox：字符键输入触发 `keydown`，回车确认输入触发 `keyup`。
* chrome：字符键输入触发 `keydown、keyup`，回车确认输入只触发 `keydown`。
* IE、字符键、opera：字符键输入触发`keydown、keyup`，回车确认输入触发`keydown、keyup`。

### ASCII码表

信息在计算机上是用二进制表示的，这种表示法让人理解就很困难。因此计算机上都配有输入和输出设备，这些设备的主要目的就是，以一种人类可阅读的形式将信息在这些设备上显示出来供人阅读理解。为保证人类和设备，设备和计算机之间能进行正确的信息交换，人们编制的统一的信息交换代码，这就是**ASCII码**（American Standard Code for Information Interchange）表，它的全称是“美国信息交换标准代码”。

**一些常见的：**

* 字母（大、小写）：`[A-z] -> [65-122]`。
* 数字：`[0-9] -> [48-57]`。

|  字符 |  编码 |  字符 |  编码 |  字符 |  编码 |  字符 |  编码 |
| :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: |
| nul |  0  |  sp |  32 |  @  |  64 |  '  |  96 |
| soh |  1  |  !  |  33 |  A  |  65 |  a  |  97 |
| stx |  2  |  "  |  34 |  B  |  66 |  b  |  98 |
| etx |  3  |  #  |  35 |  C  |  67 |  c  |  99 |
| eot |  4  |  $  |  36 |  D  |  68 |  d  | 100 |
| enq |  5  |  %  |  37 |  E  |  69 |  e  | 101 |
| ack |  6  |  &  |  38 |  F  |  70 |  f  | 102 |
| bel |  7  |  \` |  39 |  G  |  71 |  g  | 103 |
|  bs |  8  |  (  |  40 |  H  |  72 |  h  | 104 |
|  ht |  9  |  )  |  41 |  I  |  73 |  i  | 105 |
|  nl |  10 |  \* |  42 |  J  |  74 |  j  | 106 |
|  vt |  11 |  +  |  43 |  K  |  75 |  k  | 107 |
|  ff |  12 |  ,  |  44 |  L  |  76 |  l  | 108 |
|  er |  13 |  -  |  45 |  M  |  77 |  m  | 109 |
|  so |  14 |  .  |  46 |  N  |  78 |  n  | 110 |
|  si |  15 |  /  |  47 |  O  |  79 |  o  | 111 |
| dle |  16 |  0  |  48 |  P  |  80 |  p  | 112 |
| dc1 |  17 |  1  |  49 |  Q  |  81 |  q  | 113 |
| dc2 |  18 |  2  |  50 |  R  |  82 |  r  | 114 |
| dc3 |  19 |  3  |  51 |  S  |  83 |  s  | 115 |
| dc4 |  20 |  4  |  52 |  T  |  84 |  t  | 116 |
| nak |  21 |  5  |  53 |  U  |  85 |  u  | 117 |
| syn |  22 |  6  |  54 |  V  |  86 |  v  | 118 |
| etb |  23 |  7  |  55 |  W  |  87 |  w  | 119 |
| can |  24 |  8  |  56 |  X  |  88 |  x  | 120 |
|  em |  25 |  9  |  57 |  Y  |  89 |  y  | 121 |
| sub |  26 |  :  |  58 |  Z  |  90 |  z  | 122 |
| esc |  27 |  ;  |  59 |  \[ |  91 |  {  | 123 |
|  fs |  28 |  <  |  60 |  \\ |  92 |  \| | 124 |
|  gs |  29 |  =  |  61 |  ]  |  93 |  }  | 125 |
|  re |  30 |  >  |  62 |  ^  |  94 |  \~ | 126 |
|  us |  31 |  ?  |  63 |  \_ |  95 | del | 127 |

## 鼠标（Mouse）事件

鼠标事件继承于 MouseEvent 接口。MouseEvent 接口指用户与指针设备（如鼠标）交互时发生的事件。MouseEvent 接口继承自 UIEvent 接口，UIEvent 接口继承自 Event 接口。

### MouseEvent属性

MouseEvent 接口继承 UIEvent 和 Event 接口上的属性。

#### altKey（只读)

当鼠标事件触发时，alt 键是否被按下。

#### ctrlKey（只读)

当鼠标事件触发时，control 键是否被按下。

#### metaKey（只读)

当鼠标事件触发时，meta 键是否被按下。

#### shiftKey（只读)

当鼠标事件触发时，shift 键是否被按下。

#### button（只读)

当鼠标事件触发时，返回一个值，代表用户按下并触发了事件的鼠标按键。

返回值代表按下的鼠标按键：

* 0：主按键，通常指鼠标左键或默认值（Element.click() 触发事件就是默认值）。
* 1：辅助按键，通常指鼠标滚轮中键。
* 2：次按键，通常指鼠标右键。
* 3：第四个按钮，通常指浏览器后退按钮。
* 4：第五个按钮，通常指浏览器的前进按钮。

**注意：** 用户可以改变鼠标按键的配置，因此 button 属性值为 0 时，它可能不是由物理上设备最左边的按键触发的。比如，对于配置为左手使用的鼠标，按键操作将正好相反。此种情况下，从右至左读取值。

**注意：** button 属性只能够表明在触发事件的单个或多个按键按下或释放过程中哪些按键被按下了。因此，它对判断 mouseenter、mouseleave、mouseover、mouseout、mousemove 这些事件并不可靠。

#### buttons（只读)

当鼠标事件触发时，哪些鼠标按键被按下。

返回值代表按下的鼠标按键：

* 0： 没有按键或者是没有初始化。
* 1： 鼠标左键。
* 2： 鼠标右键。
* 4： 鼠标滚轮或者是中键。
* 8： 第四个按钮，通常指浏览器后退按钮。
* 16： 第五个按钮，通常指浏览器的前进按钮。

如果按下的键为多个，则值等于所有按键对应数值进行或（|）运算的结果。

```javascript
1 | 2 // 3。左键和右键同时按下
2 | 4 // 6。右键和中键同时按下
```

#### clientX（只读)

返回一个双精度浮点值。表示当事件触发时，鼠标指针在客户端区域中的 X 坐标。

例如，不论页面是否有水平滚动，当你点击客户端区域的左上角时，其值都将为 0 。

#### clientY（只读)

返回一个双精度浮点值。表示当事件触发时，鼠标指针在客户端区域中的 Y 坐标。

例如，不论页面是否有垂直滚动，当你点击客户端区域的左上角时，其值都将为 0 。

#### movementX（只读)

返回一个数字。表示当前事件和上一个 mousemove 事件之间鼠标在 X 轴方向上的移动值。

换句话说，这个值是这样计算的：

```javascript
currentEvent.movementX = currentEvent.screenX - previousEvent.screenX
```

#### movementY（只读)

返回一个数字。表示当前事件和上一个 mousemove 事件之间鼠标在 Y 轴方向上的移动值。

换句话说，这个值是这样计算的：

```javascript
currentEvent.movementY = currentEvent.screenY - previousEvent.screenY
```

#### offsetX（只读) （实验性）

返回一个双精度浮点值。表示鼠标指针相对于与事件目标的内填充边在 X 轴方向上的偏移量。

#### offsetY（只读) （实验性）

返回一个双精度浮点值。表示鼠标指针相对于与事件目标的内填充边在 Y 轴方向上的偏移量。

#### pageX（只读) （实验性）

返回一个双精度浮点值。表示鼠标指针相对于整个文档的 X 坐标。该属性将基于文档的边缘，考虑了页面水平方向上的滚动。

#### pageY（只读) （实验性）

返回一个双精度浮点值。表示鼠标指针相对于整个文档的 Y 坐标。该属性将基于文档的边缘，考虑了页面垂直方向上的滚动。

#### screenX（只读)

返回一个双精度浮点值。表示鼠标指针相对于全局（屏幕）的 X 坐标。

#### screenY（只读)

返回一个双精度浮点值。表示鼠标指针相对于全局（屏幕）的 Y 坐标。

#### x（只读) （实验性）

clientX 属性的别名。

#### y（只读) （实验性）

clientY 属性的别名。

#### region（只读)

返回被点击事件影响的点击区域的 id，如果没有区域被影响则返回 null。

#### relatedTarget（只读)

鼠标事件的次要目标（如果有的话）。

#### which（只读)（非标准）

表示鼠标事件是由哪个鼠标按键被按下所触发的。

返回值表示按键：

* 0： 无。
* 1： 左键。
* 2： 中间滚轮（如果有的话）。
* 3： 右键。

### MouseEvent方法

MouseEvent 接口从 UIEvent 和 Event 接口中继承方法。

#### getModifierState()

返回布尔值，指定修饰键是否处于活动状态（即被按下或锁定）。同 KeyboardEvent.getModifierState() 方法。

### MouseEvent事件

#### click

在一个元素上单击（按下和放开）一次鼠标的指针设备按钮（通常是鼠标左键）时触发。

#### dblclick

在一个元素上连续单击两次鼠标的指针设备按钮（通常是鼠标左键）时触发。

#### contextmenu

在用户尝试打开上下文菜单时被触发。

该事件通常在鼠标点击右键或者按下键盘上的菜单键时被触发，如果使用菜单键，该上下文菜单会被展示到所聚焦元素的左下角，但是如果该元素是一棵 DOM 树的话，上下文菜单便会展示在当前这一行的左下角。

任何没有被禁用的鼠标右击事件（通过调用事件的 preventDefault() 方法）的元素都可以触发该事件。

#### mousedown

在指针设备按钮**按下**时触发。

#### mouseup

在指针设备按钮**放开**时触发。

#### mouseenter

当指针设备（通常指鼠标）的指针**移动到**元素时触发。

类似 mouseover 事件，两者区别是：mouseenter 不会冒泡，而 mouseover 会。也就是说，当指针在该元素和其子元素之间移动时，不会触发 mouseenter 事件，但会触发 mouseover 事件。

#### mouseleave

当指针设备（通常是鼠标）的指针**移出**元素时触发。

类似 mouseout 事件，两者区别是：mouseleave 不会冒泡，而 mouseout 会。也就是说，当指针在该元素和其其子元素之间移动时，不会触发 mouseleave 事件，但会触发 mouseout 事件。

#### mouseover

当指针设备（通常指鼠标）的指针**移动到**当前元素或其子元素时触发。当指针从一个元素移入其子元素时也会触发，因为子元素遮盖了父元素的可视区域。

#### mouseout

当指针设备（通常指鼠标）的指针**移出**当前元素或其子元素时触发。当指针从一个元素移入其子元素时也会触发，因为子元素遮盖了父元素的可视区域。

#### mousemove

当指针设备（通常指鼠标）在元素上移动时触发。

#### select

有文本被选中。

#### wheel

滚轮向任意方向滚动。

## 触摸（Touch）事件

TouchEvent 是一类描述手指在触摸平面（触摸屏、触摸板等）的状态变化的事件。这类事件用于描述一个或多个触点，使开发者可以检测触点的移动、触点的增加和减少等等。

每个 Touch 对象代表一个触点，每个触点都由其位置、大小、形状、压力大小、目标元素描述组成。 TouchList 对象代表多个触点的一个列表。

在很多情况下，触摸事件和鼠标事件会同时被触发（目的是让没有对触摸设备优化的代码仍然可以在触摸设备上正常工作）。如果使用了触摸事件，可以调用 event.preventDefault() 来阻止鼠标事件被触发。

### TouchEvent属性

TouchEvent 接口继承 UIEvent 和 Event 接口的属性。

#### touches（只读）

返回一个 TouchList 对象，表示所有当前在与触摸表面接触的 Touch 对象，不管触摸点是否已经改变或其目标元素是在处于 touchstart 阶段。

#### targetTouches（只读）

返回一个 TouchList 对象，表示仍与触摸面接触的所有触摸点的 Touch 对象。

**注意：** 事件目标是触发 touchstart 事件的元素。

#### changedTouches（只读）

返回一个 TouchList 对象，表示所有从上一次触摸事件到此次事件过程中，状态发生了改变的触点的 Touch 对象。

* touchstart 事件： 列出在此次事件中新增加的触点集合。
* touchmove 事件： 列出和上一次事件相比较，发生了变化的触点集合。
* touchend 事件： 列出已经从触摸面的离开的触点集合。

### TouchEvent事件

#### touchstart

当一个或多个触摸点与触控设备表面**接触**时触发。

#### touchmove

当一个或多个触摸点沿触摸设备表面**移动**时触发。当触点的半径、旋转角度以及压力大小发生变化时，也将触发此事件。

#### touchend

当一个或多个触摸点沿触摸设备表面**移除**时触发。

#### touchcancel

当一个或多个触摸点沿触摸设备表面**被中断**时触发。中断方式基于特定实现而有所不同，例如， 创建了太多的触摸点。

有几种可能的原因如下：

* 由于某个事件出现而取消了触摸：例如触摸过程被弹窗打断。
* 触点离开了文档窗口，而进入了浏览器的界面元素、插件或者其他外部内容区域。
* 当用户产生的触点个数超过了设备支持的个数，从而导致 TouchList 中最早的 Touch 对象被取消。

### Touch接口

Touch 对象表示在触控设备上的触摸点。通常是指手指或者触控笔在触屏设备或者触摸板上的操作。

Touch 对象代表一个触点，每个触点包含位置、大小、形状、压力大小和目标元素属性。

Touch 接口没有父类，不继承任何属性，且该接口没有方法。

Touch 对象很多属性的值需要依赖硬件设备去获取。

例如，如果设备本身不支持侦测压感，那么 force 属性的值将始终是 0；对于 radiusX 和 radiusY 来说同样可能有这种情况，如果设备认为触点只是一个点而不是一个面，它们始终为 1。

```javascript
clientX: 341.6842346191406
clientY: 229.68423461914062
force: 1
identifier: 0
pageX: 341.6842346191406
pageY: 229.68423461914062
radiusX: 12.105263710021973
radiusY: 12.105263710021973
region: null
rotationAngle: 0
screenX: 345.6000061035156
screenY: 356
target: canvas.element_canvas1
```

#### identifier（只读）

返回返回一个整数，可以唯一地识别和触摸平面接触的点的值。这个值在这根手指（或触摸笔等）所引发的所有事件中保持一致，直到它离开触摸平面。

#### screenX（只读）

返回触点相对于屏幕左边沿的的 X 坐标。不包含页面滚动的偏移量。

#### screenY（只读）

返回触点相对于屏幕左边沿的的 Y 坐标。不包含页面滚动的偏移量。

#### clientX（只读）

返回触点相对于可见视区（Visual Viewport）左边沿的的 X 坐标。不包括任何滚动偏移。这个值会根据用户对可见视区的缩放行为而发生变化。

#### clientY（只读）

返回触点相对于可见视区（Visual Viewport）左边沿的的 Y 坐标。不包括任何滚动偏移。这个值会根据用户对可见视区的缩放行为而发生变化。

#### pageX（只读）

返回触点相对于 HTML 文档左边沿的的 X 坐标。当存在水平滚动的偏移时，这个值包含了水平滚动的偏移。

#### pageY（只读）

返回触点相对于 HTML 文档上边沿的的 Y 坐标。当存在垂直滚动的偏移时，这个值包含了垂直滚动的偏移。

#### target（只读）

返回触摸点最初接触的元素，即使这个触摸点已经移出那个元素的交互区域。

**注意：** 即使该元素在触摸过程中被移除，事件的 target 属性仍然会指向它，因此这个事件也不会冒泡到 window 或 document 对象。因此，如果有元素在触摸过程中可能被移除，最佳实践是将触摸事件的监听器绑定到这个元素本身，防止元素被移除后，无法再从它的上一级元素上侦测到从该元素冒泡的事件。

#### radiusX（只读）（实验性）

返回能够包围用户和触摸平面的接触面的最小椭圆的水平轴（X 轴）半径。

#### radiusY（只读）（实验性）

返回能够包围用户和触摸平面的接触面的最小椭圆的垂直轴（Y 轴）半径。

#### rotationAngle（只读）（实验性）

返回以度为单位的旋转角，可能值是从 0 到 90。由 radiusX 和 radiusY 描述的正方向的椭圆，通过顺时针旋转这个角度后，能最精确地覆盖住用户和触摸平面的接触面的角度。

由 radiusX 和 radiusY 描述的正方向的椭圆，通过顺时针旋转这个角度后，能最精确地覆盖住用户和触摸平面的接触面的角度。。这三个值一起描述了用户和触摸平面的接触面的形状的大小。例如，当用户使用手指和平面接触时，它可能是一个较大的椭圆，而当用户使用触摸笔时，它可能是很小的椭圆。

**注意：** radiusX、radiusY、rotationAngle 一起，描述了用户和触摸平面的接触面。这在面向非精确触摸设备（由手指直接操作的触摸屏）开发时非常有用。这些值描述了一个尽可能接近实际接触面（例如用户的指尖）的椭圆。

#### force（只读）（实验性）

返回用户对触摸平面的压力大小，是一个从 0.0（没有压力）到 1.0（最大压力）的浮点数。

### TouchList接口

TouchList 接口代表一个触摸平面上所有触点的列表。例如，如果一个用户用三根手指接触屏幕（或者触控板），与之对应的 TouchList 会包含每根手指的 Touch 对象，总共三个。

TouchList 对象主要通过触摸事件的 touches、changedTouches、targetTouches 属性获取。

#### length属性（只读）

返回 TouchList 中 Touch 对象的数量。

#### item()方法

返回列表中以指定值作为索引的 Touch 对象。

## 常见问题

### 300ms延迟

移动浏览器会在 touchend 和 click 事件之间，等待 300 - 350 ms，判断用户是否会进行双击手势用以缩放文字。

这是因为触摸屏幕的行为被重载（overload）了。在手指触摸屏幕的瞬间，浏览器无法预知用户是在轻触（Tap）、双触（Double-Tap）、滑动（Swipe）、按住不放（Hold）还是其他什么操作。唯一保险的做法就是等上一会儿看接下来会发生什么。

**解决方案一：** 禁用缩放。注：浏览器可能不支持。

```html
<meta name="viewport" content="user-scalable=no" />
```

```css
html {
	/*注意浏览器前缀*/
    touch-action: manipulation;
}
```

**解决方案二：** 改变视口宽度。为用户适配了页面大小和阻止了用户缩放，浏览器就不用再判断用户双击缩放了，于是便自动取消了click事件的 300ms 延迟。注：safari 浏览器可能不支持。

```html
<meta name="viewport" content="width=device-width" />
```

**解决方案三：** 引用 fastclick 库。**（不推荐）**

**原理:** 移动端点击事件发生时，会触发 `touchStart -> touchMove -> touchEnd -> click` ，fastclick 是在监听到 touchEnd 事件时，立即触发click事件，并阻止原来事件的发生。

**缺点：** 可以会引起表单 input 元素获取焦点时，唤起软件键的一些异常；还有其他Bug。

## 参考链接

[MDN - KeyboardEvent](https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent)

[MDN - 鼠标事件](https://developer.mozilla.org/zh-CN/docs/Web/API/MouseEvent)

[MDN - TouchEvent](https://developer.mozilla.org/zh-CN/docs/Web/API/TouchEvent)

[MDN Touch](https://developer.mozilla.org/zh-CN/docs/Web/API/Touch)

[MDN - TouchList](https://developer.mozilla.org/zh-CN/docs/Web/API/TouchList)
