0
# Mouse and Pointer
1
2
Components and directives for tracking mouse and pointer interactions, positions, and states.
3
4
## Capabilities
5
6
### UseMouse Component
7
8
Tracks mouse position and state with reactive updates.
9
10
```typescript { .api }
11
/**
12
* Component that tracks mouse position and state
13
* @example
14
* <UseMouse v-slot="{ x, y, sourceType }">
15
* <div>Mouse: {{ x }}, {{ y }} ({{ sourceType }})</div>
16
* </UseMouse>
17
*/
18
interface UseMouseProps {
19
/** Mouse position coordinate type @default 'page' */
20
type?: UseMouseCoordType | UseMouseEventExtractor;
21
/** Listen events on target element @default window */
22
target?: MaybeRefOrGetter<Window | EventTarget | null | undefined>;
23
/** Listen to touchmove events @default true */
24
touch?: boolean;
25
/** Listen to scroll events on window @default true */
26
scroll?: boolean;
27
/** Reset to initial value when touchend event fired @default false */
28
resetOnTouchEnds?: boolean;
29
/** Initial position values */
30
initialValue?: Position;
31
/** Event filter for throttling/debouncing */
32
eventFilter?: EventFilter;
33
/** Window object @default defaultWindow */
34
window?: Window;
35
}
36
37
/** Slot data exposed by UseMouse component */
38
interface UseMouseReturn {
39
/** Current x position */
40
x: Ref<number>;
41
/** Current y position */
42
y: Ref<number>;
43
/** Source type of the last position update */
44
sourceType: Ref<UseMouseSourceType>;
45
}
46
47
type UseMouseCoordType = 'page' | 'client' | 'screen' | 'movement';
48
type UseMouseSourceType = 'mouse' | 'touch' | null;
49
type UseMouseEventExtractor = (event: MouseEvent | Touch) => [x: number, y: number] | null | undefined;
50
51
interface Position {
52
x: number;
53
y: number;
54
}
55
```
56
57
**Usage Examples:**
58
59
```vue
60
<template>
61
<!-- Basic mouse tracking -->
62
<UseMouse v-slot="{ x, y, sourceType }">
63
<div class="mouse-tracker">
64
<p>Position: ({{ Math.round(x) }}, {{ Math.round(y) }})</p>
65
<p>Source: {{ sourceType || 'none' }}</p>
66
</div>
67
</UseMouse>
68
69
<!-- Client coordinates -->
70
<UseMouse type="client" v-slot="{ x, y }">
71
<div>Client position: {{ Math.round(x) }}, {{ Math.round(y) }}</div>
72
</UseMouse>
73
74
<!-- Movement tracking -->
75
<UseMouse type="movement" v-slot="{ x, y }">
76
<div>Movement delta: {{ x }}, {{ y }}</div>
77
</UseMouse>
78
79
<!-- Touch disabled -->
80
<UseMouse :touch="false" v-slot="{ x, y, sourceType }">
81
<div>Mouse only (no touch): {{ x }}, {{ y }} ({{ sourceType }})</div>
82
</UseMouse>
83
84
<!-- Custom initial value -->
85
<UseMouse
86
:initial-value="{ x: 100, y: 100 }"
87
v-slot="{ x, y }"
88
>
89
<div>Starts at 100,100: {{ x }}, {{ y }}</div>
90
</UseMouse>
91
</template>
92
93
<script setup>
94
import { UseMouse } from '@vueuse/components';
95
</script>
96
```
97
98
### UseMouseInElement Component
99
100
Tracks mouse position relative to a specific element.
101
102
```typescript { .api }
103
/**
104
* Component that tracks mouse position within element bounds
105
* @example
106
* <UseMouseInElement v-slot="{ x, y, isOutside }">
107
* <div>Relative: {{ x }}, {{ y }} Outside: {{ isOutside }}</div>
108
* </UseMouseInElement>
109
*/
110
interface UseMouseInElementProps extends RenderableComponent {
111
/** Handle outside element @default true */
112
handleOutside?: boolean;
113
/** Mouse position coordinate type @default 'page' */
114
type?: UseMouseCoordType | UseMouseEventExtractor;
115
/** Listen to touchmove events @default true */
116
touch?: boolean;
117
/** Reset to initial value when touchend event fired @default false */
118
resetOnTouchEnds?: boolean;
119
/** Initial position values */
120
initialValue?: Position;
121
/** Event filter for throttling/debouncing */
122
eventFilter?: EventFilter;
123
/** Window object @default defaultWindow */
124
window?: Window;
125
}
126
127
/** Slot data exposed by UseMouseInElement component */
128
interface UseMouseInElementReturn {
129
/** Current x position relative to element */
130
x: Ref<number>;
131
/** Current y position relative to element */
132
y: Ref<number>;
133
/** Source type of the last position update */
134
sourceType: Ref<UseMouseSourceType>;
135
/** Whether mouse is outside the element */
136
isOutside: Ref<boolean>;
137
/** Element width */
138
elementWidth: Ref<number>;
139
/** Element height */
140
elementHeight: Ref<number>;
141
/** Element x position */
142
elementX: Ref<number>;
143
/** Element y position */
144
elementY: Ref<number>;
145
/** Element position and size info */
146
elementPositionX: Ref<number>;
147
elementPositionY: Ref<number>;
148
/** Stop tracking */
149
stop: () => void;
150
}
151
```
152
153
**Usage Examples:**
154
155
```vue
156
<template>
157
<!-- Basic relative positioning -->
158
<UseMouseInElement v-slot="{ x, y, isOutside }">
159
<div class="mouse-area" :class="{ outside: isOutside }">
160
<p>Mouse position in element: {{ Math.round(x) }}, {{ Math.round(y) }}</p>
161
<p>{{ isOutside ? 'Outside' : 'Inside' }} element</p>
162
</div>
163
</UseMouseInElement>
164
165
<!-- All data -->
166
<UseMouseInElement v-slot="{ x, y, elementWidth, elementHeight, elementX, elementY, stop }">
167
<div class="detailed-area">
168
<h3>Mouse in Element Details</h3>
169
<p>Mouse: ({{ Math.round(x) }}, {{ Math.round(y) }})</p>
170
<p>Element size: {{ Math.round(elementWidth) }} × {{ Math.round(elementHeight) }}</p>
171
<p>Element position: ({{ Math.round(elementX) }}, {{ Math.round(elementY) }})</p>
172
<button @click="stop">Stop tracking</button>
173
</div>
174
</UseMouseInElement>
175
176
<!-- Handle outside disabled -->
177
<UseMouseInElement :handle-outside="false" v-slot="{ x, y, isOutside }">
178
<div class="no-outside-tracking">
179
Position: {{ x }}, {{ y }} (Outside tracking: disabled)
180
</div>
181
</UseMouseInElement>
182
</template>
183
184
<script setup>
185
import { UseMouseInElement } from '@vueuse/components';
186
</script>
187
188
<style>
189
.mouse-area, .detailed-area, .no-outside-tracking {
190
width: 300px;
191
height: 200px;
192
border: 2px solid #ccc;
193
padding: 20px;
194
margin: 20px 0;
195
background: #f9f9f9;
196
}
197
198
.outside {
199
background: #ffebee;
200
border-color: #f44336;
201
}
202
</style>
203
```
204
205
### vMouseInElement Directive
206
207
Directive for mouse-in-element tracking without component wrapper.
208
209
```typescript { .api }
210
/**
211
* Directive for tracking mouse position within element
212
* @example
213
* <div v-mouse-in-element="handleMouse">Track mouse</div>
214
* <div v-mouse-in-element="[handleMouse, options]">With options</div>
215
*/
216
type MouseInElementHandler = (state: UseMouseInElementReturn) => void;
217
218
interface VMouseInElementValue {
219
/** Simple handler function */
220
handler: MouseInElementHandler;
221
/** Handler with options tuple */
222
handlerWithOptions: [MouseInElementHandler, UseMouseInElementOptions];
223
}
224
225
interface UseMouseInElementOptions {
226
/** Handle outside element @default true */
227
handleOutside?: boolean;
228
/** Mouse position coordinate type @default 'page' */
229
type?: UseMouseCoordType | UseMouseEventExtractor;
230
/** Listen to touchmove events @default true */
231
touch?: boolean;
232
/** Reset to initial value when touchend event fired @default false */
233
resetOnTouchEnds?: boolean;
234
/** Initial position values */
235
initialValue?: Position;
236
/** Event filter for throttling/debouncing */
237
eventFilter?: EventFilter;
238
/** Window object @default defaultWindow */
239
window?: Window;
240
}
241
```
242
243
**Usage Examples:**
244
245
```vue
246
<template>
247
<!-- Simple tracking -->
248
<div v-mouse-in-element="handleMouse" class="tracking-element">
249
Mouse tracking element
250
</div>
251
252
<!-- With options -->
253
<div v-mouse-in-element="[handleMouse, { handleOutside: false, type: 'client' }]">
254
Client coordinates, no outside tracking
255
</div>
256
</template>
257
258
<script setup>
259
import { vMouseInElement } from '@vueuse/components';
260
261
function handleMouse(state) {
262
console.log('Mouse state:', {
263
x: state.x.value,
264
y: state.y.value,
265
isOutside: state.isOutside.value,
266
elementSize: {
267
width: state.elementWidth.value,
268
height: state.elementHeight.value
269
}
270
});
271
}
272
</script>
273
```
274
275
### UseMousePressed Component
276
277
Tracks mouse button press states.
278
279
```typescript { .api }
280
/**
281
* Component that tracks mouse button press state
282
* @example
283
* <UseMousePressed v-slot="{ pressed, sourceType }">
284
* <div>Pressed: {{ pressed }} ({{ sourceType }})</div>
285
* </UseMousePressed>
286
*/
287
interface UseMousePressedProps {
288
/** Touch support @default true */
289
touch?: boolean;
290
/** Drag support @default true */
291
drag?: boolean;
292
/** Capture events on window @default true */
293
capture?: boolean;
294
/** Initial pressed state @default false */
295
initialValue?: boolean;
296
/** Target element @default window */
297
target?: MaybeRefOrGetter<EventTarget | null | undefined>;
298
/** Window object @default defaultWindow */
299
window?: Window;
300
}
301
302
/** Slot data exposed by UseMousePressed component */
303
interface UseMousePressedReturn {
304
/** Whether any mouse button is pressed */
305
pressed: Ref<boolean>;
306
/** Source type of the press */
307
sourceType: Ref<UseMouseSourceType>;
308
}
309
```
310
311
**Usage Examples:**
312
313
```vue
314
<template>
315
<!-- Basic press tracking -->
316
<UseMousePressed v-slot="{ pressed, sourceType }">
317
<div class="press-tracker" :class="{ pressed }">
318
<p>{{ pressed ? 'PRESSED' : 'Not pressed' }}</p>
319
<p>Source: {{ sourceType || 'none' }}</p>
320
</div>
321
</UseMousePressed>
322
323
<!-- No touch support -->
324
<UseMousePressed :touch="false" v-slot="{ pressed }">
325
<div>Mouse only pressed: {{ pressed }}</div>
326
</UseMousePressed>
327
328
<!-- No drag support -->
329
<UseMousePressed :drag="false" v-slot="{ pressed, sourceType }">
330
<div>No drag tracking: {{ pressed }} ({{ sourceType }})</div>
331
</UseMousePressed>
332
</template>
333
334
<script setup>
335
import { UseMousePressed } from '@vueuse/components';
336
</script>
337
338
<style>
339
.press-tracker {
340
width: 200px;
341
height: 100px;
342
border: 2px solid #ccc;
343
display: flex;
344
flex-direction: column;
345
align-items: center;
346
justify-content: center;
347
background: #f9f9f9;
348
user-select: none;
349
cursor: pointer;
350
}
351
352
.press-tracker.pressed {
353
background: #e3f2fd;
354
border-color: #2196f3;
355
}
356
</style>
357
```
358
359
### UsePointer Component
360
361
Tracks pointer events supporting mouse, touch, and pen input.
362
363
```typescript { .api }
364
/**
365
* Component that tracks pointer events (mouse/touch/pen)
366
* @example
367
* <UsePointer v-slot="{ x, y, pointerType, pressure }">
368
* <div>{{ pointerType }}: {{ x }}, {{ y }} Pressure: {{ pressure }}</div>
369
* </UsePointer>
370
*/
371
interface UsePointerProps {
372
/** Target element @default window */
373
target?: MaybeRefOrGetter<EventTarget | null | undefined>;
374
/** Pointer types to capture @default ['mouse', 'touch', 'pen'] */
375
pointerTypes?: PointerType[];
376
/** Initial position values */
377
initialValue?: Position;
378
/** Window object @default defaultWindow */
379
window?: Window;
380
}
381
382
/** Slot data exposed by UsePointer component */
383
interface UsePointerReturn {
384
/** Whether pointer is pressed */
385
isInside: Ref<boolean>;
386
/** Pressure of the pointer input */
387
pressure: Ref<number>;
388
/** Type of pointer */
389
pointerType: Ref<PointerType>;
390
/** Current x position */
391
x: Ref<number>;
392
/** Current y position */
393
y: Ref<number>;
394
}
395
396
type PointerType = 'mouse' | 'touch' | 'pen';
397
```
398
399
**Usage Examples:**
400
401
```vue
402
<template>
403
<!-- Full pointer tracking -->
404
<UsePointer v-slot="{ x, y, pointerType, pressure, isInside }">
405
<div class="pointer-area" :class="{ inside: isInside }">
406
<h3>Pointer Information</h3>
407
<p>Position: {{ Math.round(x) }}, {{ Math.round(y) }}</p>
408
<p>Type: {{ pointerType }}</p>
409
<p>Pressure: {{ pressure.toFixed(3) }}</p>
410
<p>Inside: {{ isInside ? 'Yes' : 'No' }}</p>
411
</div>
412
</UsePointer>
413
414
<!-- Only pen input -->
415
<UsePointer :pointer-types="['pen']" v-slot="{ x, y, pressure }">
416
<div class="pen-area">
417
Pen only: {{ x }}, {{ y }} (Pressure: {{ pressure }})
418
</div>
419
</UsePointer>
420
421
<!-- Mouse and touch only -->
422
<UsePointer :pointer-types="['mouse', 'touch']" v-slot="{ pointerType, isInside }">
423
<button class="pointer-button" :class="{ active: isInside }">
424
{{ pointerType || 'No' }} pointer {{ isInside ? 'over' : 'away' }}
425
</button>
426
</UsePointer>
427
</template>
428
429
<script setup>
430
import { UsePointer } from '@vueuse/components';
431
</script>
432
433
<style>
434
.pointer-area, .pen-area {
435
width: 300px;
436
height: 200px;
437
border: 2px solid #ccc;
438
padding: 20px;
439
margin: 20px 0;
440
background: #f9f9f9;
441
touch-action: none;
442
}
443
444
.pointer-area.inside {
445
background: #e8f5e8;
446
border-color: #4caf50;
447
}
448
449
.pointer-button {
450
padding: 20px;
451
border: 2px solid #ccc;
452
background: #f9f9f9;
453
cursor: pointer;
454
}
455
456
.pointer-button.active {
457
background: #e3f2fd;
458
border-color: #2196f3;
459
}
460
</style>
461
```
462
463
## Type Definitions
464
465
```typescript { .api }
466
/** Common types used across mouse and pointer components */
467
type MaybeRefOrGetter<T> = T | Ref<T> | (() => T);
468
469
interface Position {
470
x: number;
471
y: number;
472
}
473
474
interface RenderableComponent {
475
/** The element that the component should be rendered as @default 'div' */
476
as?: object | string;
477
}
478
479
/** Pointer and mouse types */
480
type PointerType = 'mouse' | 'touch' | 'pen';
481
type UseMouseSourceType = 'mouse' | 'touch' | null;
482
type UseMouseCoordType = 'page' | 'client' | 'screen' | 'movement';
483
484
/** Event filter for throttling/debouncing */
485
interface EventFilter {
486
(invoke: () => void, options: any): void;
487
}
488
489
/** Mouse event extractor function type */
490
type UseMouseEventExtractor = (event: MouseEvent | Touch) => [x: number, y: number] | null | undefined;
491
```