Gesture of Goodwill in HTML5

May 11, 2013

This is the second time I’ve typed this. For some reason, WordPress musn’t have liked the first attempt, and so trashed it - which is annoying!

I’ve been playing with gestures on HTML5, and encountered a strange problem (this may be peculiar to Windows 8, but I doubt it).  Here’s the scenario:

The Problem

You have an app (remember that we’re talking about Windows 8).  In the app, you have a particular response to a swipe gesture: say you want to record the swipe distance; and to react to a tap / touch gesture.  This works for mouse events, too.

Here’s some code:

[sourcecode language=“html”]




Yeah - I know, you're wondering how I ever managed to get so good at HTML5!  

Here's some more interesting code:


[sourcecode language="javascript"]

    var canvas;
    var canvasContext;

    var initialiseApp = function () {
        canvas = document.getElementById("mainCanvas");
        canvasContext = canvas.getContext("2d");

        canvas.width = window.outerWidth;
        canvas.height = window.outerHeight;

        // define GestureRecognizer  
        var recognizer = new Windows.UI.Input.GestureRecognizer();
        recognizer.gestureSettings = Windows.UI.Input.GestureSettings.manipulationTranslateX
        recognizer.addEventListener('manipulationcompleted', function (e) {
            var dx = e.cumulative.translation.x

            canvasContext.clearRect(0, 0, 1000, 20);
            canvasContext.fillStyle = "#2F1BE0";
            canvasContext.fillText('manipulationcompleted ' + Date.now(), 10, 10);
            
        });

        // actual element which feeds the GestureRecognizer  
        var processUp = function (evt) {
            try {
                recognizer.processUpEvent(evt.currentPoint);

                canvasContext.clearRect(10, 90, 1000, 50);
                canvasContext.fillStyle = "#2F1BE0";
                canvasContext.fillText('processUp' + Date.now(), 10, 100);

            }
            catch (e) { } 
        }

        canvas.addEventListener('MSPointerDown', function (args) {
            try {
                recognizer.processDownEvent(args.currentPoint);

                canvasContext.clearRect(10, 190, 1000, 20);
                canvasContext.fillStyle = "#2F1BE0";
                canvasContext.fillText('processDown' + Date.now(), 10, 200);
            }
            catch (e) { } 
        }, false);

        canvas.addEventListener('MSPointerMove', function (args) {
            try {
                recognizer.processMoveEvents(args.intermediatePoints);

                canvasContext.clearRect(10, 250, 1000, 200);
                canvasContext.fillStyle = "#2F1BE0";
                canvasContext.fillText('processMove' + Date.now(), 10, 300);
            }
            catch (e) { } 
        }, false);
        canvas.addEventListener('MSPointerUp', processUp, false);
        canvas.addEventListener('MSPointerCancel', processUp, false);

    }


If you try that, you’ll notice something… or at least you will now I’ve told you to. That is that if you click / touch then you get a mouse up, but if you swipe then you get a mouse up and a manipulationcomplete! Good God - BOTH! But what if you only want to react to one? Say you have a fishing game, and the swipe casts the … err fishing string thingy, and the touch reels the … err… okay, maybe I should have picked an example I know something about, but you get the idea.

The Solution

I don’t like it, but here’s my answer to that particular conundrum:

[sourcecode language=“javascript”] var canvas; var canvasContext; var eventFlag = 0;

var initialiseApp = function () {
    canvas = document.getElementById("mainCanvas");
    canvasContext = canvas.getContext("2d");

    canvas.width = window.outerWidth;
    canvas.height = window.outerHeight;

    // define GestureRecognizer  
    var recognizer = new Windows.UI.Input.GestureRecognizer();
    recognizer.gestureSettings = Windows.UI.Input.GestureSettings.manipulationTranslateX
    recognizer.addEventListener('manipulationcompleted', function (e) {
        var dx = e.cumulative.translation.x

        canvasContext.clearRect(0, 0, 1000, 20);
        canvasContext.fillStyle = "#2F1BE0";
        canvasContext.fillText('manipulationcompleted ' + Date.now(), 10, 10);
        eventFlag = 1;
        
    });

    // actual element which feeds the GestureRecognizer  
    var processUp = function (evt) {
        try {
            recognizer.processUpEvent(evt.currentPoint);

            if (eventFlag == 0) {
                canvasContext.clearRect(10, 90, 1000, 50);
                canvasContext.fillStyle = "#2F1BE0";
                canvasContext.fillText('processUp' + Date.now(), 10, 100);

            } else {
                eventFlag = 0;
            }

        }
        catch (e) { } // translateYfails ?!  
    }



So we have a flag, and only do something based on the flag.

Conclusion

If there's a better way of doing this then I'd like to hear.  It would be particularly nice if you could get the return value of processUpEvent, or set some kind of handled flag.  Having said that, this does work.


Profile picture

A blog about one man's journey through code… and some pictures of the Peak District
Twitter

© Paul Michaels 2024