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

d3.pointer() could use event.touches[0]

jogemu opened this issue · comments

The function d3.pointer() could react to touch events as expected by adding the bold line of code to the d3.js file. I am sorry if this is not the right D3 module, but this change will probably influence this module the most and I hope asking about this issue can be beneficial regardless.

function pointer(event, node) {
event = sourceEvent(event);
if (node === undefined) node = event.currentTarget;
if (event.touches) event = event.touches[0];
if (node) {
var svg = node.ownerSVGElement || node;
if (svg.createSVGPoint) {
var point = svg.createSVGPoint();
point.x = event.clientX, point.y = event.clientY;
point = point.matrixTransform(node.getScreenCTM().inverse());
return [point.x, point.y];
}
if (node.getBoundingClientRect) {
var rect = node.getBoundingClientRect();
console.log(event.clientX, rect.top)
return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
}
}
return [event.pageX, event.pageY];
}

A touch event is a pointer according to the interpretation of the browsers that support it but page/client X/Y is not stored in the event itself but in the array touches. This means that d3.pointer() will return [NaN, NaN]. This behavior might match with the documentation. However if d3.pointer() is called on for events that aren't pointer related it returns [undefined, undefined] which might be a better response if touch events aren't supposed to be supported. I have to admit that the assignment I made after the if (bold code) might break some implementations therefore I understand that the assignment might be replaced with a return statement but I in my opinion the if itself is justified.

I use d3.pointer() in d3-zoom to control the center of the zoom and it works on Firefox and Chrome for both Android and Windows.

I often use d3.pointers()[0] for the same effect, when I'm sure I don't want to handle multitouch. I've tried to give a few hints on multitouch in https://observablehq.com/@d3/multitouch

Thank you @Fil, now I have to ask myself why I didn't look at that function, it was right under the one I debuged. While doing that I discovered that I need to give d3.pointers(event) svg.node() as second parameter, but only for the drag event, the drag start event will find the right owner element. This result is kind of unexpected but I guess that the right way to handle it would be to give the second parameter for all events.