|
1 | | -# pointer.js |
2 | | -Pointer-related methods for use in browsers. |
| 1 | +# @litert/pointer |
| 2 | + |
| 3 | +<p align="center"> |
| 4 | + <a href="https://github.com/litert/pointer.js/blob/main/LICENSE"> |
| 5 | + <img alt="License" src="https://img.shields.io/github/license/litert/pointer.js?color=blue" /> |
| 6 | + </a> |
| 7 | + <a href="https://www.npmjs.com/package/@litert/pointer"> |
| 8 | + <img alt="NPM stable version" src="https://img.shields.io/npm/v/@litert/pointer?color=brightgreen&logo=npm" /> |
| 9 | + </a> |
| 10 | + <a href="https://github.com/litert/pointer.js/releases"> |
| 11 | + <img alt="GitHub releases" src="https://img.shields.io/github/v/release/litert/pointer.js?color=brightgreen&logo=github" /> |
| 12 | + </a> |
| 13 | + <a href="https://github.com/litert/pointer.js/issues"> |
| 14 | + <img alt="GitHub issues" src="https://img.shields.io/github/issues/litert/pointer.js?color=blue&logo=github" /> |
| 15 | + </a> |
| 16 | +</p> |
| 17 | + |
| 18 | +A lightweight pointer event library for handling mouse and touch interactions in browsers. Provides unified APIs for down, move, click, long, drag, resize and more. |
| 19 | + |
| 20 | +## Features |
| 21 | + |
| 22 | +- 🖱️ Unified mouse and touch event handling |
| 23 | +- 📱 Mobile-friendly with touch support |
| 24 | +- 🎯 Click, double-click, and long-press detection |
| 25 | +- 🔄 Drag and drop with customizable constraints |
| 26 | +- 📐 Resize functionality with border detection |
| 27 | +- 🎨 Global cursor management |
| 28 | +- 📦 Zero dependencies |
| 29 | +- 🔷 Full TypeScript support |
| 30 | +- 🌐 ESM and UMD bundle support |
| 31 | + |
| 32 | +## Installation |
| 33 | + |
| 34 | +### NPM |
| 35 | + |
| 36 | +```bash |
| 37 | +npm install @litert/pointer |
| 38 | +``` |
| 39 | + |
| 40 | +### CDN |
| 41 | + |
| 42 | +```html |
| 43 | +<!-- UMD (Development) --> |
| 44 | +<script src="https://unpkg.com/@litert/pointer/dist/index.umd.js"></script> |
| 45 | + |
| 46 | +<!-- UMD (Production, minified) --> |
| 47 | +<script src="https://unpkg.com/@litert/pointer/dist/index.umd.min.js"></script> |
| 48 | +``` |
| 49 | + |
| 50 | +## Usage |
| 51 | + |
| 52 | +### ESM (Recommended) |
| 53 | + |
| 54 | +```typescript |
| 55 | +import * as pointer from '@litert/pointer'; |
| 56 | + |
| 57 | +element.addEventListener('mousedown', (e) => { |
| 58 | + pointer.move(e, { |
| 59 | + move: (e, detail) => { |
| 60 | + console.log('Moving:', detail.ox, detail.oy); |
| 61 | + } |
| 62 | + }); |
| 63 | +}); |
| 64 | +``` |
| 65 | + |
| 66 | +### Browser (UMD) |
| 67 | + |
| 68 | +```html |
| 69 | +<script src="https://unpkg.com/@litert/pointer/dist/index.umd.min.js"></script> |
| 70 | +<script> |
| 71 | +element.addEventListener('mousedown', function(e) { |
| 72 | + pointer.move(e, { |
| 73 | + move: function(e, detail) { |
| 74 | + console.log('Moving:', detail.ox, detail.oy); |
| 75 | + } |
| 76 | + }); |
| 77 | +}); |
| 78 | +</script> |
| 79 | +``` |
| 80 | + |
| 81 | +## API Reference |
| 82 | + |
| 83 | +### Core Functions |
| 84 | + |
| 85 | +#### `down(e, options)` |
| 86 | + |
| 87 | +Down and up events, bindto one of touch or mouse. |
| 88 | + |
| 89 | +```typescript |
| 90 | +pointer.down(e, { |
| 91 | + down: (e) => { /* Triggered when pressed */ }, |
| 92 | + start: (e) => { /* Triggered when start moving, return false to cancel subsequent events */ }, |
| 93 | + move: (e, dir) => { /* Triggered when moving, dir is the direction of movement */ }, |
| 94 | + up: (e) => { /* Triggered when released */ }, |
| 95 | + end: (e) => { /* Triggered when moving ends */ } |
| 96 | +}); |
| 97 | +``` |
| 98 | + |
| 99 | +#### `click(e, handler)` |
| 100 | + |
| 101 | +Click takes effect only when the mouse/finger does not move and the time is less than 250ms. |
| 102 | + |
| 103 | +```typescript |
| 104 | +element.addEventListener('mousedown', (e) => { |
| 105 | + pointer.click(e, (e, x, y) => { |
| 106 | + console.log('Clicked at:', x, y); |
| 107 | + }); |
| 108 | +}); |
| 109 | +``` |
| 110 | + |
| 111 | +#### `dblClick(e, handler)` |
| 112 | + |
| 113 | +Double-click event, the interval between two clicks is less than 300ms and the position difference is less than 10px. |
| 114 | + |
| 115 | +```typescript |
| 116 | +element.addEventListener('mousedown', (e) => { |
| 117 | + pointer.dblClick(e, (e, x, y) => { |
| 118 | + console.log('Double clicked at:', x, y); |
| 119 | + }); |
| 120 | +}); |
| 121 | +``` |
| 122 | + |
| 123 | +#### `long(e, handler, time?)` |
| 124 | + |
| 125 | +Long press event, default 500ms. |
| 126 | + |
| 127 | +```typescript |
| 128 | +element.addEventListener('mousedown', (e) => { |
| 129 | + pointer.long(e, (e) => { |
| 130 | + console.log('Long press detected!'); |
| 131 | + }, 500); |
| 132 | +}); |
| 133 | +``` |
| 134 | + |
| 135 | +#### `move(e, options)` |
| 136 | + |
| 137 | +Drag event, supports boundary detection and constraints. |
| 138 | + |
| 139 | +```typescript |
| 140 | +element.addEventListener('mousedown', (e) => { |
| 141 | + pointer.move(e, { |
| 142 | + // --- Constraint area --- |
| 143 | + left: 0, |
| 144 | + top: 0, |
| 145 | + right: window.innerWidth, |
| 146 | + bottom: window.innerHeight, |
| 147 | + // --- Or use an element as a constraint area --- |
| 148 | + // areaObject: document.getElementById('container'), |
| 149 | + // --- Drag object (used to calculate boundary offset) --- |
| 150 | + object: element, |
| 151 | + // --- Callbacks --- |
| 152 | + start: (x, y) => { |
| 153 | + console.log('Start at:', x, y); |
| 154 | + }, |
| 155 | + move: (e, detail) => { |
| 156 | + console.log('Move:', detail.ox, detail.oy); |
| 157 | + console.log('Position:', detail.x, detail.y); |
| 158 | + console.log('Border:', detail.border); |
| 159 | + console.log('Direction:', detail.dir); |
| 160 | + }, |
| 161 | + up: (moveTimes, e) => { |
| 162 | + console.log('Up'); |
| 163 | + }, |
| 164 | + end: (moveTimes, e) => { |
| 165 | + console.log('End'); |
| 166 | + }, |
| 167 | + borderIn: (x, y, border, e) => { |
| 168 | + console.log('Border in:', border); |
| 169 | + }, |
| 170 | + borderOut: () => { |
| 171 | + console.log('Border out'); |
| 172 | + } |
| 173 | + }); |
| 174 | +}); |
| 175 | +``` |
| 176 | + |
| 177 | +#### `resize(e, options)` |
| 178 | + |
| 179 | +Resize event. |
| 180 | + |
| 181 | +```typescript |
| 182 | +element.addEventListener('mousedown', (e) => { |
| 183 | + pointer.resize(e, { |
| 184 | + object: element, |
| 185 | + border: 'rb', // lt, t, tr, r, rb, b, bl, l |
| 186 | + minWidth: 100, |
| 187 | + minHeight: 100, |
| 188 | + maxWidth: 500, |
| 189 | + maxHeight: 500, |
| 190 | + start: (x, y) => { |
| 191 | + console.log('Resize start'); |
| 192 | + }, |
| 193 | + move: (left, top, width, height, x, y, border) => { |
| 194 | + element.style.left = left + 'px'; |
| 195 | + element.style.top = top + 'px'; |
| 196 | + element.style.width = width + 'px'; |
| 197 | + element.style.height = height + 'px'; |
| 198 | + }, |
| 199 | + end: () => { |
| 200 | + console.log('Resize end'); |
| 201 | + } |
| 202 | + }); |
| 203 | +}); |
| 204 | +``` |
| 205 | + |
| 206 | +#### `drag(e, el, options)` |
| 207 | + |
| 208 | +Drag event, supports drag and drop to target elements. |
| 209 | + |
| 210 | +```typescript |
| 211 | +// --- Set drag source --- |
| 212 | +dragSource.addEventListener('mousedown', (e) => { |
| 213 | + pointer.drag(e, dragSource, { |
| 214 | + data: { id: 1, name: 'item' }, |
| 215 | + start: (x, y) => { |
| 216 | + console.log('Drag start'); |
| 217 | + }, |
| 218 | + move: (e, detail) => { |
| 219 | + console.log('Dragging'); |
| 220 | + }, |
| 221 | + end: (moveTimes, e) => { |
| 222 | + console.log('Drag end'); |
| 223 | + } |
| 224 | + }); |
| 225 | +}); |
| 226 | + |
| 227 | +// --- Set drop target --- |
| 228 | +dropTarget.dataset.drop = ''; |
| 229 | +dropTarget.addEventListener('dragenter', (e) => { |
| 230 | + console.log('Drag enter'); |
| 231 | +}); |
| 232 | +dropTarget.addEventListener('dragleave', (e) => { |
| 233 | + console.log('Drag leave'); |
| 234 | +}); |
| 235 | +dropTarget.addEventListener('drop', (e) => { |
| 236 | + const data = pointer.getDragData(); |
| 237 | + console.log('Dropped:', data); |
| 238 | +}); |
| 239 | +``` |
| 240 | + |
| 241 | +### Utility Functions |
| 242 | + |
| 243 | +#### `setCursor(type?)` |
| 244 | + |
| 245 | +Set/cancel global mouse style. |
| 246 | + |
| 247 | +```typescript |
| 248 | +pointer.setCursor('move'); |
| 249 | +// ... |
| 250 | +pointer.setCursor(); // Cancel |
| 251 | +``` |
| 252 | + |
| 253 | +#### `hasTouchButMouse(e)` |
| 254 | + |
| 255 | +Determine whether the current event is a mouse event triggered by a touch device. |
| 256 | + |
| 257 | +```typescript |
| 258 | +if (pointer.hasTouchButMouse(e)) { |
| 259 | + return; // Ignore mouse events on touch devices |
| 260 | +} |
| 261 | +``` |
| 262 | + |
| 263 | +## Types |
| 264 | + |
| 265 | +### `TDirection` |
| 266 | + |
| 267 | +Direction type. |
| 268 | + |
| 269 | +```typescript |
| 270 | +type TDirection = 'top' | 'right' | 'bottom' | 'left'; |
| 271 | +``` |
| 272 | + |
| 273 | +### `TBorder` |
| 274 | + |
| 275 | +Border direction type. |
| 276 | + |
| 277 | +```typescript |
| 278 | +type TBorder = 'lt' | 't' | 'tr' | 'r' | 'rb' | 'b' | 'bl' | 'l' | ''; |
| 279 | +``` |
| 280 | + |
| 281 | +### `IMoveDetail` |
| 282 | + |
| 283 | +Detailed information in the move callback. |
| 284 | + |
| 285 | +```typescript |
| 286 | +interface IMoveDetail { |
| 287 | + ox: number; // x-axis offset |
| 288 | + oy: number; // y-axis offset |
| 289 | + x: number; // Current x coordinate |
| 290 | + y: number; // Current y coordinate |
| 291 | + border: TBorder; // Border type |
| 292 | + inBorder: { // Whether at the border |
| 293 | + top: boolean; |
| 294 | + right: boolean; |
| 295 | + bottom: boolean; |
| 296 | + left: boolean; |
| 297 | + }; |
| 298 | + dir: TDirection; // Direction of movement |
| 299 | +} |
| 300 | +``` |
| 301 | + |
| 302 | +## Demo |
| 303 | + |
| 304 | +Clone the repository and open `dist/test/index.html` in your browser. |
| 305 | + |
| 306 | +```bash |
| 307 | +git clone https://github.com/litert/pointer.js.git |
| 308 | +cd pointer.js |
| 309 | +npm install |
| 310 | +npm run build |
| 311 | +``` |
| 312 | + |
| 313 | +Then open `dist/test/index.html` in your browser. |
| 314 | + |
| 315 | +## Browser Support |
| 316 | + |
| 317 | +- Chrome (latest) |
| 318 | +- Firefox (latest) |
| 319 | +- Safari (latest) |
| 320 | +- Edge (latest) |
| 321 | +- Mobile browsers (iOS Safari, Chrome for Android) |
| 322 | + |
| 323 | +## License |
| 324 | + |
| 325 | +This library is published under [Apache-2.0](./LICENSE) license. |
0 commit comments