1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
|
---
title: 滚轮事件
slug: Web/API/Element/wheel_event
translation_of: Web/API/Element/wheel_event
---
<p>当滚动鼠标滚轮或操作其它类似输入设备时会触发<strong>滚轮事件</strong>。滚轮事件替换了已被弃用的非标准{{domxref("mousewheel")}}事件。</p>
<div class="note"><strong>注意事项:</strong> 请勿想当然依据滚轮方向(即该事件的各delta属性值)来推断文档内容的滚动方向,因标准未定义滚轮事件具体会引发什么样的行为,引发的行为实际上是各浏览器自行定义的。即便滚轮事件引发了文档内容的滚动行为,也不表示滚轮方向和文档内容的滚动方向一定相同。因而通过该滚轮事件获知文档内容滚动方向的方法并不可靠。要获取文档内容的滚动方向,可在文档内容滚动事件({{event("scroll")}})中监视{{domxref("Element.scrollLeft", "scrollLeft")}}和{{domxref("Element.scrollTop", "scrollTop")}}二值变化情况,即可推断出滚动方向了。</div>
<h2 id="概要">概要</h2>
<dl>
<dt style="float: left; text-align: right; width: 120px;">接口</dt>
<dd style="margin: 0 0 0 120px;">{{domxref("WheelEvent")}}</dd>
<dt style="float: left; text-align: right; width: 120px;">同步性</dt>
<dd style="margin: 0 0 0 120px;">异步</dd>
<dt style="float: left; text-align: right; width: 120px;">事件冒泡</dt>
<dd style="margin: 0 0 0 120px;">是</dd>
<dt style="float: left; text-align: right; width: 120px;">可取消</dt>
<dd style="margin: 0 0 0 120px;">是</dd>
<dt style="float: left; text-align: right; width: 120px;">目标元素</dt>
<dd style="margin: 0 0 0 120px;">defaultView, Document, Element</dd>
<dt style="float: left; text-align: right; width: 120px;">默认行为</dt>
<dd style="margin: 0 0 0 120px;">滚动, 历史记录切换, 或者放大/缩小.</dd>
</dl>
<h2 id="属性">属性</h2>
<p><em>滚轮事件实现了以下事件的属性: {{domxref("WheelEvent")}}, {{domxref("MouseEvent")}}, {{domxref("UIEvent")}} and {{domxref("Event")}}.</em></p>
<h3 id="Properties_of_WheelEvent">Properties of <code>WheelEvent</code></h3>
<p>{{page("/zh-CN/docs/Web/API/WheelEvent", "属性")}}</p>
<h3 id="Properties_of_MouseEvent">Properties of <code>MouseEvent</code></h3>
<p>{{page("/zh-CN/docs/Web/API/MouseEvent", "属性")}}</p>
<h3 id="Properties_of_UIEvent">Properties of <code>UIEvent</code></h3>
<p>{{page("/zh-CN/docs/Web/API/UIEvent", "属性")}}</p>
<h3 id="Properties_of_Event">Properties of <code>Event</code></h3>
<p>{{page("/zh-CN/docs/Web/API/Event", "属性")}}</p>
<h2 id="方法">方法</h2>
<p><em>滚轮事件实现了以下事件的方法: {{domxref("WheelEvent")}}, {{domxref("MouseEvent")}}, {{domxref("UIEvent")}} and {{domxref("Event")}}.</em></p>
<h3 id="Methods_of_WheelEvent">Methods of <code>WheelEvent</code></h3>
<p>{{page("/zh-CN/docs/Web/API/WheelEvent", "方法")}}</p>
<h3 id="Methods_of_MouseEvent">Methods of <code>MouseEvent</code></h3>
<p>{{page("/zh-CN/docs/Web/API/MouseEvent", "方法")}}</p>
<h3 id="Methods_of_UIEvent">Methods of <code>UIEvent</code></h3>
<p>{{page("/zh-CN/docs/Web/API/UIEvent", "方法")}}</p>
<h3 id="Methods_of_Event">Methods of <code>Event</code></h3>
<p>{{page("/zh-CN/docs/Web/API/Event", "方法")}}</p>
<h2 id="规范">规范</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
<tr>
<td>{{SpecName('DOM3 Events','DOM3-Events.html#event-type-wheel','wheel')}}</td>
<td>{{Spec2('DOM3 Events')}}</td>
<td>Initial definition.</td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容性">浏览器兼容性</h2>
<p>{{Compat("api.Element.wheel_event")}}</p>
<h3 id="跨浏览器监听滚动事件">跨浏览器监听滚动事件</h3>
<p><code><font face="Open Sans, Arial, sans-serif">以下脚本创建了一个全局的 </font>addWheelListener</code> 方法,它可以兼容各浏览器监听滚动事件,并且阻止默认行为。</p>
<pre class="brush:js;">// creates a global "addWheelListener" method
// example: addWheelListener( elem, function( e ) { console.log( e.deltaY ); e.preventDefault(); } );
(function(window,document) {
var prefix = "", _addEventListener, onwheel, support;
// detect event model
if ( window.addEventListener ) {
_addEventListener = "addEventListener";
} else {
_addEventListener = "attachEvent";
prefix = "on";
}
// detect available wheel event
support = "onwheel" in document.createElement("div") ? "wheel" : // 各个厂商的高版本浏览器都支持"wheel"
document.onmousewheel !== undefined ? "mousewheel" : // Webkit 和 IE一定支持"mousewheel"
"DOMMouseScroll"; // 低版本firefox
window.addWheelListener = function( elem, callback, useCapture ) {
_addWheelListener( elem, support, callback, useCapture );
// handle MozMousePixelScroll in older Firefox
if( support == "DOMMouseScroll" ) {
_addWheelListener( elem, "MozMousePixelScroll", callback, useCapture );
}
};
function _addWheelListener( elem, eventName, callback, useCapture ) {
elem[ _addEventListener ]( prefix + eventName, support == "wheel" ? callback : function( originalEvent ) {
!originalEvent && ( originalEvent = window.event );
// create a normalized event object
var event = {
// keep a ref to the original event object
originalEvent: originalEvent,
target: originalEvent.target || originalEvent.srcElement,
type: "wheel",
deltaMode: originalEvent.type == "MozMousePixelScroll" ? 0 : 1,
deltaX: 0,
deltaZ: 0,
preventDefault: function() {
originalEvent.preventDefault ?
originalEvent.preventDefault() :
originalEvent.returnValue = false;
}
};
// calculate deltaY (and deltaX) according to the event
if ( support == "mousewheel" ) {
event.deltaY = - 1/40 * originalEvent.wheelDelta;
// Webkit also support wheelDeltaX
originalEvent.wheelDeltaX && ( event.deltaX = - 1/40 * originalEvent.wheelDeltaX );
} else {
event.deltaY = originalEvent.detail;
}
// it's time to fire the callback
return callback( event );
}, useCapture || false );
}
})(window,document);</pre>
<h2 id="Gecko_notes">Gecko notes</h2>
<h3 id="滚轮事件和其它的鼠标滚动事件">滚轮事件和其它的鼠标滚动事件</h3>
<p>如果一个用户真实操作触发的滚轮事件没有被处理, 这会触发一个 <code>DOMMouseScroll</code> 事件和一个 <code>MozMousePixelScroll</code> 事件以向下兼容. 它们的属性值由滚轮事件delta值和最近的ancestor clipped元素计算出。(i.e., <a href="/en-US/CSS/overflow" title="en-US/CSS/overflow"><code>overflow</code></a> 不可见). 如果滚轮事件或其它任意一个剩余事件被 {{ domxref("event.preventDefault()") }}阻止, 将什么都不会发生。</p>
<p>以下为事件顺序:</p>
<ol>
<li>滚轮事件处于默认事件组 (web应用和浏览器插件都可以处理这个组的事件)</li>
<li>当连续滚轮事件 deltaY 的值累计大于1或小于-1时,<code><font face="Open Sans, Arial, sans-serif">竖直方向的 </font>DOMMouseScroll</code> 事件既属于默认事件组也属于系统事件组</li>
<li>当最近的滚轮事件的 deltaY 值非零时,两个事件组都包含竖直方向的 MozMousePixelScroll 事件</li>
<li>当连续滚轮事件 deltaX 的值累计大于1或小于-1时,两个事件组都包含水平<code><font face="Open Sans, Arial, sans-serif">方向的 </font>DOMMouseScroll</code> 事件</li>
<li>当最近的滚轮事件的 deltaX 值非零时,两个事件组都包含水平方向的 MozMousePixelScroll 事件</li>
<li>一个滚轮事件处于系统事件组 (只有浏览器插件可以处理这个组的事件)</li>
</ol>
<table>
<caption><code><font face="Open Sans, Arial, sans-serif">各个事件调用 </font>preventDefault()</code> 会发生什么?</caption>
<thead>
</thead>
<tbody>
<tr>
<th scope="row"><code>wheel</code> (default event group)</th>
<td><code>preventDefault()</code> called</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row"><code>DOMMouseScroll</code> (Vertical)</th>
<td>Not fired</td>
<td><code>preventDefault()</code> called</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row"><code>MozMousePixelScroll</code> (Vertical)</th>
<td>Not fired</td>
<td><code>defaultPrevented</code> is true</td>
<td><code>preventDefault()</code> called</td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row"><code>DOMMouseScroll</code> (Horizontal)</th>
<td>Not fired</td>
<td>Not affected</td>
<td>Not affected</td>
<td><code>preventDefault()</code> called</td>
<td></td>
</tr>
<tr>
<th scope="row"><code>MozMousePixelScroll</code> (Horizontal)</th>
<td>Not fired</td>
<td>Not affected</td>
<td>Not affected</td>
<td><code>defaultPrevented</code> is true</td>
<td><code>preventDefault()</code> called</td>
</tr>
<tr>
<th scope="row"><code>wheel</code> (system event group)</th>
<td><code>defaultPrevented</code> is true</td>
<td><code>defaultPrevented</code> is true</td>
<td><code>defaultPrevented</code> is true</td>
<td><code>defaultPrevented</code> is true</td>
<td><code>defaultPrevented</code> is true</td>
</tr>
</tbody>
</table>
<p>如果一个浏览器插件需要知道剩余事件是否被web内容所处理,它可以使用第6个滚轮事件判断,详细内容请查阅系统事件组 <a href="/en-US/docs/XPCOM_Interface_Reference/nsIEventListenerService" title="/en-US/docs/XPCOM_Interface_Reference/nsIEventListenerService"><code>nsIEventListenerService</code></a> 的文档。</p>
<p>通过设置用户偏好可以修改delta值和默认行为 (<a href="https://wiki.mozilla.org/Gecko:Mouse_Wheel_Scrolling#Preferences_for_customizing_delta_values_and_default_action" title="/en-US/docs/HTML/Element/details">details</a>), 因此开发者不应该期望在处理这个事件后发生特殊的行为。</p>
<h3 id="delta_值">delta 值</h3>
<p>delta 值并不代表默认情况下的实际滚动值,如果用户在滚动滚轮时按住其他键,可能会产生其他行为,比如在浏览记录中前进/回退,或者放大/缩小网页内容。 此外,滚动过程中被滚动的元素不一定是目标元素,滚轮事件的目标元素是由事件触发时光标所在位置计算出的。 That event may not only not be the one actually being scrolled, 甚至都不可滚动。</p>
<h3 id="deltaMode_值">deltaMode 值</h3>
<p>在 Windows 下, 以下三个原生事件造成了 DOM <font face="Consolas, Liberation Mono, Courier, monospace">滚轮事件。</font></p>
<dl>
<dt>WM_MOUSEWHEEL (竖直方向的滚动事件)</dt>
<dd><code>deltaMode</code> 值可以是 <code>DOM_DELTA_LINE</code> 或 <code>DOM_DELTA_PAGE。</code>它取决于 Windows 的用户设置 (默认设置为 <code>DOM_DELTA_LINE</code>)。</dd>
<dt>WM_MOUSEHWHEEL (水平方向的滚动事件)</dt>
<dd><code>deltaMode</code> 值可以是 <code>DOM_DELTA_LINE</code> 或 <code>DOM_DELTA_PAGE。然而 </code>Windows 的滚轮速度设置界面和鼠标驱动工具都没有提供改为 page scroll 的选项。 所以这个值通常为 <code>DOM_DELTA_LINE</code>.</dd>
<dt>WM_GESTURE (Only when caused by panning)</dt>
<dd><code>deltaMode </code>值总是 <code>DOM_DELTA_PIXEL。</code>但请注意大多数笔记本的触摸板都在模拟鼠标滚轮事件而不是调用这个事件, WM_GESTURE 事件通常被平板电脑使用。</dd>
</dl>
<p>在 Mac 下 deltaMode 值由设备决定. 如果设备支持高分辨率像素级滚动, <code>deltaMode </code>值就是典型的 <code>DOM_DELTA_PIXEL</code>. 然而用户可以通过加前缀<code>"mousewheel.enable_pixel_scrolling"</code>将其改变为 <code>DOM_DELTA_LINE</code> 。如果设备不支持高分辨率滚动,那么 deltaModel 值将一直为 <code>DOM_DELTA_LINE</code>.</p>
<p><code><font face="Open Sans, Arial, sans-serif">在其它平台下, deltaMode 值总是 </font>DOM_DELTA_LINE</code>.</p>
<h3 id="Untrusted_events">Untrusted events</h3>
<p>非用户真实操作触发的滚轮事件不会引发默认行为。</p>
<h2 id="参考">参考</h2>
<ul>
<li>{{ domxref("WheelEvent") }}</li>
<li>Gecko's legacy events: <code>DOMMouseScroll</code> and <code>MozMousePixelScroll</code></li>
<li>Non-Gecko browsers' legacy event: <code>mousewheel</code></li>
<li>WebKit bug: <a href="https://bugs.webkit.org/show_bug.cgi?id=94081">https://bugs.webkit.org/show_bug.cgi?id=94081</a></li>
</ul>
|