So it turns out that the entire concept of calling getBoundingClientRect() on each drop zone one by one is unnecessary.
There's a better way to do this: document.elementFromPoint(touch.clientX, touch.clientY). Just get the element, check if it's a drop zone, and drop the element there.
Instead of storing the last touch point in global variables, we can simply detect them locally in handleTouchEnd using changedTouches. It would look something like this:
lettouch=e.changedTouches[0]if(!touch.target.id/* try to check if it's current target */){return}letelem=document.elementFromPoint(touch.clientX,touch.clientY)