Commit 4a9611cd authored by nextime's avatar nextime

Initial commit

parents
# http://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
module.exports = {
"env": {
"browser": true,
"es6": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"rules": {
"no-console": "off"
}
};
\ No newline at end of file
# OS
Thumbs.db
ehthumbs.db
Desktop.ini
.DS_Store
._*
# Editors
*~
*.swp
*.tmproj
*.tmproject
*.sublime-*
.idea/
.project/
.settings/
.vscode/
# Logs
logs
*.log
npm-debug.log*
# Dependency directories
bower_components/
node_modules/
# Build-related directories
docs/api/
test/dist/
.eslintcache
.yo-rc.json
# Intentionally left blank, so that npm does not ignore anything by default,
# but relies on the package.json "files" array to explicitly define what ends
# up in the package.
dist: xenial
language: node_js
# node version is specified using the .nvmrc file
cache: npm
before_install:
- npm install -g greenkeeper-lockfile@1
before_script:
- greenkeeper-lockfile-update
after_script:
- greenkeeper-lockfile-upload
addons:
firefox: latest
chrome: stable
services:
- xvfb
<a name="0.1.0"></a>
# [0.1.0](https://github.com/thomasdeppisch/videojs-xr/compare/v0.0.5...v0.1.0) (2021-03-09)
<a name="0.0.5"></a>
## [0.0.5](https://github.com/thomasdeppisch/videojs-xr/compare/v0.0.4...v0.0.5) (2021-03-09)
<a name="0.0.4"></a>
## [0.0.4](https://github.com/thomasdeppisch/videojs-xr/compare/v0.0.3...v0.0.4) (2021-03-02)
<a name="0.0.3"></a>
## [0.0.3](https://github.com/thomasdeppisch/videojs-xr/compare/v0.0.2...v0.0.3) (2020-05-11)
<a name="0.0.2"></a>
## 0.0.2 (2020-05-11)
# CONTRIBUTING
We welcome contributions from everyone!
## Getting Started
Make sure you have Node.js 8 or higher and npm installed.
1. Fork this repository and clone your fork
1. Install dependencies: `npm install`
1. Run a development server: `npm start`
### Making Changes
Refer to the [video.js plugin conventions][conventions] for more detail on best practices and tooling for video.js plugin authorship.
When you've made your changes, push your commit(s) to your fork and issue a pull request against the original repository.
### Running Tests
Testing is a crucial part of any software project. For all but the most trivial changes (typos, etc) test cases are expected. Tests are run in actual browsers using [Karma][karma].
- In all available and supported browsers: `npm test`
- In a specific browser: `npm run test:chrome`, `npm run test:firefox`, etc.
- While development server is running (`npm start`), navigate to [`http://localhost:9999/test/`][local]
[karma]: http://karma-runner.github.io/
[local]: http://localhost:9999/test/
[conventions]: https://github.com/videojs/generator-videojs-plugin/blob/master/docs/conventions.md
Original codebase: Copyright (c) Thomas Deppisch
180_LR implementation: Copyright (C) Franco Lanza
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# videojs-xr
This is a plugin for using WebXR with [videojs](https://github.com/videojs), based on [videojs-vr](https://github.com/videojs/videojs-vr) and forked from [videojs-xr](https://github.com/thomasdeppisch/videojs-xr). Videojs-xr supports the Oculus browser and Firefox Reality on Oculus Quest. For a jump start how to use it with videojs see the [index.html](https://github.com/thomasdeppisch/videojs-xr/blob/master/index.html).
You can see it in action [here (NSFW! it's PORN!)](https://www.sexhack.me/v/vr180-3d-blowcum/).
Currently the only supported video format is stereo 180° LR side by side equirectangular.
## Installation
```sh
npm install --save videojs-xr
```
## Usage
To include videojs-xr on your website or web application, use any of the following methods.
### `<script>` Tag
This is the simplest case. Get the script in whatever way you prefer and include the plugin _after_ you include [video.js][videojs], so that the `videojs` global is available.
```html
<script src="//path/to/video.min.js"></script>
<script src="//path/to/videojs-xr.min.js"></script>
<script>
var player = videojs('my-video');
player.xr();
</script>
```
### Browserify/CommonJS
When using with Browserify, install videojs-xr via npm and `require` the plugin as you would any other module.
```js
var videojs = require('video.js');
// The actual plugin function is exported by this module, but it is also
// attached to the `Player.prototype`; so, there is no need to assign it
// to a variable.
require('videojs-xr');
var player = videojs('my-video');
player.xr();
```
### RequireJS/AMD
When using with RequireJS (or another AMD library), get the script in whatever way you prefer and `require` the plugin as you normally would:
```js
require(['video.js', 'videojs-xr'], function(videojs) {
var player = videojs('my-video');
player.xr();
});
```
## License
MIT. Copyright (c) Thomas Deppisch
[videojs]: http://videojs.com/
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>videojs-xr Demo</title>
<!-- <link href="node_modules/video.js/dist/video-js.css" rel="stylesheet"> -->
<link href="https://vjs.zencdn.net/7.10.2/video-js.css" rel="stylesheet" />
<link href="./dist/videojs-xr.css" rel="stylesheet">
</head>
<body>
<video id="videojs-xr-player" class="video-js vjs-default-skin" controls>
<!-- <source src="//vjs.zencdn.net/v/oceans.mp4" type='video/mp4'>
<source src="//vjs.zencdn.net/v/oceans.webm" type='video/webm'> -->
<source src="./media/hoast_analyzer.mp4" type='video/mp4'>
</video>
<ul>
<li><a href="/test/debug.html">Run unit tests in browser.</a></li>
</ul>
<script src="https://vjs.zencdn.net/7.10.2/video.min.js"></script>
<script src="./dist/videojs-xr.js"></script>
<script>
(function(window, videojs) {
var examplePlayer = window.examplePlayer = videojs('videojs-xr-player');
var xr = window.xr = examplePlayer.xr();
}(window, window.videojs));
</script>
</body>
</html>
This diff is collapsed.
{
"name": "videojs-xr",
"version": "0.1.0",
"description": "Plugin for using WebXR with videojs, based on videojs-vr",
"main": "dist/videojs-xr.cjs.js",
"module": "dist/videojs-xr.es.js",
"repository": "https://github.com/thomasdeppisch/videojs-xr",
"generator-videojs-plugin": {
"version": "7.6.3"
},
"browserslist": [
"defaults",
"ie 11"
],
"scripts": {
"prebuild": "npm run clean",
"build": "npm-run-all -p build:*",
"build:css": "postcss -o dist/videojs-xr.css --config scripts/postcss.config.js src/plugin.css",
"build:js": "rollup -c scripts/rollup.config.js",
"clean": "shx rm -rf ./dist ./test/dist",
"postclean": "shx mkdir -p ./dist ./test/dist",
"lint": "vjsstandard",
"server": "karma start scripts/karma.conf.js --singleRun=false --auto-watch",
"start": "npm-run-all -p server watch",
"pretest": "npm-run-all lint build",
"test": "npm-run-all test:*",
"posttest": "shx cat test/dist/coverage/text.txt",
"test:unit": "karma start scripts/karma.conf.js",
"test:verify": "vjsverify --skip-es-check --verbose",
"update-changelog": "conventional-changelog -p videojs -i CHANGELOG.md -s",
"preversion": "npm test",
"version": "is-prerelease || npm run update-changelog && git add CHANGELOG.md",
"watch": "npm-run-all -p watch:*",
"watch:css": "npm run build:css -- -w",
"watch:js": "npm run build:js -- -w"
},
"engines": {
"node": ">=8",
"npm": ">=5"
},
"keywords": [
"videojs",
"videojs-plugin"
],
"author": "Thomas Deppisch",
"license": "MIT",
"vjsstandard": {
"ignore": [
"dist",
"docs",
"test/dist"
]
},
"files": [
"CONTRIBUTING.md",
"dist/",
"docs/",
"index.html",
"scripts/",
"src/",
"test/"
],
"husky": {
"hooks": {}
},
"dependencies": {
"global": "^4.4.0",
"shx": "^0.3.4",
"three": "^0.125.2",
"video.js": "^7.7.6",
"webxr-polyfill": "^2.0.2"
},
"devDependencies": {
"@videojs/generator-helpers": "~1.0.0",
"babel-polyfill": "^6.26.0",
"eslint": "^6.8.0",
"karma": "^4.4.1",
"postcss-cli": "^6.0.0",
"rollup": "^1.32.1",
"sinon": "^7.5.0",
"videojs-generate-karma-config": "^5.3.1",
"videojs-generate-postcss-config": "~2.1.0",
"videojs-generate-rollup-config": "^3.2.1",
"videojs-generator-verify": "~1.2.0",
"videojs-standard": "^8.0.4"
}
}
const generate = require('videojs-generate-karma-config');
module.exports = function(config) {
// see https://github.com/videojs/videojs-generate-karma-config
// for options
const options = {};
config = generate(config, options);
// any other custom stuff not supported by options here!
};
const generate = require('videojs-generate-postcss-config');
module.exports = function(context) {
const result = generate({}, context);
// do custom stuff here
return result;
};
const generate = require('videojs-generate-rollup-config');
// see https://github.com/videojs/videojs-generate-rollup-config
// for options
const options = {};
const config = generate(options);
// Add additonal builds/customization here!
// export the builds to rollup
export default Object.values(config.builds);
/**
* @author richt / http://richt.me
* @author WestLangley / http://github.com/WestLangley
*
* W3C Device Orientation control (http://w3c.github.io/deviceorientation/spec-source-orientation.html)
*/
import {
Euler,
MathUtils,
Quaternion,
Vector3
} from "three";
var DeviceOrientationControls = function ( object ) {
var scope = this;
this.object = object;
this.object.rotation.reorder( 'YXZ' );
this.enabled = true;
this.deviceOrientation = {};
this.screenOrientation = 0;
this.alphaOffset = 0; // radians
var onDeviceOrientationChangeEvent = function ( event ) {
scope.deviceOrientation = event;
};
var onScreenOrientationChangeEvent = function () {
scope.screenOrientation = window.orientation || 0;
};
// The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y''
var setObjectQuaternion = function () {
var zee = new Vector3( 0, 0, 1 );
var euler = new Euler();
var q0 = new Quaternion();
var q1 = new Quaternion( - Math.sqrt( 0.5 ), 0, 0, Math.sqrt( 0.5 ) ); // - PI/2 around the x-axis
return function ( quaternion, alpha, beta, gamma, orient ) {
euler.set( beta, alpha, - gamma, 'YXZ' ); // 'ZXY' for the device, but 'YXZ' for us
quaternion.setFromEuler( euler ); // orient the device
quaternion.multiply( q1 ); // camera looks out the back of the device, not the top
quaternion.multiply( q0.setFromAxisAngle( zee, - orient ) ); // adjust for screen orientation
};
}();
this.connect = function () {
onScreenOrientationChangeEvent(); // run once on load
// iOS 13+
if ( window.DeviceOrientationEvent !== undefined && typeof window.DeviceOrientationEvent.requestPermission === 'function' ) {
window.DeviceOrientationEvent.requestPermission().then( function ( response ) {
if ( response == 'granted' ) {
window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );
window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
}
} ).catch( function ( error ) {
console.error( 'THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:', error );
} );
} else {
window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );
window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
}
scope.enabled = true;
};
this.disconnect = function () {
window.removeEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );
window.removeEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
scope.enabled = false;
};
this.update = function () {
if ( scope.enabled === false ) return;
var device = scope.deviceOrientation;
if ( device ) {
var alpha = device.alpha ? MathUtils.degToRad( device.alpha ) + scope.alphaOffset : 0; // Z
var beta = device.beta ? MathUtils.degToRad( device.beta ) : 0; // X'
var gamma = device.gamma ? MathUtils.degToRad( device.gamma ) : 0; // Y''
var orient = scope.screenOrientation ? MathUtils.degToRad( scope.screenOrientation ) : 0; // O
setObjectQuaternion( scope.object.quaternion, alpha, beta, gamma, orient );
}
};
this.dispose = function () {
scope.disconnect();
};
this.connect();
};
export { DeviceOrientationControls };
This diff is collapsed.
import videojs from 'video.js';
const BigPlayButton = videojs.getComponent('BigPlayButton');
class BigVrPlayButton extends BigPlayButton {
buildCSSClass() {
return `vjs-big-vr-play-button ${super.buildCSSClass()}`;
}
}
videojs.registerComponent('BigVrPlayButton', BigVrPlayButton);
export default BigVrPlayButton;
import videojs from 'video.js';
/**
* This class reacts to interactions with the canvas and
* triggers appropriate functionality on the player. Right now
* it does two things:
*
* 1. A `mousedown`/`touchstart` followed by `touchend`/`mouseup` without any
* `touchmove` or `mousemove` toggles play/pause on the player
* 2. Only moving on/clicking the control bar or toggling play/pause should
* show the control bar. Moving around the scene in the canvas should not.
*/
class CanvasPlayerControls extends videojs.EventTarget {
constructor(player, canvas) {
super();
this.player = player;
this.canvas = canvas;
this.onMoveEnd = videojs.bind(this, this.onMoveEnd);
this.onMoveStart = videojs.bind(this, this.onMoveStart);
this.onMove = videojs.bind(this, this.onMove);
this.onControlBarMove = videojs.bind(this, this.onControlBarMove);
this.player.controlBar.on([
'mousedown',
'mousemove',
'mouseup',
'touchstart',
'touchmove',
'touchend'
], this.onControlBarMove);
// we have to override these here because
// video.js listens for user activity on the video element
// and makes the user active when the mouse moves.
// We don't want that for 3d videos
this.oldReportUserActivity = this.player.reportUserActivity;
this.player.reportUserActivity = () => {};
// canvas movements
this.canvas.addEventListener('mousedown', this.onMoveStart);
this.canvas.addEventListener('touchstart', this.onMoveStart);
this.canvas.addEventListener('mousemove', this.onMove);
this.canvas.addEventListener('touchmove', this.onMove);
this.canvas.addEventListener('mouseup', this.onMoveEnd);
this.canvas.addEventListener('touchend', this.onMoveEnd);
this.shouldTogglePlay = false;
}
togglePlay() {
this.trigger('vrtoggleplay');
}
onMoveStart(e) {
// if the player does not have a controlbar or
// the move was a mouse click but not left click do not
// toggle play.
if (!this.player.controls() || (e.type === 'mousedown' && !videojs.dom.isSingleLeftClick(e))) {
this.shouldTogglePlay = false;
return;
}
this.shouldTogglePlay = true;
this.touchMoveCount_ = 0;
}
onMoveEnd(e) {
// We want to have the same behavior in VR360 Player and standar player.
// in touchend we want to know if was a touch click, for a click we show the bar,
// otherwise continue with the mouse logic.
//
// Maximum movement allowed during a touch event to still be considered a tap
// Other popular libs use anywhere from 2 (hammer.js) to 15,
// so 10 seems like a nice, round number.
if (e.type === 'touchend' && this.touchMoveCount_ < 10) {
if (this.player.userActive() === false) {
this.player.userActive(true);
return;
}
this.player.userActive(false);
return;
}
if (!this.shouldTogglePlay) {
return;
}
// We want the same behavior in Desktop for VR360 and standar player
if (e.type === 'mouseup') {
this.togglePlay();
}
}
onMove(e) {
// Increase touchMoveCount_ since Android detects 1 - 6 touches when user click normaly
this.touchMoveCount_++;
this.shouldTogglePlay = false;
}
onControlBarMove(e) {
this.player.userActive(true);
}
dispose() {
this.canvas.removeEventListener('mousedown', this.onMoveStart);
this.canvas.removeEventListener('touchstart', this.onMoveStart);
this.canvas.removeEventListener('mousemove', this.onMove);
this.canvas.removeEventListener('touchmove', this.onMove);
this.canvas.removeEventListener('mouseup', this.onMoveEnd);
this.canvas.removeEventListener('touchend', this.onMoveEnd);
this.player.controlBar.off([
'mousedown',
'mousemove',
'mouseup',
'touchstart',
'touchmove',
'touchend'
], this.onControlBarMove);
this.player.reportUserActivity = this.oldReportUserActivity;
}
}
export default CanvasPlayerControls;
import window from 'global/window';
import videojs from 'video.js';
// Add Cardboard button
const Button = videojs.getComponent('Button');
class CardboardButton extends Button {
constructor(player, options) {
super(player, options);
// this.handleVrDisplayActivate_ = videojs.bind(this, this.handleVrDisplayActivate_);
// this.handleVrDisplayDeactivate_ = videojs.bind(this, this.handleVrDisplayDeactivate_);
// this.handleVrDisplayPresentChange_ = videojs.bind(this, this.handleVrDisplayPresentChange_);
// this.handleOrientationChange_ = videojs.bind(this, this.handleOrientationChange_);
// window.addEventListener('orientationchange', this.handleOrientationChange_);
// window.addEventListener('vrdisplayactivate', this.handleVrDisplayActivate_);
// window.addEventListener('vrdisplaydeactivate', this.handleVrDisplayDeactivate_);
// vrdisplaypresentchange does not fire activate or deactivate
// and happens when hitting the back button during cardboard mode
// so we need to make sure we stay in the correct state by
// listening to it and checking if we are presenting it or not
// window.addEventListener('vrdisplaypresentchange', this.handleVrDisplayPresentChange_);
// we cannot show the cardboard button in fullscreen on
// android as it breaks the controls, and makes it impossible
// to exit cardboard mode
// if (videojs.browser.IS_ANDROID) {
// this.on(player, 'fullscreenchange', () => {
// if (player.isFullscreen()) {
// this.hide();
// } else {
// this.show();
// }
// });
// }
}
buildCSSClass() {
return `vjs-button-vr ${super.buildCSSClass()}`;
}
// handleVrDisplayPresentChange_() {
// if (!this.player_.vr().vrDisplay.isPresenting && this.active_) {
// this.handleVrDisplayDeactivate_();
// }
// if (this.player_.vr().vrDisplay.isPresenting && !this.active_) {
// this.handleVrDisplayActivate_();
// }
// }
// handleOrientationChange_() {
// if (this.active_ && videojs.browser.IS_IOS) {
// this.changeSize_();
// }
// }
// changeSize_() {
// this.player_.width(window.innerWidth);
// this.player_.height(window.innerHeight);
// window.dispatchEvent(new window.Event('resize'));
// }
// handleVrDisplayActivate_() {
// // we mimic fullscreen on IOS
// if (videojs.browser.IS_IOS) {
// this.oldWidth_ = this.player_.currentWidth();
// this.oldHeight_ = this.player_.currentHeight();
// this.player_.enterFullWindow();
// this.changeSize_();
// }
// this.active_ = true;
// }
// handleVrDisplayDeactivate_() {
// // un-mimic fullscreen on iOS
// if (videojs.browser.IS_IOS) {
// if (this.oldWidth_) {
// this.player_.width(this.oldWidth_);
// }
// if (this.oldHeight_) {
// this.player_.height(this.oldHeight_);
// }
// this.player_.exitFullWindow();
// }
// this.active_ = false;
// }
handleClick(event) {
// if cardboard mode display is not active, activate it
// otherwise deactivate it
if (!this.active_) {
// This starts playback mode when the cardboard button
// is clicked on Andriod. We need to do this as the controls
// disappear
// if (!this.player_.hasStarted() && videojs.browser.IS_ANDROID) {
// this.player_.play();
// }
window.dispatchEvent(new window.Event('vrdisplayactivate'));
this.active_ = true;
} else {
window.dispatchEvent(new window.Event('vrdisplaydeactivate'));
this.active_ = false;
}
}
dispose() {
super.dispose();
// window.removeEventListener('vrdisplayactivate', this.handleVrDisplayActivate_);
// window.removeEventListener('vrdisplaydeactivate', this.handleVrDisplayDeactivate_);
// window.removeEventListener('vrdisplaypresentchange', this.handleVrDisplayPresentChange_);
}
}
videojs.registerComponent('CardboardButton', CardboardButton);
export default CardboardButton;
import * as THREE from 'three';
import { OrbitControls } from './OrbitControls.js';
import { DeviceOrientationControls } from './DeviceOrientationControls.js';
/**
* Convert a quaternion to an angle
*
* Taken from https://stackoverflow.com/a/35448946
* Thanks P. Ellul
*/
function Quat2Angle(x, y, z, w) {
const test = x * y + z * w;
// singularity at north pole
if (test > 0.499) {
const yaw = 2 * Math.atan2(x, w);
const pitch = Math.PI / 2;
const roll = 0;
return new THREE.Vector3(pitch, roll, yaw);
}
// singularity at south pole
if (test < -0.499) {
const yaw = -2 * Math.atan2(x, w);
const pitch = -Math.PI / 2;
const roll = 0;
return new THREE.Vector3(pitch, roll, yaw);
}
const sqx = x * x;
const sqy = y * y;
const sqz = z * z;
const yaw = Math.atan2(2 * y * w - 2 * x * z, 1 - 2 * sqy - 2 * sqz);
const pitch = Math.asin(2 * test);
const roll = Math.atan2(2 * x * w - 2 * y * z, 1 - 2 * sqx - 2 * sqz);
return new THREE.Vector3(pitch, roll, yaw);
}
class OrbitOrientationControls {
constructor(options) {
this.object = options.camera;
this.domElement = options.canvas;
this.orbit = new OrbitControls(this.object, this.domElement);
this.speed = 0.5;
this.orbit.target.set(0, 1, -1);
this.orbit.enableZoom = true;
this.orbit.enablePan = false;
this.orbit.rotateSpeed = -this.speed;
// if orientation is supported
if (options.orientation) {
this.orientation = new DeviceOrientationControls(this.object);
}
// if projection is not full view
// limit the rotation angle in order to not display back half view
if (options.halfView) {
this.orbit.minAzimuthAngle = -Math.PI / 4;
this.orbit.maxAzimuthAngle = Math.PI / 4;
}
}
update() {
// orientation updates the camera using quaternions and
// orbit updates the camera using angles. They are incompatible
// and one update overrides the other. So before
// orbit overrides orientation we convert our quaternion changes to
// an angle change. Then save the angle into orbit so that
// it will take those into account when it updates the camera and overrides
// our changes
if (this.orientation) {
this.orientation.update();
const quat = this.orientation.object.quaternion;
const currentAngle = Quat2Angle(quat.x, quat.y, quat.z, quat.w);
// we also have to store the last angle since quaternions are b
if (typeof this.lastAngle_ === 'undefined') {
this.lastAngle_ = currentAngle;
}
this.orbit.rotateLeft((this.lastAngle_.z - currentAngle.z) * (1 + this.speed));
this.orbit.rotateUp((this.lastAngle_.y - currentAngle.y) * (1 + this.speed));
this.lastAngle_ = currentAngle;
}
this.orbit.update();
}
dispose() {
this.orbit.dispose();
if (this.orientation) {
this.orientation.dispose();
}
}
enable() {
this.orbit.enabled = true;
if (this.orientation)
this.orientation.enabled = true;
}
disable() {
this.orbit.enabled = false;
if (this.orientation)
this.orientation.enabled = false;
}
}
export default OrbitOrientationControls;
.video-js .vjs-big-vr-play-button {
width: 100px;
height: 100px;
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='360' height='360' viewBox='0 0 360 360'%3E%3Cpath fill='%23FFF' d='M334.883 275.78l-6.374-36.198-6.375-36.2-28.16 23.62-28.164 23.62 25.837 9.41C266.247 296.544 224 320.5 176.25 320.5c-77.47 0-140.5-63.03-140.5-140.5 0-77.472 63.03-140.5 140.5-140.5 53.428 0 99.98 29.978 123.733 73.993l13.304-6.923C287.025 57.76 235.45 24.5 176.25 24.5c-85.743 0-155.5 69.757-155.5 155.5 0 85.742 69.757 155.5 155.5 155.5 54.253 0 102.09-27.94 129.922-70.177l28.71 10.457z'/%3E%3Cpath fill='%23FFF' d='M314.492 175.167c-12.98 0-23.54-10.56-23.54-23.54s10.56-23.54 23.54-23.54c12.98 0 23.54 10.56 23.54 23.54s-10.56 23.54-23.54 23.54zm0-38.08c-8.018 0-14.54 6.522-14.54 14.54s6.522 14.54 14.54 14.54c8.017 0 14.54-6.522 14.54-14.54s-6.523-14.54-14.54-14.54z'/%3E%3Cg fill='%23FFF'%3E%3Cpath d='M88.76 173.102h9.395c4.74-.042 8.495-1.27 11.268-3.682 2.77-2.412 4.157-5.903 4.157-10.474 0-4.4-1.153-7.817-3.46-10.25-2.307-2.434-5.83-3.65-10.568-3.65-4.147 0-7.554 1.195-10.22 3.585-2.666 2.392-4 5.514-4 9.364H69.908c0-4.74 1.26-9.055 3.776-12.95 2.518-3.892 6.03-6.928 10.537-9.108 4.508-2.18 9.554-3.27 15.14-3.27 9.225 0 16.472 2.318 21.74 6.952 5.27 4.634 7.903 11.077 7.903 19.33 0 4.147-1.323 8.05-3.967 11.71-2.646 3.66-6.062 6.422-10.252 8.284 5.078 1.736 8.94 4.465 11.584 8.19s3.968 8.166 3.968 13.33c0 8.294-2.847 14.895-8.538 19.804s-13.17 7.363-22.438 7.363c-8.887 0-16.166-2.37-21.836-7.11-5.67-4.74-8.506-11.045-8.506-18.916h15.425c0 4.062 1.365 7.363 4.094 9.902 2.73 2.54 6.4 3.81 11.014 3.81 4.782 0 8.55-1.27 11.3-3.81s4.126-6.22 4.126-11.045c0-4.865-1.44-8.61-4.316-11.235-2.878-2.623-7.152-3.936-12.822-3.936H88.76V173.1zM187.598 133.493v12.76h-1.904c-8.633.126-15.53 2.497-20.693 7.108-5.162 4.614-8.23 11.152-9.203 19.615 4.95-5.205 11.277-7.808 18.98-7.808 8.166 0 14.608 2.878 19.328 8.633 4.718 5.755 7.077 13.182 7.077 22.28 0 9.395-2.76 17.002-8.284 22.82-5.52 5.818-12.77 8.73-21.74 8.73-9.226 0-16.705-3.407-22.44-10.222-5.733-6.812-8.6-15.742-8.6-26.787v-5.267c0-16.208 3.945-28.903 11.84-38.086 7.89-9.182 19.242-13.774 34.054-13.774h1.586zM171.03 177.61c-3.386 0-6.485.95-9.3 2.855-2.814 1.904-4.877 4.443-6.188 7.617v4.697c0 6.854 1.438 12.304 4.316 16.345 2.877 4.04 6.602 6.062 11.172 6.062s8.188-1.715 10.854-5.143 4-7.934 4-13.52-1.355-10.135-4.063-13.648c-2.708-3.51-6.304-5.267-10.79-5.267zM271.136 187.447c0 13.29-2.486 23.307-7.46 30.057s-12.535 10.125-22.69 10.125c-9.988 0-17.51-3.292-22.566-9.872-5.058-6.58-7.65-16.323-7.776-29.23V172.53c0-13.287 2.485-23.252 7.458-29.896 4.973-6.643 12.558-9.966 22.757-9.966 10.112 0 17.655 3.237 22.63 9.712 4.97 6.475 7.52 16.166 7.647 29.072v15.995zm-15.425-17.265c0-8.674-1.185-15.033-3.554-19.075-2.37-4.04-6.137-6.062-11.3-6.062-5.035 0-8.738 1.915-11.107 5.745-2.37 3.83-3.62 9.807-3.746 17.932v20.948c0 8.633 1.206 15.064 3.618 19.297s6.2 6.348 11.362 6.348c4.95 0 8.61-1.957 10.98-5.87 2.37-3.915 3.62-10.04 3.746-18.378v-20.885z'/%3E%3C/g%3E%3C/svg%3E");
background-size: contain;
background-color: rgba(0, 0, 0, 0.5)
}
.video-js .vjs-big-vr-play-button .vjs-icon-placeholder {
display: none
}
:hover.video-js .vjs-big-vr-play-button {
-webkit-transition: border-color 0.4s, outline 0.4s, background-color 0.4s;
-moz-transition: border-color 0.4s, outline 0.4s, background-color 0.4s;
-ms-transition: border-color 0.4s, outline 0.4s, background-color 0.4s;
-o-transition: border-color 0.4s, outline 0.4s, background-color 0.4s;
transition: border-color 0.4s, outline 0.4s, background-color 0.4s
}
.video-js .vjs-big-vr-play-button::before {
content: ''
}
.video-js canvas {
cursor: move
}
.video-js .vjs-button-vr .vjs-icon-placeholder {
height: 30px;
width: 30px;
display: inline-block;
background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjI0cHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI0ZGRkZGRiI+CiAgICA8cGF0aCBkPSJNMjAuNzQgNkgzLjIxQzIuNTUgNiAyIDYuNTcgMiA3LjI4djEwLjQ0YzAgLjcuNTUgMS4yOCAxLjIzIDEuMjhoNC43OWMuNTIgMCAuOTYtLjMzIDEuMTQtLjc5bDEuNC0zLjQ4Yy4yMy0uNTkuNzktMS4wMSAxLjQ0LTEuMDFzMS4yMS40MiAxLjQ1IDEuMDFsMS4zOSAzLjQ4Yy4xOS40Ni42My43OSAxLjExLjc5aDQuNzljLjcxIDAgMS4yNi0uNTcgMS4yNi0xLjI4VjcuMjhjMC0uNy0uNTUtMS4yOC0xLjI2LTEuMjh6TTcuNSAxNC42MmMtMS4xNyAwLTIuMTMtLjk1LTIuMTMtMi4xMiAwLTEuMTcuOTYtMi4xMyAyLjEzLTIuMTMgMS4xOCAwIDIuMTIuOTYgMi4xMiAyLjEzcy0uOTUgMi4xMi0yLjEyIDIuMTJ6bTkgMGMtMS4xNyAwLTIuMTMtLjk1LTIuMTMtMi4xMiAwLTEuMTcuOTYtMi4xMyAyLjEzLTIuMTNzMi4xMi45NiAyLjEyIDIuMTMtLjk1IDIuMTItMi4xMiAyLjEyeiIvPgogICAgPHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgyNHYyNEgwVjB6Ii8+Cjwvc3ZnPgo=) no-repeat left center
}
\ No newline at end of file
This diff is collapsed.
import document from 'global/document';
import QUnit from 'qunit';
import sinon from 'sinon';
import videojs from 'video.js';
import plugin from '../src/plugin';
const Player = videojs.getComponent('Player');
QUnit.test('the environment is sane', function(assert) {
assert.strictEqual(typeof Array.isArray, 'function', 'es5 exists');
assert.strictEqual(typeof sinon, 'object', 'sinon exists');
assert.strictEqual(typeof videojs, 'function', 'videojs exists');
assert.strictEqual(typeof plugin, 'function', 'plugin is a function');
});
QUnit.module('videojs-xr', {
beforeEach() {
// Mock the environment's timers because certain things - particularly
// player readiness - are asynchronous in video.js 5. This MUST come
// before any player is created; otherwise, timers could get created
// with the actual timer methods!
this.clock = sinon.useFakeTimers();
this.fixture = document.getElementById('qunit-fixture');
this.video = document.createElement('video');
this.fixture.appendChild(this.video);
this.player = videojs(this.video);
},
afterEach() {
this.player.dispose();
this.clock.restore();
}
});
QUnit.test('registers itself with video.js', function(assert) {
assert.expect(2);
assert.strictEqual(
typeof Player.prototype.xr,
'function',
'videojs-xr plugin was registered'
);
this.player.xr();
// Tick the clock forward enough to trigger the player to be "ready".
this.clock.tick(1);
assert.ok(
this.player.hasClass('vjs-xr'),
'the plugin adds a class to the player'
);
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment