@smoovy/observer
Version:
Simple and easy-to-use ticker
176 lines (141 loc) • 4.34 kB
Markdown
# @smoovy/observer
[](https://www.npmjs.com/package/@smoovy/observer) 
Easily observe states of HTML elements and the viewport.
## Installation
```sh
yarn add @smoovy/observer
```
or
```sh
npm install --save @smoovy/observer
```
## Why?!
Operations like `window.innerWidth` and `element.offsetTop` will have an impact on the performance if not used properly. So this package is useful to avoid [layout thrashing](https://devhints.io/layout-thrashing) by batching all of the expensive calls together and only executing them if needed.
## Usage
For most use cases using the exposed `observe` and `unobserve` methods is sufficient.
### Observing the window
```js
import { observe } from '@smoovy/observer';
const observable = observe(window);
const unlisten = observable.onChange(() => {
console.log(`The viewport size is ${observable.width}x${observable.height}`);
});
```
To remove the listener and observable you can simply call the the `unobserve` method:
```js
import { unobserve } from '@smoovy/observer';
// Remove update listener
unlisten();
// Remove observable from detection
unobserve(observable);
```
#### Throttling the update listener calls
This will throttle the update callback to **100ms**:
```js
import { throttle } from '@smoovy/utils/throttle';
const observable = observe(window).onChange(
throttle(() => {}, 100)
);
```
#### Updating the observable manually
```js
observable.update();
```
#### When does a viewport update occur?
The update callback is called everytime the user triggers the `resize` event on
the `window` or through `ResizeObserver`s change detection.
### Observing an element
Observing elements works through the same API as with the window.
```js
import { observe } from '@smoovy/observer';
const element = document.querySelector('#test');
const observable = observe(element, {
visibilityDetection: true,
resizeDetection: true
});
```
#### Listening/Unlistening for element updates
```js
const listener = observable.onChange(({ size, coord }) => {
console.log('Element bounds:', size);
console.log('Element page offset:', coord);
});
// Stop listening
listener();
```
#### Updating the element state manually
```js
observable.update();
```
#### Removing the element state from the observer
```js
import { unobserve } from '@smoovy/observer';
unobserve(observable);
```
#### Listening for visibility and dimension changes separately
The `onChange` callback bundles the `onDimChnage` and `onVisChange` callback
together. You can listen to either of those separately:
```js
const listenerVis = observable.onVisChange(() => {
console.log('Element is now', observable.visible);
});
const listenerDim = observable.onDimChange(() => {
console.log('Element has changed size', observable.size, observable.pos);
});
```
### Further configurations
```js
/**
* The target to observe. Can be HTMLElement or Window
*/
target: HTMLElement | Window;
/**
* Use `getBoundingClientRect()` instead of offsetWidth etc.
*
* Default = false
*/
useBounds?: boolean;
/**
* Automatically listen for changes, resizes and updates once created
*
* Default = true
*/
autoAttach?: boolean;
/**
* Whether to use visibility detection via the IntersectionObserver API.
* You can configure it with a custom threshold.
*
* Default = false
*/
visibilityDetection?: boolean | IntersectionObserverInit;
/**
* If `visiblityDetection` is enabled, this will delay the visibile
* event by a defined number (ms)
*
* Default = 0
*/
visibilityDelay?: number;
/**
* If `visibiltiyDetection` is enabled, remove the target from the
* IntersectionObserver once it has been marked as visible
*
* Default = false
*/
detectVisibilityOnce?: boolean;
/**
* Whether to detect dimension changes via the ResizeObserver API
*
* Default = false
*/
resizeDetection?: boolean | ResizeObserverOptions;
/**
* Debounce is the number of milliseconds to wait for the next change.
* So if the delta value is below this threshold the resize event will
* be discarded and therefore the observable will not be updated.
*
* Default = 16.6
*/
resizeDebounce?: number;
```
## License
See the [LICENSE](../../LICENSE) file for license rights and limitations (MIT).