useMouse hook

This commit is contained in:
Ward Oosterlijnck 2019-03-25 22:18:35 +11:00 committed by Va Da
parent 74cbb1eaca
commit e8b43ea95c
5 changed files with 121 additions and 0 deletions

View File

@ -42,6 +42,7 @@
- [`useMedia`](./docs/useMedia.md) — tracks state of a CSS media query. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usemedia--demo)
- [`useMediaDevices`](./docs/useMediaDevices.md) — tracks state of connected hardware devices.
- [`useMotion`](./docs/useMotion.md) — tracks state of device's motion sensor.
- [`useMouse`](./docs/useMouse.md) — tracks state of mouse position. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usemouse--docs)
- [`useNetwork`](./docs/useNetwork.md) — tracks state of user's internet connection.
- [`useOrientation`](./docs/useOrientation.md) — tracks state of device's screen orientation.
- [`useScroll`](./docs/useScroll.md) — tracks some HTML element's scroll position. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usescroll--docs)

23
docs/useMouse.md Normal file
View File

@ -0,0 +1,23 @@
# `useMouse`
React sensor hook that re-renders on mouse position changes.
## Usage
```jsx
import {useMouse} from 'react-use';
const Demo = () => {
const ref = React.useRef(null);
const {docX, docY, posX, posY, elX, elY, elW, elH} = useScroll(ref);
return (
<div ref={element}>
<div>Mouse position in document - x:{docX} y:{docY}</div>
<div>Mouse position in element - x:{posX} y:{posY}</div>
<div>Element position - x:{elX} y:{elY}</div>
<div>Element dimensions - {elW}x{elH}</div>
</div>
);
};
```

View File

@ -0,0 +1,32 @@
import * as React from 'react';
import {storiesOf} from '@storybook/react';
import {useMouse} from '..';
import ShowDocs from '../util/ShowDocs';
const Demo = () => {
const ref = React.useRef(null);
const state = useMouse(ref);
return (
<>
<pre>
{JSON.stringify(state, null, 2)}
</pre>
<div
ref={ref}
style={{
width: '400px',
height: '400px',
backgroundColor: 'whitesmoke',
}}>
Move your mouse over me
</div>
</>
);
};
storiesOf('Sensors|useMouse', module)
.add('Docs', () => <ShowDocs md={require('../../docs/useMouse.md')} />)
.add('Demo', () =>
<Demo/>
)

View File

@ -27,6 +27,7 @@ import useMedia from './useMedia';
import useMediaDevices from './useMediaDevices';
import useMotion from './useMotion';
import useMount from './useMount';
import useMouse from './useMouse';
import useNetwork from './useNetwork';
import useNumber from './useNumber';
import useObservable from './useObservable';
@ -84,6 +85,7 @@ export {
useMediaDevices,
useMotion,
useMount,
useMouse,
useNetwork,
useNumber,
useObservable,

63
src/useMouse.ts Normal file
View File

@ -0,0 +1,63 @@
import {useState, useEffect, useRef, RefObject} from 'react';
export interface State {
docX: number;
docY: number;
posX: number;
posY: number;
elX: number;
elY: number;
elH: number;
elW: number;
}
const useMouse = (ref: RefObject<HTMLElement>): State => {
const frame = useRef(0);
const [state, setState] = useState<State>({
docX: 0,
docY: 0,
posX: 0,
posY: 0,
elX: 0,
elY: 0,
elH: 0,
elW: 0,
});
useEffect(() => {
const handler = (event: MouseEvent) => {
frame.current = requestAnimationFrame(() => {
if (ref && ref.current) {
const {left, top} = ref.current.getBoundingClientRect()
const posX = left + window.scrollX;
const posY = top + window.scrollY;
setState({
docX: event.pageX,
docY: event.pageY,
posX,
posY,
elX: event.pageX - posX,
elY: event.pageY - posY,
elH: ref.current.offsetHeight,
elW: ref.current.offsetWidth,
});
}
});
}
document.addEventListener('mousemove', handler);
return () => {
if (frame.current) {
cancelAnimationFrame(frame.current);
}
document.addEventListener('mousemove', handler);
};
}, []);
return state;
}
export default useMouse