mudcube / Event.js

:hand: Multi-touch, gestures, and other events—click, dblclick, dbltap, tap, longpress, drag, swipe, pinch, rotate, shake. For pointer events, each listener can handle anywhere from 1 to 12 fingers at a time, or more, depending on the device. Includes MetaKey tracking (CMD, CTRL) to support native key-commands in various platforms.
MIT License
368 stars 68 forks source link

Add centre coordinates to callback object or how to calculate during pinch? #9

Open stodge opened 10 years ago

stodge commented 10 years ago

Could you add the centre coordinates of the pinch gesture to the object?

Event.add(window, "gesture", function(event, self) {
    console.log(self.gesture, self.fingers, self.state, self.rotation, self.scale, self.centre);
});

If this isn't possible, any ideas how I should accurately calculate the centre of the pinch?

Thanks

stodge commented 10 years ago

Currently I'm just doing this when the gesture state is "change" and there are two touches:

            this.centreX = Math.abs((evt.touches[1].pageX + evt.touches[0].pageX) / 2.0);
            this.centreY = Math.abs((evt.touches[1].pageY + evt.touches[0].pageY) / 2.0);
mudcube commented 10 years ago

Hi Stodge,

I actually did this recently... Unfortunately, my event.js is a bit ahead of the online branch, and would take an hour or two to merge. I upgrade the online version every few months:

if (typeof(eventjs) === "undefined") var eventjs = {};
if (typeof(eventjs.proxy) === "undefined") eventjs.proxy = {};

eventjs.proxy = (function(root) { "use strict";

var RAD_DEG = Math.PI / 180;
var getCentroid = function(self, points) {
    var centroidx = 0;
    var centroidy = 0;
    var length = 0;
    for (var sid in points) {
        var touch = points[sid];
        if (touch.up) continue;
        centroidx += touch.move.x;
        centroidy += touch.move.y;
        length ++;
    }
    self.x = centroidx /= length;
    self.y = centroidy /= length;
    return self;
};

root.gesture = function(conf) {
    conf.gesture = conf.gesture || "gesture";
    conf.minFingers = conf.minFingers || conf.fingers || 2;
    // Tracking the events.
    conf.onPointerDown = function (event) {
        var fingers = conf.fingers;
        if (root.pointerStart(event, self, conf)) {
            eventjs.add(conf.doc, "mousemove", conf.onPointerMove);
            eventjs.add(conf.doc, "mouseup", conf.onPointerUp);
        }
        // Record gesture start.
        if (conf.fingers === conf.minFingers && fingers !== conf.fingers) {
            self.fingers = conf.minFingers;
            self.scale = 1;
            self.rotation = 0;
            self.state = "start";
            var sids = ""; //- FIXME(mud): can generate duplicate IDs.
            for (var key in conf.tracker) sids += key;
            self.identifier = parseInt(sids);
            getCentroid(self, conf.tracker);
            conf.listener(event, self);
        }
    };
    ///
    conf.onPointerMove = function (event, state) {
        var bbox = conf.bbox;
        var points = conf.tracker;
        var touches = event.changedTouches || root.getCoords(event);
        var length = touches.length;
        // Update tracker coordinates.
        for (var i = 0; i < length; i ++) {
            var touch = touches[i];
            var sid = touch.identifier || Infinity;
            var pt = points[sid];
            // Check whether "pt" is used by another gesture.
            if (!pt) continue; 
            // Find the actual coordinates.
            pt.move.x = (touch.pageX - bbox.x1);
            pt.move.y = (touch.pageY - bbox.y1);
        }
        ///
        if (conf.fingers < conf.minFingers) return;
        ///
        var touches = [];
        var scale = 0;
        var rotation = 0;

        /// Calculate centroid of gesture.
        getCentroid(self, points);
        ///
        for (var sid in points) {
            var touch = points[sid];
            if (touch.up) continue;
            var start = touch.start;
            if (!start.distance) {
                var dx = start.x - self.x;
                var dy = start.y - self.y;
                start.distance = Math.sqrt(dx * dx + dy * dy);
                start.angle = Math.atan2(dx, dy) / RAD_DEG;
            }
            // Calculate scale.
            var dx = touch.move.x - self.x;
            var dy = touch.move.y - self.y;
            var distance = Math.sqrt(dx * dx + dy * dy);
            scale += distance / start.distance;
            // Calculate rotation.
            var angle = Math.atan2(dx, dy) / RAD_DEG;
            var rotate = (start.angle - angle + 360) % 360 - 180;
            touch.DEG2 = touch.DEG1; // Previous degree.
            touch.DEG1 = rotate > 0 ? rotate : -rotate; // Current degree.
            if (typeof(touch.DEG2) !== "undefined") {
                if (rotate > 0) {
                    touch.rotation += touch.DEG1 - touch.DEG2;
                } else {
                    touch.rotation -= touch.DEG1 - touch.DEG2;
                }
                rotation += touch.rotation;
            }
            // Attach current points to self.
            touches.push(touch.move);
        }
        ///
        self.touches = touches;
        self.fingers = conf.fingers;
        self.scale = scale / conf.fingers;
        self.rotation = rotation / conf.fingers;
        self.state = "change";
        conf.listener(event, self);
    };
    conf.onPointerUp = function(event) {
        // Remove tracking for touch.
        var fingers = conf.fingers;
        if (root.pointerEnd(event, self, conf)) {
            eventjs.remove(conf.doc, "mousemove", conf.onPointerMove);
            eventjs.remove(conf.doc, "mouseup", conf.onPointerUp);
        }
        // Check whether fingers has dropped below minFingers.
        if (fingers === conf.minFingers && conf.fingers < conf.minFingers) {
            self.fingers = conf.fingers;
            self.state = "end";
            conf.listener(event, self);
        }
    };
    // Generate maintenance commands, and other configurations.
    var self = root.pointerSetup(conf);
    // Attach events.
    eventjs.add(conf.target, "mousedown", conf.onPointerDown);
    // Return this object.
    return self;
};

eventjs.Gesture = eventjs.Gesture || {};
eventjs.Gesture._gestureHandlers = eventjs.Gesture._gestureHandlers || {};
eventjs.Gesture._gestureHandlers.gesture = root.gesture;

return root;

})(eventjs.proxy);