| // Copyright (c) 2014 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| 'use strict'; |
| |
| /** |
| * Text track. |
| * @constructor |
| */ |
| function TextTrack() { |
| /** |
| * List of actions. |
| * @param {Array.<Object>} |
| * @private |
| */ |
| this.actions_ = [{type: 'clearText', time: 0}]; |
| |
| /** |
| * Current index of the actions_. |
| * @param {number} |
| * @private |
| */ |
| this.index_ = 0; |
| |
| Object.seal(this); |
| } |
| |
| /** |
| * Adds an entry to show the text. |
| * @param {number} tiem Time in seconds to show the text. |
| * @param {string} text Text to be shown. |
| * @param {number} size Ratio of the font size to the screen width. |
| * @param {number} x Horizontal position of the center of the text. 0 is the |
| * center. -50 is the left edge. +50 is the right edge. |
| * @param {number} y Vertical position of hte center of the text. 0 is the |
| * center. -50 is the top edge. +50 is the bottom edge. |
| */ |
| TextTrack.prototype.showText = function(time, text, size, x, y) { |
| this.actions_.push({ |
| type: 'showText', |
| time: time, |
| text: text, |
| size: size, |
| x: x, |
| y: y |
| }); |
| }; |
| |
| /** |
| * Adds an entry to clear the text. |
| * @param {number} tiem Time in seconds to show the text. |
| */ |
| TextTrack.prototype.clearText = function(time) { |
| this.actions_.push({type: 'clearText', time: time}); |
| }; |
| |
| /** |
| * Apply the text of the given time to the element. |
| * @param {time} time Current play position of the video. |
| * @param {DOMElement} element Element to be applied the text. |
| * @param {number} width Width of the screen. |
| */ |
| TextTrack.prototype.play = function(time, element, width) { |
| while (true) { |
| // Usually the current time is satisfy the inequation. |
| // actions_[index] <= time && time < actions_[index + 1] |
| // If the time is out of the range, it updates the index to satisfy the |
| // inequation. |
| |
| var action = this.actions_[this.index_]; |
| if (action.time > time) { |
| this.index_--; |
| continue; |
| } |
| |
| var nextAction = this.actions_[this.index_ + 1]; |
| if (!nextAction || nextAction.time > time) |
| break; |
| switch (nextAction.type) { |
| case 'showText': |
| element.textContent = nextAction.text; |
| element.style.fontSize = (width * nextAction.size) + 'px'; |
| element.style.left = nextAction.x + '%'; |
| element.style.top = nextAction.y + '%'; |
| break; |
| case 'clearText': |
| element.textContent = ''; |
| break; |
| } |
| this.index_++; |
| } |
| }; |
| |
| /** |
| * Root class of the application window. |
| * @constructor |
| */ |
| function Screen() { |
| /** |
| * Background video. |
| * @type {HTMLVideoElement} |
| * @private |
| */ |
| this.backgroundVideo_ = null; |
| |
| /** |
| * Text element. |
| * @type {HTMLElement} |
| * @private |
| */ |
| this.text_ = null; |
| |
| /** |
| * Text track. |
| * @type {TextTrack} |
| * @private |
| */ |
| this.track_ = null; |
| |
| /** |
| * Bounded onFrame_ function. |
| * @type {function()} |
| * @private |
| */ |
| this.onFrameBound_ = this.onFrame_.bind(this); |
| |
| Object.seal(this); |
| window.addEventListener('load', this.onLoad_.bind(this)); |
| }; |
| |
| /** |
| * Creates the text track of the scrennsaver video. |
| * @private |
| */ |
| Screen.createTextTrack_ = function() { |
| var captions = chrome.i18n.getMessage('captions').split(/\s+\|\|\s+/); |
| var track = new TextTrack(); |
| track.showText(0.5, captions[0], 0.05, 0, 0); // rethought |
| track.clearText(1.8); |
| track.showText(2.4, captions[1], 0.04, 0, 0); // chromebook |
| track.clearText(3.8); |
| track.showText(4.5, captions[2], 0.05, -20, 0); // lightweight |
| track.clearText(7); |
| track.showText(8, captions[3], 0.05, 20, 0); // fast |
| track.clearText(10); |
| track.showText(10.8, captions[4], 0.05, 0, 0); // easy_to_use |
| track.showText(11.8, captions[5], 0.05, 0, 0); // easy_to_share |
| track.clearText(12.8); |
| track.showText(13, captions[6], 0.045, 0, 0); // update_itself |
| track.showText(14.6, captions[7], 0.05, 0, 0); // new_now |
| track.clearText(16.2); |
| track.showText(17, captions[8], 0.05, 0, -35); // in_a_year |
| track.showText(19, captions[9], 0.05, 0, -35); // even_newer |
| track.clearText(21); |
| track.showText(22, captions[10], 0.05, 0, -3); // one_click |
| track.clearText(23.1); |
| track.showText(24.5, captions[11], 0.05, -32, 0); // best_of_google |
| track.clearText(27.5); |
| track.showText(29, captions[12], 0.05, 20, 0); // gmail |
| track.clearText(31); |
| track.showText(33, captions[13], 0.05, 0, -42); // youtube |
| track.clearText(37); |
| track.showText(38.3, captions[14], 0.05, -15, 0); // hangouts |
| track.clearText(41.5); |
| track.showText(42, captions[15], 0.05, 0, -40); // docs |
| track.showText(47, captions[16], 0.05, 0, -40); // music |
| track.clearText(51); |
| track.showText(52.5, captions[17], 0.05, 0, 0); // thousands |
| track.showText(55, captions[18], 0.05, 0, 0); // get_it_done |
| track.clearText(57); |
| track.showText(58, captions[19], 0.05, 0, -40); // boots |
| track.showText(60, captions[20], 0.05, 0, -40); // in_seconds |
| track.showText(62, captions[21], 0.05, 0, -40); // virus_protection |
| track.clearText(64.5); |
| track.showText(66.5, captions[22], 0.05, 0, 0); // cloud |
| track.clearText(69); |
| track.showText(71, captions[23], 0.05, 0, -35); // everywhere |
| track.showText(74, captions[24], 0.05, 0, -40); // safe_and_secure |
| track.clearText(77); |
| track.showText(77.5, captions[25], 0.05, 0, -32); // fingertips |
| track.clearText(81.3); |
| track.showText(82.1, captions[26], 0.05, 0, 0); // online |
| track.showText(83.6, captions[27], 0.05, 0, 0); // offline |
| track.clearText(84.5); |
| track.showText(85.5, captions[28], 0.05, 0, -3); // plane |
| track.clearText(88); |
| track.showText(88.9, captions[29], 0.05, 0, -3); // train |
| track.showText(91, captions[30], 0.05, 0, -3); // tree |
| track.clearText(93.7); |
| track.showText(94.8, captions[31], 0.05, 0, 0); // wherever |
| track.clearText(97); |
| track.showText(98, captions[32], 0.05, 20, 0); // dads |
| track.showText(99, captions[33], 0.05, 20, 0); // sisters |
| track.showText(100, captions[34], 0.05, 20, 0); // aunts |
| track.showText(101, captions[35], 0.05, 20, 0); // you |
| track.clearText(102); |
| track.showText(103, captions[36], 0.05, -20, 0); // everyone |
| track.clearText(105); |
| return track; |
| }; |
| |
| /** |
| * Handles load events. |
| * @private |
| */ |
| Screen.prototype.onLoad_ = function() { |
| this.track_ = Screen.createTextTrack_(); |
| this.text_ = document.querySelector('#text'); |
| this.backgroundVideo_ = document.querySelector('#background-video'); |
| this.onFrame_(); |
| }; |
| |
| /** |
| * Handles animation frames and updates the text. |
| * @private |
| */ |
| Screen.prototype.onFrame_ = function() { |
| this.track_.play(this.backgroundVideo_.currentTime, |
| this.text_, |
| document.querySelector('body').offsetWidth); |
| webkitRequestAnimationFrame(this.onFrameBound_); |
| }; |
| |
| var screen = new Screen(); |