GUAC-324: Fix panning and pinch. Add placeholder menu.

This commit is contained in:
Michael Jumper
2014-04-18 16:56:32 -07:00
parent 91551e4e23
commit 5bb629a709
3 changed files with 163 additions and 51 deletions

View File

@@ -30,7 +30,7 @@
<link rel="stylesheet" type="text/css" href="styles/ui.css"/> <link rel="stylesheet" type="text/css" href="styles/ui.css"/>
<link rel="stylesheet" type="text/css" href="styles/client.css"/> <link rel="stylesheet" type="text/css" href="styles/client.css"/>
<link rel="stylesheet" type="text/css" href="styles/keyboard.css"/> <link rel="stylesheet" type="text/css" href="styles/keyboard.css"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, target-densitydpi=device-dpi"/> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, target-densitydpi=medium-dpi"/>
<meta name="apple-mobile-web-app-capable" content="yes"/> <meta name="apple-mobile-web-app-capable" content="yes"/>
<title>Guacamole ${project.version}</title> <title>Guacamole ${project.version}</title>
</head> </head>
@@ -38,9 +38,11 @@
<body> <body>
<!-- Display --> <!-- Display -->
<div class="displayOuter"> <div id="main">
<div class="displayMiddle"> <div class="displayOuter">
<div id="display"> <div class="displayMiddle">
<div id="display">
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -51,6 +53,15 @@
<!-- Notification area --> <!-- Notification area -->
<div id="notificationArea"/> <div id="notificationArea"/>
<!-- Menu -->
<div id="menu">
<h1>Guacamole ${project.version}</h1>
<button>Test button</button>
<button>Test button</button>
<button>Test button</button>
<button>Test button</button>
</div>
<!-- Images which should be preloaded --> <!-- Images which should be preloaded -->
<div id="preload"> <div id="preload">
<img src="images/action-icons/guac-close.png"/> <img src="images/action-icons/guac-close.png"/>

View File

@@ -219,6 +219,7 @@ GuacUI.Client = {
/* UI Components */ /* UI Components */
"viewport" : document.getElementById("viewportClone"), "viewport" : document.getElementById("viewportClone"),
"main" : document.getElementById("main"),
"display" : document.getElementById("display"), "display" : document.getElementById("display"),
"notification_area" : document.getElementById("notificationArea"), "notification_area" : document.getElementById("notificationArea"),
@@ -430,7 +431,7 @@ GuacUI.Client.Pan = function(element) {
* @private * @private
*/ */
var guac_pan = this; var guac_pan = this;
/** /**
* The starting X location of the pan gesture. * The starting X location of the pan gesture.
* @private * @private
@@ -566,12 +567,26 @@ GuacUI.Client.Pinch = function(element) {
*/ */
this.ratio = 1; this.ratio = 1;
/**
* The X-coordinate of the current center of the pinch gesture.
* @type Number
*/
this.centerX = 0;
/**
* The Y-coordinate of the current center of the pinch gesture.
* @type Number
*/
this.centerY = 0;
/** /**
* Called when a zoom gesture begins. * Called when a zoom gesture begins.
* *
* @event * @event
* @param {Number} ratio The relative value of the starting zoom. This will * @param {Number} ratio The relative value of the starting zoom. This will
* ALWAYS be 1. * ALWAYS be 1.
* @param {Number} x The X-coordinate of the center of the pinch gesture.
* @param {Number} y The Y-coordinate of the center of the pinch gesture.
*/ */
this.onzoomstart = null; this.onzoomstart = null;
@@ -581,6 +596,8 @@ GuacUI.Client.Pinch = function(element) {
* @event * @event
* @param {Number} ratio The relative value of the changed zoom, with 1 * @param {Number} ratio The relative value of the changed zoom, with 1
* being no change. * being no change.
* @param {Number} x The X-coordinate of the center of the pinch gesture.
* @param {Number} y The Y-coordinate of the center of the pinch gesture.
*/ */
this.onzoomchange = null; this.onzoomchange = null;
@@ -590,6 +607,8 @@ GuacUI.Client.Pinch = function(element) {
* @event * @event
* @param {Number} ratio The relative value of the final zoom, with 1 * @param {Number} ratio The relative value of the final zoom, with 1
* being no change. * being no change.
* @param {Number} x The X-coordinate of the center of the pinch gesture.
* @param {Number} y The Y-coordinate of the center of the pinch gesture.
*/ */
this.onzoomend = null; this.onzoomend = null;
@@ -613,6 +632,40 @@ GuacUI.Client.Pinch = function(element) {
} }
/**
* Given a touch event, calculates the center between the first two
* touches in pixels, returning the X coordinate of this center.
*
* @param {TouchEvent} e The touch event to use when performing center
* calculation.
* @return {Number} The X-coordinate of the center of the first two touches.
*/
function pinch_center_x(e) {
var touch_a = e.touches[0];
var touch_b = e.touches[1];
return (touch_a.clientX + touch_b.clientX) / 2;
}
/**
* Given a touch event, calculates the center between the first two
* touches in pixels, returning the Y coordinate of this center.
*
* @param {TouchEvent} e The touch event to use when performing center
* calculation.
* @return {Number} The Y-coordinate of the center of the first two touches.
*/
function pinch_center_y(e) {
var touch_a = e.touches[0];
var touch_b = e.touches[1];
return (touch_a.clientY + touch_b.clientY) / 2;
}
// When there are exactly two touches, monitor the distance between // When there are exactly two touches, monitor the distance between
// them, firing zoom events as appropriate // them, firing zoom events as appropriate
element.addEventListener("touchmove", function(e) { element.addEventListener("touchmove", function(e) {
@@ -624,19 +677,23 @@ GuacUI.Client.Pinch = function(element) {
// Calculate current zoom level // Calculate current zoom level
var current = pinch_distance(e); var current = pinch_distance(e);
// Calculate center
guac_zoom.centerX = pinch_center_x(e);
guac_zoom.centerY = pinch_center_y(e);
// If gesture just starting, fire zoom start // If gesture just starting, fire zoom start
if (!start_length) { if (!start_length) {
start_length = current; start_length = current;
guac_zoom.ratio = 1; guac_zoom.ratio = 1;
if (guac_zoom.onzoomstart) if (guac_zoom.onzoomstart)
guac_zoom.onzoomstart(guac_zoom.ratio); guac_zoom.onzoomstart(guac_zoom.ratio, guac_zoom.centerX, guac_zoom.centerY);
} }
// Otherwise, notify of zoom change // Otherwise, notify of zoom change
else { else {
guac_zoom.ratio = current / start_length; guac_zoom.ratio = current / start_length;
if (guac_zoom.onzoomchange) if (guac_zoom.onzoomchange)
guac_zoom.onzoomchange(guac_zoom.ratio); guac_zoom.onzoomchange(guac_zoom.ratio, guac_zoom.centerX, guac_zoom.centerY);
} }
} }
@@ -652,7 +709,7 @@ GuacUI.Client.Pinch = function(element) {
start_length = null; start_length = null;
if (guac_zoom.onzoomend) if (guac_zoom.onzoomend)
guac_zoom.onzoomend(guac_zoom.ratio); guac_zoom.onzoomend(guac_zoom.ratio, guac_zoom.centerX, guac_zoom.centerY);
guac_zoom.ratio = 1; guac_zoom.ratio = 1;
} }
@@ -1065,6 +1122,64 @@ GuacUI.Client.attach = function(guac) {
}; };
/*
* Pinch-to-zoom
*/
var guac_pinch = new GuacUI.Client.Pinch(document.body);
var initial_scale = null;
var initial_center_x = null;
var initial_center_y = null;
guac_pinch.onzoomstart = function(ratio, x, y) {
initial_scale = guac.getScale();
initial_center_x = (x + GuacUI.Client.main.scrollLeft) / initial_scale;
initial_center_y = (y + GuacUI.Client.main.scrollTop) / initial_scale;
};
guac_pinch.onzoomchange = function(ratio, x, y) {
// Rescale based on new ratio
var new_scale = initial_scale * ratio;
new_scale = Math.max(new_scale, GuacUI.Client.min_zoom);
new_scale = Math.min(new_scale, GuacUI.Client.max_zoom);
guac.scale(new_scale);
// Calculate point at currently at center of touch
var point_at_center_x = (x + GuacUI.Client.main.scrollLeft) / new_scale;
var point_at_center_y = (y + GuacUI.Client.main.scrollTop) / new_scale;
// Correct position to keep point-of-interest within center of pinch
GuacUI.Client.main.scrollLeft += (initial_center_x - point_at_center_x) * new_scale;
GuacUI.Client.main.scrollTop += (initial_center_y - point_at_center_y) * new_scale;
};
/*
* Touch panning
*/
var guac_pan = new GuacUI.Client.Pan(document.body);
var last_pan_dx = 0;
var last_pan_dy = 0;
guac_pan.onpanstart = function(dx, dy) {
last_pan_dx = dx;
last_pan_dy = dy;
};
guac_pan.onpanchange = function(dx, dy) {
if (!touch.currentState.left) {
var change_pan_dx = dx - last_pan_dx;
var change_pan_dy = dy - last_pan_dy;
GuacUI.Client.main.scrollLeft -= change_pan_dx;
GuacUI.Client.main.scrollTop -= change_pan_dy;
last_pan_dx = dx;
last_pan_dy = dy;
}
};
// Hide any existing status notifications // Hide any existing status notifications
GuacUI.Client.hideStatus(); GuacUI.Client.hideStatus();
@@ -1215,48 +1330,6 @@ GuacUI.Client.attach = function(guac) {
}, false); }, false);
/*
* Pinch-to-zoom
*/
var guac_pinch = new GuacUI.Client.Pinch(document.body);
var initial_scale = null;
guac_pinch.onzoomstart = function() {
initial_scale = guac.getScale();
};
guac_pinch.onzoomchange = function(ratio) {
var new_scale = initial_scale * ratio;
new_scale = Math.max(new_scale, GuacUI.Client.min_zoom);
new_scale = Math.min(new_scale, GuacUI.Client.max_zoom);
guac.scale(new_scale);
};
/*
* Touch panning
*/
var guac_pan = new GuacUI.Client.Pan(document.body);
var last_pan_dx = 0;
var last_pan_dy = 0;
guac_pan.onpanstart = function(dx, dy) {
last_pan_dx = dx;
last_pan_dy = dy;
};
guac_pan.onpanchange = function(dx, dy) {
if (!touch.currentState.left) {
var change_pan_dx = dx - last_pan_dx;
var change_pan_dy = dy - last_pan_dy;
window.scrollBy(-change_pan_dx, -change_pan_dy);
last_pan_dx = dx;
last_pan_dy = dy;
}
};
/* /*
* Disconnect and update thumbnail on close * Disconnect and update thumbnail on close
*/ */
@@ -1417,4 +1490,9 @@ GuacUI.Client.attach = function(guac) {
}, false); }, false);
// Prevent default on all touch events
document.addEventListener("touchstart", function(e) {
e.preventDefault();
}, false);
})(); })();

View File

@@ -113,6 +113,15 @@ div.dialog p {
margin: 0; margin: 0;
} }
div#main {
overflow: auto;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
div.displayOuter { div.displayOuter {
height: 100%; height: 100%;
width: 100%; width: 100%;
@@ -489,4 +498,18 @@ p.hint {
width: 0; width: 0;
height: 0; height: 0;
overflow: hidden; overflow: hidden;
} }
/* Menu */
#menu {
overflow: auto;
position: fixed;
top: 0;
left: 0;
bottom: 0;
max-width: 100%;
width: 320px;
padding: 1em;
background: red;
}