source: other-projects/playing-in-the-street/summer-2013/trunk/Playing-in-the-Street-WPF/Content/Web.orig/SamplePage.html@ 28897

Last change on this file since 28897 was 28897, checked in by davidb, 10 years ago

GUI front-end to server base plus web page content

File size: 18.1 KB
Line 
1<!DOCTYPE HTML>
2<html>
3<head>
4 <title>Kinect Web Basics</title>
5 <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.1.min.js"></script>
6 <script type="text/javascript" src="Kinect-1.8.0.js"></script>
7 <script type="text/javascript">
8 $(document).ready(function () {
9 var streamImageWidth = 640;
10 var streamImageHeight = 480;
11 var streamImageResolution = streamImageWidth.toString() + "x" + streamImageHeight.toString();
12
13 var isSensorConnected = false;
14 var engagedUser = null;
15 var cursor = null;
16 var userViewerCanvasElement = null;
17 var backgroundRemovalCanvasElement = null;
18
19 // Log errors encountered during sensor configuration
20 function configError(statusText, errorData) {
21 console.log((errorData != null) ? JSON.stringify(errorData) : statusText);
22 }
23
24 // Determine if the specified object has any properties or not
25 function isEmptyObject(obj) {
26 if (obj == null) {
27 return true;
28 }
29
30 var numProperties = 0;
31
32 for (var prop in obj) {
33 if (obj.hasOwnProperty(prop)) {
34 ++numProperties;
35 }
36 }
37
38 return numProperties <= 0;
39 }
40
41 // Show or hide the cursor
42 function setCursorVisibility(isVisible) {
43 if (cursor == null) {
44 return;
45 }
46
47 if (isVisible) {
48 cursor.show();
49 } else {
50 cursor.hide();
51 }
52 }
53
54 // Show or hide a canvas element
55 function setCanvasVisibility(canvasElement, isVisible) {
56 if (canvasElement == null) {
57 return;
58 }
59
60 var canvasQuery = $(canvasElement);
61
62 if (isVisible) {
63 if (!canvasQuery.hasClass("showing")) {
64 // Clear canvas before showing it
65 var canvasContext = canvasElement.getContext("2d");
66 canvasContext.clearRect(0, 0, streamImageWidth, streamImageHeight);
67 }
68
69 canvasQuery.addClass("showing");
70 } else {
71 canvasQuery.removeClass("showing");
72 }
73 }
74
75 var showPanelLabel = "Choose<br/>Background";
76 var hidePanelLabel = "Hide<br/>Panel";
77 function setChoosePanelVisibility(isVisible) {
78 var togglePanelElement = document.getElementById("togglePanelButton");
79 var spanQuery = $("span", togglePanelElement);
80
81 if (isVisible) {
82 // If choose background panel is being shown, hide toggle button
83 // border so top of button is aligned with other buttons
84 $("#choosePanel").addClass("showing");
85 spanQuery.html(hidePanelLabel);
86 } else {
87 // If choose background panel is being hidden, show toggle button
88 // border to provide contrast against picture
89 $("#choosePanel").removeClass("showing");
90 spanQuery.html(showPanelLabel);
91 }
92 }
93
94 function isChoosePanelVisible() {
95 return $("#choosePanel").hasClass("showing");
96 }
97
98 // property and function used to keep track of when the choose background control panel
99 // should be hidden after an inactivity period
100 var hidePanelTimeoutId = null;
101 function resetHidePanelTimeout() {
102 // First clear any previous timeout
103 if (hidePanelTimeoutId != null) {
104 clearTimeout(hidePanelTimeoutId);
105 hidePanelTimeoutId = null;
106 }
107
108 if (!isSensorConnected || (engagedUser == null)) {
109 // if there is no engaged user or no sensor connected, we hide the choose background
110 // control panel after 10 seconds
111 hidePanelTimeoutId = setTimeout(function () {
112 setChoosePanelVisibility(false);
113 hidePanelTimeoutId = null;
114 }, 10000);
115 }
116 }
117
118 // Update sensor state and perform UI transitions (showing/hiding appropriate UI elements)
119 // related to sensor status or engagement state changes
120 var delayedConfigTimeoutId = null;
121 function updateUserState(newIsSensorConnected, newEngagedUser, sensorToConfig) {
122 var hasEngagedUser = engagedUser != null;
123 var newHasEngagedUser = newEngagedUser != null;
124
125 // If there's a pending configuration change when state changes again, cancel previous timeout
126 if (delayedConfigTimeoutId != null) {
127 clearTimeout(delayedConfigTimeoutId);
128 delayedConfigTimeoutId = null;
129 }
130
131 if ((isSensorConnected != newIsSensorConnected) || (engagedUser != newEngagedUser)) {
132 if (newIsSensorConnected) {
133
134 var immediateConfig = {};
135 var delayedConfig = {};
136 immediateConfig[Kinect.INTERACTION_STREAM_NAME] = { "enabled": true };
137 immediateConfig[Kinect.USERVIEWER_STREAM_NAME] = { "resolution": streamImageResolution };
138 immediateConfig[Kinect.BACKGROUNDREMOVAL_STREAM_NAME] = { "resolution": streamImageResolution };
139
140 setCursorVisibility(newHasEngagedUser);
141 setCanvasVisibility(userViewerCanvasElement, !newHasEngagedUser);
142 setCanvasVisibility(backgroundRemovalCanvasElement, newHasEngagedUser);
143
144 if (newHasEngagedUser) {
145 immediateConfig[Kinect.BACKGROUNDREMOVAL_STREAM_NAME].enabled = true;
146 immediateConfig[Kinect.BACKGROUNDREMOVAL_STREAM_NAME].trackingId = newEngagedUser;
147
148 delayedConfig[Kinect.USERVIEWER_STREAM_NAME] = { "enabled": false };
149 } else {
150 immediateConfig[Kinect.USERVIEWER_STREAM_NAME].enabled = true;
151
152 if (hasEngagedUser) {
153 delayedConfig[Kinect.BACKGROUNDREMOVAL_STREAM_NAME] = { "enabled": false };
154 }
155 }
156
157 // Perform immediate configuration
158 sensorToConfig.postConfig(immediateConfig, configError);
159
160 // schedule delayed configuration for 2 seconds later
161 if (!isEmptyObject(delayedConfig)) {
162 delayedConfigTimeoutId = setTimeout(function () {
163 sensorToConfig.postConfig(delayedConfig, configError);
164 delayedConfigTimeoutId = null;
165 }, 2000);
166 }
167 } else {
168 setCursorVisibility(false);
169 setCanvasVisibility(userViewerCanvasElement, false);
170 setCanvasVisibility(backgroundRemovalCanvasElement, false);
171 }
172 }
173
174 isSensorConnected = newIsSensorConnected;
175 engagedUser = newEngagedUser;
176
177 resetHidePanelTimeout();
178 }
179
180 // Get the id of the engaged user, if present, or null if there is no engaged user
181 function findEngagedUser(userStates) {
182 var engagedUserId = null;
183
184 for (var i = 0; i < userStates.length; ++i) {
185 var entry = userStates[i];
186 if (entry.userState == "engaged") {
187 engagedUserId = entry.id;
188 break;
189 }
190 }
191
192 return engagedUserId;
193 }
194
195 // Respond to user state change event
196 function onUserStatesChanged(newUserStates) {
197 var newEngagedUser = findEngagedUser(newUserStates);
198
199 updateUserState(isSensorConnected, newEngagedUser, sensor);
200 }
201
202 // Create sensor and UI adapter layers
203 var sensor = Kinect.sensor(Kinect.DEFAULT_SENSOR_NAME, function (sensorToConfig, isConnected) {
204 if (isConnected) {
205 // Determine what is the engagement state upon connection
206 sensorToConfig.getConfig(function (data) {
207 var engagedUserId = findEngagedUser(data[Kinect.INTERACTION_STREAM_NAME].userStates);
208
209 updateUserState(true, engagedUserId, sensorToConfig);
210 });
211 } else {
212 updateUserState(false, engagedUser, sensorToConfig);
213 }
214 });
215 var uiAdapter = KinectUI.createAdapter(sensor);
216
217 uiAdapter.promoteButtons();
218 cursor = uiAdapter.createDefaultCursor();
219 userViewerCanvasElement = document.getElementById("userViewerCanvas");
220 backgroundRemovalCanvasElement = document.getElementById("backgroundRemovalCanvas");
221 uiAdapter.bindStreamToCanvas(Kinect.USERVIEWER_STREAM_NAME, userViewerCanvasElement);
222 uiAdapter.bindStreamToCanvas(Kinect.BACKGROUNDREMOVAL_STREAM_NAME, backgroundRemovalCanvasElement);
223
224 sensor.addEventHandler(function (event) {
225 switch (event.category) {
226 case Kinect.USERSTATE_EVENT_CATEGORY:
227 switch (event.eventType) {
228 case Kinect.USERSTATESCHANGED_EVENT_TYPE:
229 onUserStatesChanged(event.userStates);
230 break;
231 }
232 break;
233 }
234 });
235
236 setChoosePanelVisibility(false);
237 $("#togglePanelButton").click(function (event) {
238 if (isChoosePanelVisible()) {
239 setChoosePanelVisibility(false);
240 } else {
241 setChoosePanelVisibility(true);
242 resetHidePanelTimeout();
243 }
244 });
245 $(".imgButtonContainer .kinect-button").click(function (event) {
246 var imgElement = $("img", event.currentTarget)[0];
247 document.getElementById("backgroundImg").src = imgElement.src;
248 resetHidePanelTimeout();
249 });
250 });
251 </script>
252 <link rel="stylesheet" type="text/css" href="Kinect-1.8.0.css" />
253 <style type="text/css">
254 html {
255 width: 100%;
256 height: 100%;
257 overflow: hidden;
258 }
259
260 body {
261 width: 100%;
262 height: 100%;
263 margin: 0;
264 overflow: hidden;
265 font-family: 'Segoe UI';
266 }
267
268 #uiContainer {
269 position: relative;
270 margin: 0 auto;
271 width: 100vw;
272 height: 100%;
273 }
274
275 #logoImg {
276 position: absolute;
277 top: 18px;
278 left: 26px;
279 width: 100px;
280 height: 40px;
281 }
282
283 #sampleName {
284 position: relative;
285 display: block;
286 text-align: right;
287 font-size: 16pt;
288 color: gray;
289 top: 24px;
290 margin-right: 26px;
291 }
292
293 #backgroundContainer {
294 position: absolute;
295 top: 80px;
296 width: 100vw;
297 height: 56.25vw;
298 margin-bottom: 26px;
299 }
300
301 @media screen and (max-width: 960px) {
302 #uiContainer {
303 width: 960px;
304 }
305
306 #backgroundContainer {
307 width: 960px;
308 height: 540px;
309 }
310 }
311
312 @media screen and (min-width: 1600px) {
313 #uiContainer {
314 width: 1600px;
315 }
316
317 #backgroundContainer {
318 width: 1600px;
319 height: 900px;
320 }
321 }
322
323 #backgroundImg {
324 width: 100%;
325 height: 100%;
326 }
327
328 .streamImageCanvas {
329 position: absolute;
330 width: 75%;
331 height: 100%;
332 top: 0;
333 left: 12.5%;
334 opacity: 0.0;
335 transition: opacity 1.0s;
336 }
337
338 .streamImageCanvas.showing {
339 opacity: 1.0;
340 transition: opacity 1.0s;
341 }
342
343 #buttonContainer {
344 position: absolute;
345 display: block;
346 width: 100%;
347 height: 160px;
348 bottom: 0;
349 }
350
351 #choosePanel {
352 position: absolute;
353 background-color: white;
354 width: 100%;
355 height: 100%;
356 top: 100%;
357 transition: top 0.4s;
358 }
359
360 #choosePanel.showing {
361 top: 0;
362 transition: top 0.4s;
363 }
364
365 .commandButtonContainer {
366 position: absolute;
367 width: 18%;
368 height: 100%;
369 top: 0;
370 left: 3%;
371 }
372
373 .imgButtonContainer {
374 position: absolute;
375 width: 18%;
376 height: 100%;
377 top: 0;
378 }
379
380 #togglePanelButton {
381 /* Add an explicit background color to make sure mouse/touch events get routed
382 to button even when hovering/pressing over transparent area around button edge. */
383 background-color: rgba(0,0,0,0.0);
384 }
385
386 #imgButtonContainer1 {
387 left: 25%;
388 }
389
390 #imgButtonContainer2 {
391 left: 43%;
392 }
393
394 #imgButtonContainer3 {
395 left: 61%;
396 }
397
398 #imgButtonContainer4 {
399 left: 79%;
400 }
401
402 .kinect-button.tile {
403 position: relative;
404 display: block;
405 width: 170px;
406 height: 100px;
407 margin: 30px auto;
408 padding: 0;
409 }
410
411 .kinect-button.tile .commandButtonContent {
412 position: absolute;
413 width: 100%;
414 height: 100%;
415 border-style: solid;
416 border-color: white;
417 border-width: 2px;
418 transition: border-width 0.15s;
419 left: -2px;
420 top: -2px;
421 }
422
423 .kinect-button.image {
424 position: relative;
425 display: block;
426 width: 170px;
427 height: 100px;
428 margin: 30px auto;
429 padding: 0;
430 }
431
432 .kinect-button img {
433 width: 100%;
434 height: 100%;
435 }
436
437 .kinect-button-text {
438 font-size: 14pt;
439 width: 100%;
440 height: 3em;
441 margin-top: -1.5em;
442 }
443
444 @media screen and (min-width: 1280px) and (max-width: 1600px) {
445 #buttonContainer {
446 height: 186px;
447 }
448
449 .kinect-button.tile {
450 width: 224px;
451 height: 126px;
452 }
453
454 .kinect-button.image {
455 width: 224px;
456 height: 126px;
457 }
458
459 .kinect-button-text {
460 font-size: 16pt;
461 }
462 }
463
464 @media screen and (min-width: 1600px) {
465 #buttonContainer {
466 height: 222px;
467 }
468
469 .kinect-button.tile {
470 width: 288px;
471 height: 162px;
472 }
473
474 .kinect-button.image {
475 width: 288px;
476 height: 162px;
477 }
478
479 .kinect-button-text {
480 font-size: 18pt;
481 }
482 }
483 </style>
484</head>
485<body>
486 <div id="uiContainer">
487 <img id="logoImg" src="Images\logo.png"/>
488 <span id="sampleName">Kinect Web Basics</span>
489 <div id="backgroundContainer">
490 <img id="backgroundImg" src="Images\beach.jpg"/>
491 <canvas id="userViewerCanvas" class="streamImageCanvas"></canvas>
492 <canvas id="backgroundRemovalCanvas" class="streamImageCanvas"></canvas>
493 </div>
494 <div id="buttonContainer">
495 <div id="choosePanel">
496 <div id="imgButtonContainer1" class="imgButtonContainer">
497 <div class="kinect-button image">
498 <img src="Images/beach.jpg"/>
499 </div>
500 </div>
501 <div id="imgButtonContainer2" class="imgButtonContainer">
502 <div class="kinect-button image">
503 <img src="Images/fireworks.jpg"/>
504 </div>
505 </div>
506 <div id="imgButtonContainer3" class="imgButtonContainer">
507 <div class="kinect-button image">
508 <img src="Images/hamlet.jpg"/>
509 </div>
510 </div>
511 <div id="imgButtonContainer4" class="imgButtonContainer">
512 <div class="kinect-button image">
513 <img src="Images/operahouse.jpg"/>
514 </div>
515 </div>
516 </div>
517 <div class="commandButtonContainer">
518 <div id="togglePanelButton" class="kinect-button tile">
519 <div class="commandButtonContent">
520 <span class="kinect-button-text"></span>
521 </div>
522 </div>
523 </div>
524 </div>
525 </div>
526</body>
527</html>
Note: See TracBrowser for help on using the repository browser.