1+ import { onScopeDispose , reactive , ref } from 'vue'
2+ import { useGlobalEventListener } from '@/useGlobalEventListener'
3+
4+ export type MousePosition = {
5+ x : number ,
6+ y : number ,
7+ }
8+
9+ export type UseMousePosition = {
10+ position : MousePosition ,
11+ positionAtLastClick : MousePosition ,
12+ }
13+
14+ const position = reactive < MousePosition > ( { x : 0 , y : 0 } )
15+ const positionAtLastClick = reactive < MousePosition > ( { x : 0 , y : 0 } )
16+
17+ const updatePositionAtLastClick = ( ) : void => {
18+ Object . assign ( positionAtLastClick , position )
19+ }
20+
21+ const updateMousePosition = ( event : MouseEvent ) : void => {
22+ position . x = event . clientX
23+ position . y = event . clientY
24+
25+ if ( positionAtLastClick . x === 0 && positionAtLastClick . y === 0 ) {
26+ updatePositionAtLastClick ( )
27+ }
28+ }
29+
30+ const listeners = ref ( 0 )
31+
32+ const { add : addMouseMoveEventListener , remove : removeMouseMoveEventListener } = useGlobalEventListener ( 'mousemove' , updateMousePosition , { passive : true } )
33+ const { add : addClickEventListener , remove : removeClickEventListener } = useGlobalEventListener ( 'click' , updatePositionAtLastClick , { capture : true } )
34+ const { add : addContextMenuEventListener , remove : removeContextMenuEventListener } = useGlobalEventListener ( 'contextmenu' , updatePositionAtLastClick , { capture : true } )
35+
36+ function tryTeardownEventListeners ( ) : void {
37+ if ( listeners . value > 0 ) {
38+ return
39+ }
40+
41+ removeMouseMoveEventListener ( )
42+ removeClickEventListener ( )
43+ removeContextMenuEventListener ( )
44+ }
45+
46+ function addEventListeners ( ) : void {
47+ // These have no effect if the event listeners are already added
48+ addMouseMoveEventListener ( )
49+ addClickEventListener ( )
50+ addContextMenuEventListener ( )
51+ }
52+
53+ export function useMousePosition ( ) : UseMousePosition {
54+ listeners . value += 1
55+
56+ addEventListeners ( )
57+
58+ onScopeDispose ( ( ) => {
59+ listeners . value -= 1
60+ tryTeardownEventListeners ( )
61+ } )
62+
63+ return {
64+ position,
65+ positionAtLastClick,
66+ }
67+ }
0 commit comments