Chromium Code Reviews| Index: chrome/browser/resources/vr_shell/vr_shell_ui.js |
| diff --git a/chrome/browser/resources/vr_shell/vr_shell_ui.js b/chrome/browser/resources/vr_shell/vr_shell_ui.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..7ef068739c0f6c67bc89830b80c9fa24b64bd5c2 |
| --- /dev/null |
| +++ b/chrome/browser/resources/vr_shell/vr_shell_ui.js |
| @@ -0,0 +1,236 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +var vrShellUi = (function() { |
| + 'use strict'; |
| + |
| + /** |
| + * Enumeration of valid Anchroing for X axis. |
| + * A mesh can either be anchored to the left, right, or center of the main |
| + * content rect (or it can be absolutely positioned using NONE). Any |
| + * translations applied will be relative to this anchoring. |
| + * @enum {number} |
| + * @const |
| + */ |
| + var XAnchoring = Object.freeze({ |
| + 'XLEFT': 0, |
| + 'XRIGHT': 1, |
| + 'XCENTER': 2, |
| + 'XNONE': 3 |
| + }); |
| + |
| + /** |
| + * Enumeration of valid Anchroing for Y axis. |
| + * @enum {number} |
| + * @const |
| + */ |
| + var YAnchoring = Object.freeze({ |
| + 'YTOP': 0, |
| + 'YBOTTOM': 1, |
| + 'YCENTER': 2, |
| + 'YNONE': 3 |
| + }); |
| + |
| + /** |
| + * Enumeration of animatable properties. |
| + * @enum {number} |
| + * @const |
| + */ |
| + var Property = Object.freeze({ |
| + 'COPYRECT': 0, |
| + 'SIZE': 1, |
| + 'TRANSLATION': 2, |
| + 'ORIENTATION': 3, |
| + 'ROTATION': 4 |
| + }); |
| + |
| + /** |
| + * Enumeration of easing type. |
| + * @enum {number} |
| + * @const |
| + */ |
| + var Easing = Object.freeze({ |
| + 'LINEAR': 0, |
| + 'CUBICBEZIER': 1, |
| + 'EASEIN': 2, |
| + 'EASEOUT': 3 |
| + }); |
| + |
| + /** |
| + * @type {number} Id generator. |
| + */ |
| + var idIndex = 1; |
| + |
| + class UiElement { |
| + /** |
| + * Constructor of UiElement. |
| + * pixelX and pixelY values indicate the left upper corner; pixelWidth and |
| + * pixelHeight is width and height of the texture to be copied from the web |
| + * contents. metersX and metersY indicate the size of the rectangle onto |
| + * which the pixel region will be mapped. |
| + */ |
|
bshe
2016/09/15 22:02:11
I know I didn't quite follow closure jsdoc require
|
| + constructor(pixelX, pixelY, pixelWidth, pixelHeight, metersX, metersY) { |
| + this.copyRect = { |
| + x: pixelX, |
| + y: pixelY, |
| + width: pixelWidth, |
| + height: pixelHeight |
| + }; |
| + this.size = { x: metersX, y: metersY }; |
| + this.xAnchoring = XAnchoring.XNONE; |
| + this.yAnchoring = YAnchoring.YNONE; |
| + this.anchorZ = false; |
| + this.translation = { x: 0, y: 0, z: 0 }; |
| + this.orientationAxisAngle = { x: 0, y: 0, z: 0, a: 0 }; |
| + this.rotationAxisAngle = { x: 0, y: 0, z: 0, a: 0 }; |
| + } |
| + |
| + /** |
| + * The rotation for the mesh in 3D, applied before translation. The |
| + * rotation is axis-angle representation (rotated around unit vector [x, y, |
| + * z] by 'a' radians). |
| + */ |
| + setRotation(x, y, z, a) { |
| + this.rotationAxisAngle = { x: x, y: y, z: z, a: a }; |
| + } |
| + |
| + /** |
| + * The offset for the mesh in 3D. If anchoring is specified, the offset is |
| + * applied to the anchoring position rather than the origin. |
| + */ |
| + setTranslation(x, y, z) { |
| + this.translation = { x: x, y: y, z: z }; |
| + } |
| + |
| + /** |
| + * Anchoring allows a rectangle to be positioned relative to the content |
| + * window. X and Y values should be XAnchoring and YAnchoring elements. |
| + * anchorZ is a boolean. |
| + * Example: rect.setAnchoring(XAnchoring.XCENTER, YAnchoring.YBOTTOM, true); |
| + */ |
| + setAnchoring(x, y, z) { |
| + this.xAnchoring = x; |
| + this.yAnchoring = y; |
| + this.anchorZ = z; |
| + } |
| + }; |
| + |
| + class Animation { |
| + constructor(meshId, durationMs) { |
| + this.meshId = meshId; |
| + this.easing = {}; |
| + this.from = {}; |
| + this.to = {}; |
| + this.easing.type = Easing.LINEAR; |
| + |
| + // How many milliseconds in the future to start the animation. |
| + this.startInMillis = 0.0; |
| + // Duration of the animation (milliseconds). |
| + this.durationMillis = durationMs; |
| + } |
| + |
| + setRotateTo(x, y, z, a) { |
| + this.property = Property.ROTATION; |
| + this.to.x = x; |
| + this.to.y = y; |
| + this.to.z = z; |
| + this.to.a = a; |
| + } |
| + |
| + setResizeTo(newWidth, newHeight) { |
| + this.property = Property.SIZE; |
| + this.to.x = newWidth; |
| + this.to.y = newHeight; |
| + } |
| + }; |
| + |
| + function initialize() { |
| + domLoaded(); |
| + |
| + // Change the body background so that the transparency applies. |
| + window.setTimeout(function() { |
| + document.body.parentNode.style.backgroundColor = 'rgba(255,255,255,0)'; |
|
xiyuan
2016/09/15 22:58:47
Can this be in css to replace
rgba(255, 255, 255
bshe
2016/09/16 18:27:53
Had a quick chat with Micheal. It looks like this
|
| + }, 100); |
| + |
| + addControlButtons(); |
| + } |
| + |
| + // Build a row of control buttons. |
| + function addControlButtons() { |
| + var buttons = [ |
| + // Button text, UI action passed down to native. |
| + ['<', 'HISTORY_BACK'], |
| + ['>', 'HISTORY_FORWARD'], |
| + ['R', 'RELOAD'], |
| + ['-', 'ZOOM_OUT'], |
| + ['+', 'ZOOM_IN'] |
| + ]; |
| + |
| + var buttonWidth = 0.3; |
| + var buttonHeight = 0.2; |
| + var buttonSpacing = 0.5; |
| + var buttonStartPosition = -buttonSpacing * (buttons.length / 2.0 - 0.5); |
| + |
| + for (var i = 0; i < buttons.length; i++) { |
| + var b = document.createElement('div'); |
| + b.position = 'absolute'; |
| + b.style.top = '200px'; |
| + b.style.left = 50 * i + 'px'; |
| + b.style.width = '50px'; |
| + b.style.height = '50px'; |
| + b.className = 'ui-button'; |
| + b.innerHTML = buttons[i][0]; |
|
xiyuan
2016/09/15 22:58:47
nit: innerHTML -> textContent ?
bshe
2016/09/16 18:27:53
Done.
|
| + |
| + // Add click behaviour. |
| + b.addEventListener('click', function(action, e) { |
| + chrome.send('doAction', [action]); |
| + }.bind(undefined, buttons[i][1])); |
| + |
| + document.body.appendChild(b); |
| + |
| + // Add a UI rectangle for the button. |
| + var el1 = new UiElement(50 * i, 200, 50, 50, buttonWidth, buttonHeight); |
|
xiyuan
2016/09/15 22:58:47
nit: why el1? Would there be an el2? If not, we sh
bshe
2016/09/16 18:27:53
Done.
|
| + el1.setAnchoring(XAnchoring.XCENTER, YAnchoring.YBOTTOM, true); |
| + el1.setTranslation(buttonStartPosition + buttonSpacing * i, -0.3, 0.0); |
| + var id = idIndex++; |
| + addMesh(id, el1); |
| + |
| + // Add transitions when the mouse hovers over (and leaves) the button. |
| + b.addEventListener('mouseenter', function(buttonId, width, height, e) { |
| + var resize = new Animation(buttonId, 250); |
| + resize.id = idIndex++; |
| + resize.setResizeTo(width, height); |
| + chrome.send('addAnimations', [resize]); |
| + }.bind(undefined, id, buttonWidth * 1.5, buttonHeight * 1.5)); |
| + b.addEventListener('mouseleave', function(buttonId, width, height) { |
| + var resize = new Animation(buttonId, 250); |
| + resize.id = idIndex++; |
| + resize.setResizeTo(width, height); |
| + chrome.send('addAnimations', [resize]); |
| + }.bind(undefined, id, buttonWidth, buttonHeight)); |
| + } |
| + } |
| + |
| + function domLoaded() { |
| + chrome.send('domLoaded', [window.innerWidth, window.innerHeight]); |
| + } |
| + |
| + function addAnimations(animations) { |
| + chrome.send('addAnimations', animations); |
| + } |
| + |
| + function addMesh(id, mesh) { |
| + chrome.send('addMesh', [id, mesh]); |
| + } |
| + |
| + function removeMesh(id) { |
|
xiyuan
2016/09/15 22:58:47
nit: seems not used.
bshe
2016/09/16 18:27:52
Done.
|
| + chrome.send('removeMesh', [id]); |
| + } |
| + |
| + return { |
| + initialize: initialize, |
| + }; |
| +})(); |
| + |
| +document.addEventListener('DOMContentLoaded', vrShellUi.initialize); |