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/client.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"/>
<title>Guacamole ${project.version}</title>
</head>
@@ -38,9 +38,11 @@
<body>
<!-- Display -->
<div class="displayOuter">
<div class="displayMiddle">
<div id="display">
<div id="main">
<div class="displayOuter">
<div class="displayMiddle">
<div id="display">
</div>
</div>
</div>
</div>
@@ -51,6 +53,15 @@
<!-- Notification area -->
<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 -->
<div id="preload">
<img src="images/action-icons/guac-close.png"/>

View File

@@ -219,6 +219,7 @@ GuacUI.Client = {
/* UI Components */
"viewport" : document.getElementById("viewportClone"),
"main" : document.getElementById("main"),
"display" : document.getElementById("display"),
"notification_area" : document.getElementById("notificationArea"),
@@ -430,7 +431,7 @@ GuacUI.Client.Pan = function(element) {
* @private
*/
var guac_pan = this;
/**
* The starting X location of the pan gesture.
* @private
@@ -566,12 +567,26 @@ GuacUI.Client.Pinch = function(element) {
*/
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.
*
* @event
* @param {Number} ratio The relative value of the starting zoom. This will
* 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;
@@ -581,6 +596,8 @@ GuacUI.Client.Pinch = function(element) {
* @event
* @param {Number} ratio The relative value of the changed zoom, with 1
* 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;
@@ -590,6 +607,8 @@ GuacUI.Client.Pinch = function(element) {
* @event
* @param {Number} ratio The relative value of the final zoom, with 1
* 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;
@@ -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
// them, firing zoom events as appropriate
element.addEventListener("touchmove", function(e) {
@@ -624,19 +677,23 @@ GuacUI.Client.Pinch = function(element) {
// Calculate current zoom level
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 (!start_length) {
start_length = current;
guac_zoom.ratio = 1;
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
else {
guac_zoom.ratio = current / start_length;
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;
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;
}
@@ -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
GuacUI.Client.hideStatus();
@@ -1215,48 +1330,6 @@ GuacUI.Client.attach = function(guac) {
}, 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
*/
@@ -1417,4 +1490,9 @@ GuacUI.Client.attach = function(guac) {
}, 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;
}
div#main {
overflow: auto;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
div.displayOuter {
height: 100%;
width: 100%;
@@ -489,4 +498,18 @@ p.hint {
width: 0;
height: 0;
overflow: hidden;
}
}
/* Menu */
#menu {
overflow: auto;
position: fixed;
top: 0;
left: 0;
bottom: 0;
max-width: 100%;
width: 320px;
padding: 1em;
background: red;
}