Bad pointerId on iOS



I'm trying to use hand.js on multiple devices and I've an issue with iOS (really ?). On Android and iOS we've touch events and all events contains an array of touches id.

With hand.js this array of touches is replaced by a pointerId property and it start at 2 (the first finger) according to the code :

// handjs line 237
var touchPointId = touchPoint.identifier + 2; // Just to not override mouse id

It assume that touchPoint.identifier is equals to 0 up to 9 (for 10 fingers), by the way a different result is returned by iOS.. The pointer ID seems to use a timestamp so the result is totaly false.

document.body.addEventListener("touchstart", function (event) {
console.log(event.touches[0].identifier) // 0 on android, a timestamp on iOS
}, false);

I think that we need to use the index of event.touches array instead of event.touches[i].identifier value.


SaschaNaz wrote Jun 11, 2014 at 10:51 AM

The Pointer Events specification says that:
The pointerId selection algorithm is implementation specific. Therefore authors cannot assume values convey any particular meaning other than an identifier for the pointer that is unique from all other active pointers. As an example, values are not guaranteed to be monotonically increasing.
It means that we are OK if the identifiers are unique for each pointer. They don't have to be in 0-9 range, or to be determined by timestamp. Only the uniqueness is required.

So... I think it's not really a problem. However, if you still think this is a problem then please tell us :)

PS: Yes, pointerId starts at 2 for touch, because the value '1' is already occupied by mouse pointer in Hand.js. (See the definition of generateMouseProxy function!)

CYannick wrote Jun 11, 2014 at 11:54 AM

Ok... So how can I identifie a pointer id without having multiple hacks ?

In my opinion, having pointerId = 1 for mouse and 2, n for touches is logic. I don't understand why it's implemented like that in Safari..

So I think that there are two solutions. The first is to use Pointer = 1 for mouse and 2, n for touches and why not, change the specification because it's logic to work like that. The second solution is to hack hand.js but it's not a really good choice.

SaschaNaz wrote Jun 12, 2014 at 1:00 AM

Our current handjs example uses pointerId to determine
line color. Accessing pointerId, and giving same color with same pointerId.

Note that we are here storing pointerIds and use it later.
var pointerDown = {};
var lastPositions = {};
var colors = ["rgb(100, 255, 100)", "rgb(255, 0, 0)", "rgb(0, 255, 0)", "rgb(0, 0, 255)", "rgb(0, 255, 100)", "rgb(10, 255, 255)", "rgb(255, 0, 100)"];

var onPointerMove = function(evt) {
    if (pointerDown[evt.pointerId]) {

        var color = colors[evt.pointerId % colors.length];

        context.strokeStyle = color;

        context.lineWidth = 2;
        context.moveTo(lastPositions[evt.pointerId].x, lastPositions[evt.pointerId].y);
        context.lineTo(evt.clientX, evt.clientY);

        lastPositions[evt.pointerId] = { x: evt.clientX, y: evt.clientY };

var onPointerUp = function (evt) {
    pointerDown[evt.pointerId] = false;

var onPointerDown = function (evt) {
    pointerDown[evt.pointerId] = true;

    lastPositions[evt.pointerId] = { x: evt.clientX, y: evt.clientY };

CYannick wrote Jun 12, 2014 at 9:38 AM


I understand your example. For me it's a problem. So I'll make my own library or fork hand.js.

You can close this issue because according to the specifications it's not.

SaschaNaz wrote Jun 12, 2014 at 10:11 AM

I don't know exactly what problem you have, but Array.prototype.indexOf might help you with the pointerId storing shown above. The .indexOf function will then always give you a value within 0-9(or 9+ if your device supports more) range.

I hope this will help you :)