/* Here implemented the case when both dragArea and dropArea are located inside the document of the dragging iframe. Thus, all the events belong and relate to that inside document. */ export default function attachDND( movingEl: HTMLIFrameElement, dragArea: Element, dropArea: Element, ) { dragArea.addEventListener('pointerdown', userPressed, { passive: true, }) let bbox, startX, startY, raf, deltaX = 0, deltaY = 0 function userPressed(event) { startX = event.clientX startY = event.clientY bbox = movingEl.getBoundingClientRect() dropArea.addEventListener('pointermove', userMoved, { passive: true, }) dropArea.addEventListener('pointerup', userReleased, { passive: true, }) dropArea.addEventListener('pointercancel', userReleased, { passive: true, }) }; /* In case where the dropArea moves along with the dragging object we can only append deltas, but not to define each time it moves. */ function userMoved(event) { if (!raf) { deltaX += event.clientX - startX deltaY += event.clientY - startY deltaX = Math.min( Math.max(deltaX, -bbox.left), window.innerWidth - bbox.right, ) deltaY = Math.min( Math.max(deltaY, -bbox.top), window.innerHeight - bbox.bottom, ) raf = requestAnimationFrame(userMovedRaf) } } function userMovedRaf() { movingEl.style.transform = 'translate3d('+deltaX+'px,'+deltaY+'px, 0px)' raf = null } function userReleased() { dropArea.removeEventListener('pointermove', userMoved) dropArea.removeEventListener('pointerup', userReleased) dropArea.removeEventListener('pointercancel', userReleased) if (raf) { cancelAnimationFrame(raf) raf = null } movingEl.style.left = bbox.left + deltaX + 'px' movingEl.style.top = bbox.top + deltaY + 'px' movingEl.style.transform = 'translate3d(0px,0px,0px)' deltaX = deltaY = 0 } }