drag
Description
The drag utility function enables drag interactions on DOM elements. It handles both mouse and touch
events, providing callbacks for drag start, move, and end events.
Basic Usage
Import and use the drag function to make elements draggable. The function returns a cleanup function that should be called to remove all event listeners:
import drag from './utils/drag.js';
const element = document.querySelector('.draggable');
const cleanup = drag({
element,
callback: (diff) => {
console.log('Dragged:', diff.x, diff.y);
}
});
// Later, when you need to remove the drag functionality
cleanup();
Options
element: HTMLElement
The DOM element to make draggable.
preventScroll: boolean (optional)
Whether to prevent scroll behavior during drag. Defaults to false.
Callbacks
callback: Function (optional)
Called on every drag move. Receives a diff object with x, y coordinates and original options.
startCallback: Function (optional)
Called when drag starts. Receives a diff object with x: 0, y: 0 and original options.
moveCallback: Function (optional)
Called on every drag move (in addition to callback). Receives a diff object.
endCallback: Function (optional)
Called when drag ends. Receives a diff object with the final position.
Return Value
cleanup: Function
The drag function returns a cleanup function. Call this function to remove all event listeners and stop the drag functionality. This is important for preventing memory leaks when removing or destroying components.
const cleanup = drag({ element, callback });
// Later, when component is destroyed or drag is no longer needed
cleanup();
Examples
Draggable Element
const box = document.querySelector('.box');
let position = { x: 0, y: 0 };
drag({
element: box,
callback: (diff) => {
position.x += diff.x;
position.y += diff.y;
box.style.transform = `translate(${position.x}px, ${position.y}px)`;
}
});
Resize Handle
const resizeHandle = document.querySelector('.resize-handle');
const panel = document.querySelector('.panel');
drag({
element: resizeHandle,
preventScroll: true,
callback: (diff) => {
const newWidth = panel.offsetWidth + diff.x;
panel.style.width = Math.max(100, newWidth) + 'px';
},
startCallback: () => {
panel.classList.add('resizing');
},
endCallback: () => {
panel.classList.remove('resizing');
}
});
Component with Cleanup
import ShadowComponent from './ShadowComponent.js';
import drag from './utils/drag.js';
class DraggableComponent extends ShadowComponent {
constructor() {
super();
this.cleanupDrag = null;
}
firstUpdated() {
const handle = this.shadowRoot.querySelector('.drag-handle');
this.cleanupDrag = drag({
element: handle,
moveCallback: (diff) => {
this.style.transform = `translate(${diff.x}px, ${diff.y}px)`;
}
});
}
disconnectedCallback() {
super.disconnectedCallback();
if(this.cleanupDrag) {
this.cleanupDrag();
this.cleanupDrag = null;
}
}
}