Touch gestures for zooming in & out on specific document areas

I am trying to create a touchscreen application where there is a menu which needs to stay in place at all times, and an additional area where the user should be able to zoom & pan a map (a custom SVG in this case) with touch gestures (including pinch in and out). I need the application to work in Google Chrome.

What would be the best way to go about doing this? As far as I can tell, I first need to disable pinch gestures in Chrome (via command line options), in order to prevent the entire web page being “zoomable” by users using the touchscreen - this part I got working just fine.

However, Tumult doesn’t appear to have native support for this kind of gestures. I have tried using interact.js to make my map object zoomable, alas it doesn’t seem to quite work as expected: the scaling is pretty jerky, and pinching out works much slower than pinching in. Also, it doesn’t seem to accept changing the pinch direction (within the same gesture) or be draggable. The example code for Pinch-to-Zoom on the project webpage (interactjs.io) works however just fine, and behaves as expected. So, it appears to be a conflict somewhere, which I can’t however identify.

Did anybody implement something similar successfully? Or (most likely) I am missing something
completely obvious ?

Well, I believe I solved it myself, or at least it looks like it so far from my testing. I couldn’t get it in the end to work with Interact.JS, probably because I don’t quite get their event handling system, but it works just fine with Hammer.JS (https://hammerjs.github.io).

If anybody is stumbling over similar problems, here is the code I used on OnSceneLoad:

	myElement = hypeDocument.getElementById('Karte');
	
	var hammertime = new Hammer(myElement);
	
	var scale = 1,
		last_scale = 1,
	    posX = 0,
        posY = 	0,
        last_posX = 0,
        last_posY = 0,
        max_pos_x = 0,
        max_pos_y = 0,
        el = myElement;
	
	hammertime.get('pinch').set({ enable: true });
	
	hammertime.on('pan panend pinch pinchend', function(ev) {
		
		if (scale != 1) {
            posX = last_posX + ev.deltaX;
            posY = last_posY + ev.deltaY;
            max_pos_x = Math.ceil((scale - 1) * el.clientWidth / 2);
            max_pos_y = Math.ceil((scale - 1) * el.clientHeight / 2);
            
            if (posX > max_pos_x) {
                posX = max_pos_x;
            }
            if (posX < -max_pos_x) {
                posX = -max_pos_x;
            }
            if (posY > max_pos_y) {
                posY = max_pos_y;
            }
            if (posY < -max_pos_y) {
                posY = -max_pos_y;
            }
        }
        
		if(ev.type == "panend"){
            last_posX = posX < max_pos_x ? posX : max_pos_x;
            last_posY = posY < max_pos_y ? posY : max_pos_y;
        }
        
		if (ev.type == "pinch") {
			scale = Math.max(.999, Math.min(last_scale * (ev.scale), 4));
		}
		
		if (ev.type == "pinchend") {
			last_scale = scale;
		} 
		
		if (scale != 1) {
           	hypeDocument.setElementProperty(myElement, 'top', posY);
			hypeDocument.setElementProperty(myElement, 'left', posX);
			
           	hypeDocument.setElementProperty(myElement, 'scaleX', scale);
			hypeDocument.setElementProperty(myElement, 'scaleY', scale);

        }
	});

It works smoothly in Chrome, and also the Hammer event handling doesn’t get in the way of other touch events (like Tap), which can be managed and reacted to natively from within Hype.

1 Like

How are you creating the map object? It would be great to know what types of interactions Hype might be conflicting with.

The map is just a SVG vector drawing, directly imported in the Hype scene - nothing spectacular. But, like said, that it didn’t quite work with Interact.JS is likely me bumbling around all newbie like.

Interesting. I got this setup and I assume you are doing something like this?

I can see how this is a useful effect: pinch + zoom for an object instead of the entire document.

svg-doc.hype.zip (43.1 KB)

1 Like