Manipulation gestures complete code (HTML)
This topic provides the complete code sample used in Quickstart: Manipulation gestures.
This topic contains these sections:
- Technologies
- Requirements
- View the code ()
Download location
This sample is not available for download.
Technologies
Programming languages | C++ |
Programming models | Windows Runtime |
Requirements
Minimum supported client | Windows 8 |
Minimum supported server | Windows Server 2012 |
Minimum required SDK | Microsoft Visual Studio Express 2012 for Windows 8 |
View the code ()
default.css
body {
/*
A manipulation-blocking element is defined as an element that explicitly
blocks direct manipulation via declarative markup, and instead fires gesture
events such as MSGestureStart, MSGestureChange, and MSGestureEnd.
*/
overflow: hidden;
position: absolute;
font-family: 'Segoe UI';
font-size: small;
touch-action: none;
background-color: black;
}
div #targetContainer {
position: relative;
height: fill-available;
width: fill-available;
}
div #inputBox {
position: relative;
width: 640px;
height: 640px;
color: black;
overflow: hidden;
background-color: darkgrey;
margin: 0px;
padding: 0px;
border-width: 1px;
border-color: white;
border-style: solid;
}
div #instructions {
position: relative;
width: 100%;
height: fit-content;
color: black;
background-color: white;
visibility: visible;
}
div #questions {
position: relative;
width: 100%;
height: fit-content;
color: white;
background-color: black;
visibility: visible;
}
div #answers {
position: relative;
width: 100%;
height: fit-content;
color: white;
background-color: black;
visibility: visible;
}
div #clues {
position: relative;
width: 100%;
height: 100%;
background-color: DimGray;
}
div #timerBox {
background-color: red;
color: black;
position: absolute;
width: 100%;
bottom: 0px;
height: 20px;
text-align: center;
}
div #answerFloater {
position: absolute;
visibility: hidden;
top: 0px;
left: 0px;
background-color: blue;
}
div #eventLog {
font-size: xx-small;
position: absolute;
left: 0px;
top: 0px;
width: 640px;
height: 50px;
overflow: auto;
overflow-style: auto;
}
default.html
<html>
<head>
<meta charset="utf-8" />
<title>Manipulation Gestures</title>
<!-- WinJS references -->
<link rel="stylesheet" href="//Microsoft.WinJS.2.0/css/ui-light.css" />
<script src="//Microsoft.WinJS.2.0/js/base.js"></script>
<script src="//Microsoft.WinJS.2.0/js/ui.js"></script>
<!-- BasicGesture references -->
<link href="/css/default.css" rel="stylesheet" />
<script src="/js/InputProcessor.js"></script>
<script src="/js/ManipulationManager.js"></script>
<script src="/js/default.js"></script>
</head>
<body>
<div class="Container" id="Container">
<div id="targetTitle">Manipulation gestures (rotation)</div>
<div class="TargetContainer" id="targetContainer">
<div id="target" draggable="false"></div>
</div>
<div id="targetFooter"> </div>
</div>
</body>
</html>
default.js
(function () {
"use strict";
/// <summary>
/// Initializes the target and manipulation handling.
/// </summary>
function initialize() {
var container = document.getElementById("targetContainer");
var target = document.getElementById("target");
var title = document.getElementById("targetTitle");
var footer = document.getElementById("targetFooter");
// Set the height of the target container for initial positioning of the target.
var containerHeight = window.innerHeight - title.clientHeight - footer.clientHeight;
container.style.height = containerHeight + "px";
// Set the initial position of the target.
target.style.msTransform = (new MSCSSMatrix()).
translate((container.clientWidth - parseInt(target.clientWidth)) / 2.0,
(containerHeight - parseInt(target.clientHeight)) / 2.0);
// Configure manipulation handling.
var manipulable = new Manipulator.ManipulationManager();
// The configuration function can support all manipulations.
// For this example, we limit manipulation support to rotation with inertia.
manipulable.configure(false,
true, // Rotation.
false,
true, // Inertia.
1,
0,
{
x: (container.clientWidth - parseInt(target.clientWidth)) / 2.0,
y: (containerHeight - parseInt(target.clientHeight)) / 2.0
});
manipulable.setElement(target);
manipulable.setParent(container);
// Handler for transforms related to the manipulation.
manipulable.registerMoveHandler({
x: (container.clientWidth / 2.0),
y: (containerHeight / 2.0)
}, Manipulator.ManipulationManager.FixPivot.MoveHandler);
}
document.addEventListener("DOMContentLoaded", initialize, false);
})();
InputProcessor.js
/// <summary>
/// InputProcessor is a thin wrapper for pointer event handling and gesture detection.
/// Defines an InputProcessor class that takes all pointer event data and feeds it to
/// a GestureRecognizer for processing of the manipulation gestures
/// as configured in ManipulationManager.js.
/// </summary>
(function () {
"use strict";
WinJS.Namespace.define("Manipulator", {
InputProcessor: WinJS.Class.define(function () {
// Constructor.
this._gestureRecognizer = new Windows.UI.Input.GestureRecognizer();
this._downPoint = null;
this._lastState = null;
}, {
// Instance members.
element: {
/// <summary>
/// The manipulable element.
/// </summary>
get: function () {
if (!this._element) {
return null;
}
return this._element;
},
set: function (value) {
this._element = value;
this._setupElement();
}
},
parent: {
/// <summary>
/// The container that defines the coordinate space used
/// for transformations during manipulation of the target.
/// </summary>
get: function () {
if (!this._parent) {
return null;
}
return this._parent;
},
set: function (value) {
this._parent = value;
}
},
getRecognizer: function () {
/// <summary>
/// The gesture recognition object.
/// </summary>
return this._gestureRecognizer;
},
getDown: function () {
/// <summary>
/// The pointer data for the pointerdown event.
/// </summary>
return this._downPoint;
},
_setupElement: function () {
/// <summary>
/// Declare the event listeners for the pointer events on the target.
/// </summary>
var that = this;
this._element.addEventListener("pointerdown",
function (evt) { Manipulator.InputProcessor._handleDown(that, evt); },
false);
this._element.addEventListener("pointermove",
function (evt) { Manipulator.InputProcessor._handleMove(that, evt); },
false);
this._element.addEventListener("pointerup",
function (evt) { Manipulator.InputProcessor._handleUp(that, evt); },
false);
this._element.addEventListener("pointercancel",
function (evt) { Manipulator.InputProcessor._handleCancel(that, evt); },
false);
this._element.addEventListener("wheel",
function (evt) { Manipulator.InputProcessor._handleMouse(that, evt); },
false);
}
}, {
// Static members.
_handleDown: function (that, evt) {
/// <summary>
/// Handler for the pointerdown event.
/// </summary>
/// <param name="that" type="Object">
/// The InputProcessor object handling this event.
/// </param>
/// <param name="evt" type="Event">
/// The event object.
/// </param>
var pp = evt.getCurrentPoint(that._parent);
that._element.setPointerCapture(pp.pointerId);
that._gestureRecognizer.processDownEvent(pp);
// Prevent propagation of this event to additional event handlers.
evt.stopImmediatePropagation();
// Capture the pointer location for this event.
that._downPoint = { x: pp.position.x, y: pp.position.y };
},
_handleMove: function (that, evt) {
/// <summary>
/// Handler for the pointermove event.
/// </summary>
/// <param name="that" type="Object">
/// The InputProcessor object handling this event.
/// </param>
/// <param name="evt" type="Event">
/// The event object.
/// </param>
var pps = evt.getIntermediatePoints(that._parent);
that._gestureRecognizer.processMoveEvents(pps);
// Prevent propagation of this event to additional event handlers.
evt.stopImmediatePropagation();
},
_handleUp: function (that, evt) {
/// <summary>
/// Handler for the pointerup event.
/// </summary>
/// <param name="that" type="Object">
/// The InputProcessor object handling this event.
/// </param>
/// <param name="evt" type="Event">
/// The event object.
/// </param>
var pp = evt.getCurrentPoint(that._parent);
that._gestureRecognizer.processUpEvent(pp);
// Prevent propagation of this event to additional event handlers.
evt.stopImmediatePropagation();
},
_handleCancel: function (that, evt) {
/// <summary>
/// Handler for the pointercancel event.
/// </summary>
/// <param name="that" type="Object">
/// The InputProcessor object handling this event.
/// </param>
/// <param name="evt" type="Event">
/// The event object.
/// </param>
that._gestureRecognizer.completeGesture();
// Prevent propagation of this event to additional event handlers.
evt.stopImmediatePropagation();
},
_handleMouse: function (that, evt) {
/// <summary>
/// Handler for the mouse wheel event.
/// </summary>
/// <param name="that" type="Object">
/// The InputProcessor object handling this event.
/// </param>
/// <param name="evt" type="Event">
/// The event object.
/// </param>
var pp = evt.getCurrentPoint(that._parent);
that._gestureRecognizer.processMouseWheelEvent(pp, evt.shiftKey, evt.ctrlKey);
// Prevent propagation of this event to additional event handlers.
evt.stopImmediatePropagation();
evt.preventDefault();
}
})
});
})();
ManipulationManager.js
/// <summary>
/// ManipulationManager is the manipulation processing engine for the
/// GestureRecognizer object defined in InputProcessor.js.
/// Different components and behaviors of manipulation (rotate, translate, zoom,
/// and inertia) can be enabled, disabled, and customized as required.
/// </summary>
(function () {
"use strict";
WinJS.Namespace.define("Manipulator", {
ManipulationManager: WinJS.Class.define(function () {
// Constructor.
// Create an input processor.
this._inputProcessor = new Manipulator.InputProcessor();
// Initialize the manipulation movement and end handlers.
this._endHandler = null;
this._moveHandler = null;
// Create the transform matrices used for manipulating
// and resetting the target.
this._currentTransform = new MSCSSMatrix();
this._initialTransform = new MSCSSMatrix();
// Initialize the transform matrices values.
this._initialTransformParams = {
translation: { x: 0, y: 0 },
rotation: 0,
scale: 1
};
this._currentTransformParams = {
translation: { x: 0, y: 0 },
rotation: 0,
scale: 1
};
}, {
// Instance members.
configure: function (scale, rotate, translate, inertia,
initialScale, initialRotate, initialTranslate) {
/// <summary>
/// Define the behaviors of the ManipulationManager object.
/// </summary>
/// <param name="scale" type="Boolean">
/// True if scaling is enabled.
/// </param>
/// <param name="rotate" type="Boolean">
/// True if rotation is enabled.
/// </param>
/// <param name="translate" type="Boolean">
/// True if translation is enabled.
/// </param>
/// <param name="inertia" type="Boolean">
/// True if inertia is enabled.
/// </param>
/// <param name="initialScale" type="Number">
/// The initial scale factor.
/// </param>
/// <param name="initialRotate" type="Number">
/// The initial rotation value.
/// </param>
/// <param name="initialTranslate" type="Object">
/// The initial translation values (x,y).
/// </param>
// Get the GestureRecognizer associated with this manipulation manager.
var gr = this._inputProcessor.getRecognizer();
// Set the manipulations supported by the GestureRecognizer if the
// interaction is not already being processed.
if (!gr.isActive) {
var settings = 0;
if (scale) {
settings |= Windows.UI.Input.GestureSettings.manipulationScale;
if (inertia) {
settings |= Windows.UI.Input.GestureSettings.manipulationScaleInertia;
}
}
if (rotate) {
settings |= Windows.UI.Input.GestureSettings.manipulationRotate;
if (inertia) {
settings |= Windows.UI.Input.GestureSettings.manipulationRotateInertia;
}
}
if (translate) {
settings |= Windows.UI.Input.GestureSettings.manipulationTranslateX |
Windows.UI.Input.GestureSettings.manipulationTranslateY;
if (inertia) {
settings |= Windows.UI.Input.GestureSettings.manipulationTranslateInertia;
}
}
// Cache a reference to the current object.
var that = this;
// If any manipulation is supported, declare the manipulation event listeners.
if (scale || rotate || translate) {
gr.addEventListener('manipulationstarted',
function (evt) { Manipulator.ManipulationManager._manipulationStarted(that, evt); },
false);
gr.addEventListener('manipulationupdated',
function (evt) { Manipulator.ManipulationManager._manipulationUpdated(that, evt); },
false);
gr.addEventListener('manipulationended',
function (evt) { Manipulator.ManipulationManager._manipulationEnded(that, evt); },
false);
}
gr.gestureSettings = settings;
// Initialize the transform matrices.
this._currentTransformParams.scale = initialScale;
this._currentTransformParams.rotation = initialRotate;
this._currentTransformParams.translation = initialTranslate;
this._initialTransformParams.scale = initialScale;
this._initialTransformParams.rotation = initialRotate;
this._initialTransformParams.translation = initialTranslate;
// Set the transformation values.
if (initialRotate) {
this._initialTransform = this._initialTransform.rotate(initialRotate);
}
else {
this._currentTransformParams.rotation = 0;
this._initialTransformParams.rotation = 0;
}
if (initialTranslate) {
this._initialTransform = this._initialTransform.translate(initialTranslate.x, initialTranslate.y);
}
else {
this._currentTransformParams.translation = { x: 0, y: 0 };
this._initialTransformParams.translation = { x: 0, y: 0 };
}
if (initialScale) {
this._initialTransform = this._initialTransform.scale(initialScale);
}
else {
this._currentTransformParams.scale = 1;
this._initialTransformParams.scale = 1;
}
this._currentTransform = this._initialTransform;
}
},
setElement: function (elm) {
/// <summary>
/// Set the manipulable object.
/// </summary>
/// <param name="elm" type="Object">
/// The object that supports manipulation.
/// </param>
this._inputProcessor.element = elm;
// Set the transform origin for rotation and scale manipulations.
this._inputProcessor.element.style.msTransformOrigin = "0 0";
},
setParent: function (elm) {
/// <summary>
/// Set the parent of the manipulable object.
/// </summary>
/// <param name="elm" type="Object">
/// The parent of the object that supports manipulation.
/// </param>
this._inputProcessor.parent = elm;
},
registerEndHandler: function (handler) {
/// <summary>
/// Register handler to be called after the manipulation is complete.
/// </summary>
/// <param name="handler" type="Function">
/// The manipulationended event handler.
/// </param>
this._endHandler = handler;
},
registerMoveHandler: function (arg, handler) {
/// <summary>
/// Register handler to be called when manipulation is under way.
/// </summary>
/// <param name="args">
/// Arguments passed to the move handler function.
/// </param>
/// <param name="handler" type="Function">
/// The manipulationupdated event handler.
/// </param>
this._moveHandlerArg = arg;
this._moveHandler = handler;
},
resetAllTransforms: function () {
/// <summary>
/// Reset the ManipulationManager object to its initial state.
/// </summary>
// Check that the element has been registered before before attempting to reset.
if (this._inputProcessor.element) {
// Reapply the initial transform
this._inputProcessor.element.style.transform = this._initialTransform.toString();
this._currentTransform = this._initialTransform;
// Reset the current transform parameters to their initial values.
this._currentTransformParams.translation = this._initialTransformParams.translation;
this._currentTransformParams.rotation = this._initialTransformParams.rotation;
this._currentTransformParams.scale = this._initialTransformParams.scale;
}
},
_applyMotion: function (pivot, translation, rotation, scaling) {
/// <summary>
/// Apply the manipulation transform to the target.
/// </summary>
/// <param name="pivot" type="Object">
/// The X,Y values for the rotation and scaling pivot point.
/// </param>
/// <param name="translation" type="Object">
/// The X,Y values for the translation delta.
/// </param>
/// <param name="rotation" type="Number">
/// The angle of rotation.
/// </param>
/// <param name="scaling" type="Number">
/// The scaling factor.
/// </param>
// Create the transform, apply parameters, and multiply by the current transform matrix.
var transform = new MSCSSMatrix().translate(pivot.x, pivot.y).
translate(translation.x, translation.y).
rotate(rotation).
scale(scaling).
translate(-pivot.x, -pivot.y).multiply(this._currentTransform);
this._inputProcessor.element.style.transform = transform.toString();
this._currentTransform = transform;
},
_updateTransformParams: function (delta) {
/// <summary>
/// Update the current transformation parameters based on the new delta.
/// </summary>
/// <param name="that" type="Object">
/// The change in rotation, scaling, and translation.
/// </param>
this._currentTransformParams.translation.x = this._currentTransformParams.translation.x + delta.translation.x;
this._currentTransformParams.translation.y = this._currentTransformParams.translation.y + delta.translation.y;
this._currentTransformParams.rotation = this._currentTransformParams.rotation + delta.rotation;
this._currentTransformParams.scale = this._currentTransformParams.scale * delta.scale;
}
}, {
// Static members.
_manipulationStarted: function (that, evt) {
/// <summary>
/// The manipulationstarted event handler.
/// </summary>
/// <param name="that" type="Object">
/// ManipulationManager object on which the event was performed.
/// </param>
/// <param name="evt" type="Event">
/// The event data.
/// </param>
Manipulator.ManipulationManager._manipulationHelper(that, evt);
},
_manipulationUpdated: function (that, evt) {
/// <summary>
/// The manipulationupdated event handler.
/// </summary>
/// <param name="that" type="Object">
/// ManipulationManager object on which the event was performed.
/// </param>
/// <param name="evt" type="Event">
/// The event data.
/// </param>
Manipulator.ManipulationManager._manipulationHelper(that, evt);
},
_manipulationEnded: function (that, evt) {
/// <summary>
/// The manipulationended event handler.
/// </summary>
/// <param name="that" type="Object">
/// ManipulationManager object on which the event was performed.
/// </param>
/// <param name="evt" type="Event">
/// The event data.
/// </param>
// Pass the event to the manipulation helper function.
Manipulator.ManipulationManager._manipulationHelper(that, evt);
// Call the manipulationended handler, if registered.
if (that._endHandler) {
that._endHandler();
}
},
_manipulationHelper: function (that, evt) {
/// <summary>
/// Helper function for calculating and applying the transformation parameter deltas.
/// </summary>
/// <param name="that" type="Object">
/// ManipulationManager object on which the event was performed.
/// </param>
/// <param name="evt" type="Event">
/// The event data.
/// </param>
if (evt.delta) {
// Rotation/scaling pivot point.
var pivot = { x: evt.position.x, y: evt.position.y };
// Translation values.
var translation = { x: evt.delta.translation.x, y: evt.delta.translation.y };
// Rotation angle.
var rotation = evt.delta.rotation;
// Scale factor.
var scale = evt.delta.scale;
// Group the transformation parameter deltas.
var delta = {
pivot: pivot,
translation: translation,
rotation: rotation,
scale: scale
};
// Apply the manipulation movement constraints.
if (that._moveHandler) {
delta = that._moveHandler(that._moveHandlerArg, delta, that._currentTransformParams, that._currentTransform);
}
// Update the transformation parameters with fresh deltas.
that._updateTransformParams(delta);
// Apply the transformation.
that._applyMotion(delta.pivot, delta.translation, delta.rotation, delta.scale);
}
},
FixPivot: WinJS.Class.define(function () {
/// <summary>
/// Constrain the center of manipulation (or pivot point) to a set of X,Y coordinates,
/// instead of the centroid of the pointers associated with the manipulation.
/// <param name="pivot" type="Object">
/// The pivot coordinates for the ManipulationManager object.
/// </param>
/// <param name="delta" type="Object">
/// The transformation parameter deltas (pivot, delta, rotation, scale).
/// </param>
/// </summary>
}, {
}, {
MoveHandler: function (pivot, delta) {
delta.pivot = pivot;
return delta;
}
}),
})
});
})();