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> |
---|