3 ms·
How does the dragging itself work? custom js?
by hipadev23 2y ago
How does the dragging itself work? custom js?
- tyleo 2y agoIn the Cross-Platform Dynamic Light section I describe `data-*` attributes (https://www.tyleo.com/html-glass.html#cross-platform-dynamic-light https://www.tyleo.com/html-glass.html#cross-platform-dynamic...). The dragging works with another bit of JavaScript--the only other bit on the page--which uses a `data-click-drag-area` to define an element which will contain draggable children and a `data-click-drag-item` attribute to indicate a child can be dragged. The the parent must be a 'positioned element' (it must have `position` set to something in CSS) the children must have `position: absolute`. I did this in TypeScript. I'll share the code below. You have to call `initDataClickDrag` from another script... if you want to include this script directly you can just remove the `export` keyword and call `initDataClickDrag()` at the bottom after it is defined: export const initDataClickDrag = () => { // Get all of the areas we can drag items in const dragAreas = document.querySelectorAll("[data-click-drag-area]"); for (const dragArea of dragAreas) { // Only iterate `HTMLElement`s if (!(dragArea instanceof HTMLElement)) continue; // Get all of the items we can drag const dragItems = dragArea.querySelectorAll("[data-click-drag-item]"); for (const dragItem of dragItems) { // Only iterate `HTMLElement`s if (!(dragItem instanceof HTMLElement)) continue; let isDragging = false; let lastCursorX: number | undefined = undefined; let lastCursorY: number | undefined = undefined; // Mouse down event to start dragging const downCallback = (obj: { readonly pageX: number; readonly pageY: number; }) => { isDragging = true; lastCursorX = obj.pageX; lastCursorY = obj.pageY; }; dragItem.addEventListener("mousedown", (e) => { downCallback(e); }); dragItem.addEventListener("touchstart", (e) => { const touches = e.touches; if (touches.length === 0) return; downCallback(touches[0]); }); // Mouse move event to scroll while dragging const moveCallback = (obj: { readonly pageX: number; readonly pageY: number; }): boolean => { if (!isDragging) return false; if (lastCursorX === undefined) return false; if (lastCursorY === undefined) return false; const x = lastCursorX - obj.pageX; const y = lastCursorY - obj.pageY; const left = dragItem.offsetLeft - x; const top = dragItem.offsetTop - y; dragItem.style.left = `${left.toString()}px`; dragItem.style.top = `${top.toString()}px`; // Get dragArea dimensions const dragAreaRect = dragArea.getBoundingClientRect(); // Get element dimensions const elementRect = dragItem.getBoundingClientRect(); if (dragItem.offsetLeft < 0) dragItem.style.left = "0px"; if (dragItem.offsetTop < 0) dragItem.style.top = "0px"; if (left + elementRect.width > dragAreaRect.width) { // Right boundary const left = dragAreaRect.width - elementRect.width; dragItem.style.left = `${left.toString()}px`; } if (top + elementRect.height > dragAreaRect.height) { // Bottom boundary const top = dragAreaRect.height - elementRect.height; dragItem.style.top = `${top.toString()}px`; } lastCursorX = obj.pageX; lastCursorY = obj.pageY; return true; }; document.addEventListener("mousemove", (e) => { moveCallback(e); }); document.addEventListener( "touchmove", (e) => { const touches = e.touches; if (touches.length === 0) return; if (!moveCallback(touches[0])) return; e.preventDefault(); }, { passive: false }, ); // Mouse up event to stop dragging document.addEventListener("mouseup", () => { isDragging = false; }); document.addEventListener("touchend", () => { isDragging = false; }); } } };