Skip to content

Commit

Permalink
feat: visibleOnState option
Browse files Browse the repository at this point in the history
fix: state resolving
  • Loading branch information
Drafteed committed May 11, 2022
1 parent 234a337 commit 7ff8a78
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 41 deletions.
72 changes: 39 additions & 33 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ You can configure cursor follower via options:

```js
const cursor = new MouseFollower({
container: ".mf-container",
container: '.mf-container',
speed: 0.3
});
```
Expand All @@ -60,26 +60,28 @@ The following options with defaults are available:
const cursor = new MouseFollower({
el: null,
container: document.body,
className: "mf-cursor",
innerClassName: "mf-cursor-inner",
textClassName: "mf-cursor-text",
mediaClassName: "mf-cursor-media",
mediaBoxClassName: "mf-cursor-media-box",
iconSvgClassName: "mf-svgsprite",
iconSvgStatePrefix: "-",
iconSvgSrc: "",
dataAttr: "cursor",
hiddenState: "-hidden",
textState: "-text",
iconState: "-icon",
activeState: "-active",
mediaState: "-media",
className: 'mf-cursor',
innerClassName: 'mf-cursor-inner',
textClassName: 'mf-cursor-text',
mediaClassName: 'mf-cursor-media',
mediaBoxClassName: 'mf-cursor-media-box',
iconSvgClassName: 'mf-svgsprite',
iconSvgNamePrefix: '-',
iconSvgSrc: '',
dataAttr: 'cursor',
hiddenState: '-hidden',
textState: '-text',
iconState: '-icon',
activeState: '-active',
mediaState: '-media',
stateDetection: {
"-pointer": "a,button",
"-hidden": "iframe"
'-pointer': 'a,button',
'-hidden': 'iframe'
},
visible: true,
visibleOnState: false,
speed: 0.55,
ease: "expo.out",
ease: 'expo.out',
overwrite: true,
skewing: 0,
skewingText: 2,
Expand All @@ -89,11 +91,9 @@ const cursor = new MouseFollower({
skewingDeltaMax: 0.15,
stickDelta: 0.15,
showTimeout: 20,
showOnEnter: true,
hideOnLeave: true,
hideTimeout: 300,
hideMediaTimeout: 300,
initialPos: [-window.innerWidth, -window.innerHeight],
hideMediaTimeout: 300
});
```

Expand All @@ -115,7 +115,8 @@ const cursor = new MouseFollower({
| `iconState` | `string` | Icon class name state. |
| `activeState` | `string` | Active (mousedown) class name state. |
| `mediaState` | `string` | Media (image/video) class name state. |
| `visible` | `number` | Show the cursor when mouse enter container. This also means that the cursor will be visible by default. |
| `visible` | `boolean` | Is cursor visible by default. |
| `visibleOnState` | `boolean` | Automatically show/hide cursor when state added. Can be useful when implementing a hidden cursor follower. |
| `stateDetection` | `object` | `null` | Allow to set predefined states for different elements on page. Uses an event delegation. |
| `speed` | `number` | Cursor movement speed. |
| `ease` | `string` | Timing function of cursor movement. See [gsap easing](https://greensock.com/docs/v3/Eases). |
Expand All @@ -130,7 +131,7 @@ const cursor = new MouseFollower({
| `showTimeout` | `number` | Delay before show. May be useful for the spawn animation to work properly. |
| `hideOnLeave` | `boolean` | Hide the cursor when mouse leave container. |
| `hideTimeout` | `number` | Hiding delay. Should be equal to the CSS hide animation time. |
| `initialPos` | `array` | Array (X, Y) of initial cursor position. |
| `initialPos` | `array` | Array (x, y) of initial cursor position. |

## Advanced usage

Expand Down Expand Up @@ -159,7 +160,8 @@ or via data attribute:

### Toggle cursor state

A state is essentially a class that applies to the root element of the cursor. You can change the appearance of the cursor using CSS (see `cursor.scss`).
A state is essentially a class that applies to the root element of the cursor. You can change the appearance of the
cursor using CSS (see `cursor.scss`).

To set/unset state use methods:

Expand Down Expand Up @@ -189,9 +191,9 @@ You can customize the list of states for all elements on the page:
```js
const cursor = new MouseFollower({
stateDetection: {
"-pointer": "a,button",
"-opaque": ".my-image",
"-hidden": ".my-input"
'-pointer': 'a,button',
'-opaque': '.my-image',
'-hidden': '.my-input'
}
});
```
Expand All @@ -202,7 +204,9 @@ const cursor = new MouseFollower({
<div class="mf-input">On this element cursor will be hidden</div>
```

Note: State detection feature uses an event delegation. Do not create large amount rules and complex selectors to avoid performance problems. It is recommended to disable this in projects with a large number of nested DOM elements. This also applies to binding via data attribute.
Note: State detection feature uses an event delegation. Do not create large amount rules and complex selectors to avoid
performance problems. It is recommended to disable this in projects with a large number of nested DOM elements. This
also applies to binding via data attribute.

To fully disable event delegation:

Expand Down Expand Up @@ -238,13 +242,14 @@ or via data attribute:

### Icon mode

If you use SVG spritesheet in your project and want to display them in the cursor, then you can use this method. In this case, you need to specify the path to the SVG sprite in the options and set class names.
If you use SVG spritesheet in your project and want to display them in the cursor, then you can use this method. In this
case, you need to specify the path to the SVG sprite in the options and set class names.

```js
const cursor = new MouseFollower({
iconSvgSrc: "/assets/img/sprites/svgsprites.svg",
iconSvgClassName: "my-spritesheet",
iconSvgNamePrefix: "-",
iconSvgSrc: '/assets/img/sprites/svgsprites.svg',
iconSvgClassName: 'my-spritesheet',
iconSvgNamePrefix: '-',
});
const el = document.querySelector('.my-element');

Expand Down Expand Up @@ -311,7 +316,8 @@ or via data attribute:

### Sticky effect

This method allows you to attach the cursor to an element with a magnet effect. This only works correctly with fixed elements on the page.
This method allows you to attach the cursor to an element with a magnet effect. This only works correctly with fixed
elements on the page.

```js
const cursor = new MouseFollower();
Expand Down
26 changes: 18 additions & 8 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default class MouseFollower {
* @param {HTMLElement|null} options.container Cursor container.
* @param {string} options.className Cursor root element class name.
* @param {string} options.innerClassName Inner element class name.
* @param {string} options.textClassName Text element class name.
* @param {string} options.mediaClassName Media element class name.
* @param {string} options.mediaBoxClassName Media inner element class name.
* @param {string} options.iconSvgClassName SVG sprite class name.
Expand All @@ -35,8 +36,9 @@ export default class MouseFollower {
* @param {string} options.iconState Icon state name.
* @param {string} options.activeState Active (mousedown) state name.
* @param {string} options.mediaState Media (image/video) state name.
* @param {string} options.visible Is cursor visible by default.
* @param {object} options.stateDetection State detection rules.
* @param {boolean} options.visible Is cursor visible by default.
* @param {boolean} options.visibleOnState Automatically show/hide cursor when state added.
* @param {number} options.speed Cursor movement speed.
* @param {string} options.ease Timing function of cursor movement.
* @param {boolean} options.overwrite Overwrite or remain cursor position when `mousemove` event happens.
Expand All @@ -50,7 +52,7 @@ export default class MouseFollower {
* @param {number} options.showTimeout Delay before show.
* @param {boolean} options.hideOnLeave Hide the cursor when mouse leave container.
* @param {number} options.hideTimeout Delay before hiding. It should be equal to the CSS hide animation time.
* @param {array} options.initialPos Array (X, Y) of initial cursor position.
* @param {array} options.initialPos Array (x, y) of initial cursor position.
*/
constructor(options) {
this.gsap = MouseFollower.gsap || window.gsap;
Expand All @@ -73,9 +75,9 @@ export default class MouseFollower {
mediaState: '-media',
stateDetection: {
'-pointer': 'a,button',
'-hidden': 'iframe',
},
visible: true,
visibleOnState: false,
speed: 0.55,
ease: 'expo.out',
overwrite: true,
Expand All @@ -93,6 +95,8 @@ export default class MouseFollower {
initialPos: [-window.innerWidth, -window.innerHeight],
}, options);

if (this.options.visible && !options.stateDetection) this.options.stateDetection['-hidden'] = 'iframe';

this.el = typeof (this.options.el) === 'string' ?
document.querySelector(this.options.el) : this.options.el;
this.container = typeof (this.options.container) === 'string' ?
Expand Down Expand Up @@ -295,10 +299,10 @@ export default class MouseFollower {
/**
* Toggle cursor.
*
* @param {boolean} [force=false] Force state.
* @param {boolean} [force] Force state.
*/
toggle(force = false) {
if (!this.visible || force) {
toggle(force) {
if (force === true || force !== false && !this.visible) {
this.show();
} else {
this.hide();
Expand All @@ -314,6 +318,7 @@ export default class MouseFollower {
this.trigger('addState', state);
if (state === this.options.hiddenState) return this.hide();
this.el.classList.add(...state.split(' '));
if (this.options.visibleOnState) this.show();
}

/**
Expand All @@ -325,16 +330,21 @@ export default class MouseFollower {
this.trigger('removeState', state);
if (state === this.options.hiddenState) return this.show();
this.el.classList.remove(...state.split(' '));
if (this.options.visibleOnState && this.el.className === this.options.className) this.hide();
}

/**
* Toggle cursor state.
*
* @param {string} state State name.
* @param {boolean} force Force state.
* @param {boolean} [force] Force state.
*/
toggleState(state, force) {
this.el.classList.toggle(`${state}`, force);
if (force === true || force !== false && !this.el.classList.contains(state)) {
this.addState(state);
} else {
this.removeState(state);
}
}

/**
Expand Down

0 comments on commit 7ff8a78

Please sign in to comment.