d3 / d3-drag

Drag and drop SVG, HTML or Canvas using mouse or touch input.

Home Page:https://d3js.org/d3-drag

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Signal reaching clickDistance threshold?

Herst opened this issue · comments

commented

In my application I want to do certain things only after I am certain that the user intents to do a drag, e.g.:

  • Adding the styles for dragged elements. If I would do it on the drag start event then it the style would be added on every mousedown which is not what I want.

  • .raise() the element being dragged. If I would do it right away it might cause the click event to not be triggered (at least in some browsers) if the element got removed from the DOM.

The way I solved it is to simply use the delta x and y inside the drag event handler to calculate whether the click stance threshold has been breached or not.

Now d3 already does the same calculation already, I wondered whether it couldn't just simply tell me about whether the distance has been overstepped in the drag event, e.g. using d3.event.isOutsideClickDistance.


On a side note, an alternative idea would be a .dragDistance() which would cause the start events to only appear after a certain distance. This would cause the elements to appear a bit sticky though and it depends on the specific use case whether that's what you want or not.

commented

Demo demonstrating my current solution: https://bl.ocks.org/Herst/3d486648556a3eee60442da977022fd1

@Herst - to workaround losing your click event, tweak how "raise" works to not move the "drag" node, but rather move all its siblings:

            //  Safe Raise - does not interfere with current click event  ---
            const dragNode = /* the DOM node being dragged during "dragstart" event */
            let nextSibling = dragNode.nextSibling;
            while (nextSibling) {
                target.parentNode.insertBefore(nextSibling, dragNode);
                nextSibling = dragNode.nextSibling;
            }

Would it be cleaner to not call event.preventDefault() on the mousemove event until the click distance threshold is crossed? Then you could check event.isDefaultPrevented to test.

commented

I guess this could work. I wonder if this would have any (good or bad) side effects concerning #9:

It’s a Chrome bug that calling mousemove.preventDefault prevents text selection, drag-and-drop, and scrolling (see issue 485892). The mousemove event is defined as having no default action.