UNPKG

@phucbm/magnetic-button

Version:

A lightweight TypeScript library that creates smooth magnetic attraction effects for HTML elements

349 lines (258 loc) 10.5 kB
# 🧲 Magnetic Button A lightweight TypeScript library that creates smooth magnetic attraction effects for HTML elements. Elements with the `data-magnetic` attribute will gently follow the mouse cursor when it's nearby, creating an engaging hover interaction. [![npm version](https://badgen.net/npm/v/@phucbm/magnetic-button?icon=npm)](https://www.npmjs.com/package/@phucbm/magnetic-button) [![npm downloads](https://badgen.net/npm/dm/@phucbm/magnetic-button?icon=npm)](https://www.npmjs.com/package/@phucbm/magnetic-button) [![npm downloads](https://badgen.net/npm/dependents/@phucbm/magnetic-button?icon=npm)](https://www.npmjs.com/package/@phucbm/magnetic-button) [![jsdelivr hits](https://badgen.net/jsdelivr/hits/gh/phucbm/magnetic-button?icon=jsdelivr)](https://www.jsdelivr.com/package/gh/phucbm/magnetic-button) [![GitHub release](https://badgen.net/jsdelivr/rank/npm/@phucbm/magnetic-button?icon=jsdelivr)](https://github.com/phucbm/magnetic-button/releases) [![pages-build-deployment](https://github.com/phucbm/magnetic-button/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/phucbm/magnetic-button/actions/workflows/pages/pages-build-deployment) [![Publish on Release](https://github.com/phucbm/magnetic-button/actions/workflows/publish-on-release.yml/badge.svg)](https://github.com/phucbm/magnetic-button/actions/workflows/publish-on-release.yml) [![license](https://badgen.net/github/license/phucbm/magnetic-button?icon=github)](https://github.com/phucbm/magnetic-button/blob/main/LICENSE) [![Made in Vietnam](https://raw.githubusercontent.com/webuild-community/badge/master/svg/made.svg)](https://webuild.community) ## ✨ Features - **Zero dependencies** - Lightweight and fast - **TypeScript support** - Full type definitions included - **Auto-initialization** - Works with data attributes out of the box - **Customizable** - Fine-tune distance, attraction, and animation speed - **Smooth animations** - Uses linear interpolation for buttery smooth movement - **Event callbacks** - Hook into enter, exit, and update events - **Modern browsers** - Works in all modern browsers that support ES2022 ## 🚀 Demo Check out the [live demo](https://phucbm.github.io/magnetic-button/) to see the magnetic effect in action! ## 📦 Installation ### npm ```bash npm install @phucbm/magnetic-button ``` ### pnpm ```bash pnpm add @phucbm/magnetic-button ``` ### yarn ```bash yarn add @phucbm/magnetic-button ``` ### CDN ```html <script type="module"> import {MagneticButton} from 'https://unpkg.com/@phucbm/magnetic-button/dist/index.js' new MagneticButton() </script> ``` ```html <script src="https://unpkg.com/@phucbm/magnetic-button/dist/magnetic-button.js"></script> <script> // MagneticButton is available on the window object const magnetic = new window.MagneticButton() </script> ``` ## 🎯 Quick Start ### HTML + Data Attributes (Easiest) ```html <!DOCTYPE html> <html> <head> <style> .magnetic-btn { padding:1rem 2rem; border:2px solid #333; background:#1a1a1a; color:white; border-radius:8px; cursor:pointer; transition:border-color 0.3s ease; } .magnetic-btn.magnetizing { border-color:#ff6b6b; box-shadow:0 0 20px rgba(255, 107, 107, 0.3); } </style> </head> <body> <!-- Basic usage --> <button class="magnetic-btn" data-magnetic> Hover me! </button> <!-- With custom parameters --> <button class="magnetic-btn" data-magnetic data-distance="150" data-attraction="0.3" data-fraction="0.2"> Custom magnetic button </button> <script type="module"> import {MagneticButton} from '@phucbm/magnetic-button' new MagneticButton() // Auto-initializes all elements with data-magnetic </script> </body> </html> ``` ### JavaScript/TypeScript ```typescript import {MagneticButton} from '@phucbm/magnetic-button' // Auto-initialize all elements with data-magnetic attribute new MagneticButton() // Or target a specific element const button = document.querySelector('.my-button') new MagneticButton(button, { distance: 200, attraction: 0.5, fraction: 0.1, onEnter: (data) => console.log('Magnetized!', data), onExit: (data) => console.log('Released!', data) }) ``` ## ⚙️ Configuration Options ### Data Attributes Add these attributes to your HTML elements to customize the magnetic effect: | Attribute | Type | Default | Description | |-------------------|----------|---------|-----------------------------------------------------------| | `data-magnetic` | - | - | **Required**. Enables magnetic effect on the element | | `data-distance` | `number` | `200` | Range within which the magnetic effect is active (pixels) | | `data-attraction` | `number` | `0.3` | Strength of magnetic pull (0 = strong, 1 = weak) | | `data-fraction` | `number` | `0.1` | Speed of magnetic movement (0 = instant, 1 = slow) | ### JavaScript Options When initializing with JavaScript, you can pass these options: | Option | Type | Default | Description | |---------------|------------|-----------------|-------------------------------------------------------| | `activeClass` | `string` | `'magnetizing'` | CSS class added when magnetic effect is active | | `attraction` | `number` | `0.3` | Strength of magnetic pull (0 = strong, 1 = weak) | | `distance` | `number` | `200` | Range within which magnetic effect is active (pixels) | | `fraction` | `number` | `0.1` | Speed of magnetic movement (0 = instant, 1 = slow) | | `onEnter` | `function` | `() => {}` | Callback fired when mouse enters magnetic area | | `onExit` | `function` | `() => {}` | Callback fired when mouse exits magnetic area | | `onUpdate` | `function` | `() => {}` | Callback fired continuously while in magnetic area | ## 🎭 CSS Classes The library automatically adds CSS classes that you can style: | Class | When Applied | Description | |------------------|--------------|-----------------------------------------------------------------------------------| | `.is-magnetized` | Always | Added to all magnetic elements for identification | | `.magnetizing` | On hover | Added when mouse is within magnetic range (customizable via `activeClass` option) | ## 📋 API Reference ### Constructor ```typescript new MagneticButton(target ? : HTMLElement | null, options ? : MagneticButtonOptions) ``` **Parameters:** - `target` - The HTML element to apply magnetic effect to. If `null` or omitted, auto-initializes all elements with `data-magnetic` attribute - `options` - Configuration options (see table above) ### Event Data Callback functions receive a `MagneticData` object with the following properties: | Property | Type | Description | |------------|----------|-------------------------------------------| | `deltaX` | `number` | Horizontal offset from element center | | `deltaY` | `number` | Vertical offset from element center | | `distance` | `number` | Distance between mouse and element center | ## 🎨 Examples ### Strong Attraction ```html <button data-magnetic data-distance="120" data-attraction="0.1"> Strong Pull </button> ``` ### Subtle Effect ```html <button data-magnetic data-distance="80" data-attraction="0.8" data-fraction="0.05"> Subtle Movement </button> ``` ### Large Detection Area ```html <button data-magnetic data-distance="300" data-attraction="0.4"> Wide Range </button> ``` ### With Event Callbacks ```typescript new MagneticButton(document.querySelector('.special-btn'), { distance: 150, attraction: 0.3, onEnter: (data) => { console.log('Entered magnetic field!') // Play sound, trigger animation, etc. }, onExit: (data) => { console.log('Left magnetic field!') // Reset state, stop animation, etc. }, onUpdate: (data) => { // Update UI based on mouse position if (data.distance < 50) { console.log('Very close to button!') } } }) ``` ## 🎯 Tips and Best Practices ### Performance - The library is optimized and uses `requestAnimationFrame` internally - Avoid initializing too many magnetic elements simultaneously (recommended max: ~20-30) ### CSS Styling ```css /* Smooth transitions for non-magnetic properties */ .magnetic-btn { transition:border-color 0.3s ease, box-shadow 0.3s ease; } /* Active state styling */ .magnetic-btn.magnetizing { border-color:#ff6b6b; box-shadow:0 0 20px rgba(255, 107, 107, 0.3); } /* Ensure transform doesn't interfere with other transforms */ .magnetic-btn { transform-origin:center; } ``` ### Accessibility The magnetic effect doesn't interfere with keyboard navigation or screen readers, making it accessible by default. ### Framework Integration **React:** ```jsx import {useEffect, useRef} from 'react' import {MagneticButton} from '@phucbm/magnetic-button' function MyButton(){ const buttonRef = useRef(null) useEffect(() => { const magnetic = new MagneticButton(buttonRef.current, { distance: 150, attraction: 0.3 }) }, []) return <button ref={buttonRef}>Magnetic Button</button> } ``` **Vue:** ```vue <template> <button ref="buttonRef">Magnetic Button</button> </template> <script setup> import {ref, onMounted} from 'vue' import {MagneticButton} from '@phucbm/magnetic-button' const buttonRef = ref(null) onMounted(() => { new MagneticButton(buttonRef.value, { distance: 150, attraction: 0.3 }) }) </script> ``` ## 🌐 Browser Support - Chrome 63+ - Firefox 61+ - Safari 13.1+ - Edge 79+ ## 📄 License MIT © [phucbm](https://github.com/phucbm) ## 🤝 Contributing Contributions are welcome! Please feel free to submit a Pull Request. ## 🔗 Links - [GitHub Repository](https://github.com/phucbm/magnetic-button) - [Live Demo](https://phucbm.github.io/magnetic-button/) - [npm Package](https://www.npmjs.com/package/@phucbm/magnetic-button)