add vr player
This commit is contained in:
parent
1b26562123
commit
7d2d3973bd
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
.DS_Store
|
||||
vr/node_modules
|
||||
vr//dist
|
||||
|
||||
vr/tests/e2e/videos/
|
||||
vr/tests/e2e/screenshots/
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
BIN
recoder/2025-02-08 00-24-25.mp4
Normal file
BIN
recoder/2025-02-08 00-24-25.mp4
Normal file
Binary file not shown.
BIN
test_data/08-26-17.mp4
Normal file
BIN
test_data/08-26-17.mp4
Normal file
Binary file not shown.
3
vr/.browserslistrc
Normal file
3
vr/.browserslistrc
Normal file
@ -0,0 +1,3 @@
|
||||
> 1%
|
||||
last 2 versions
|
||||
not dead
|
5
vr/.editorconfig
Normal file
5
vr/.editorconfig
Normal file
@ -0,0 +1,5 @@
|
||||
[*.{js,jsx,ts,tsx,vue}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
28
vr/.eslintrc.js
Normal file
28
vr/.eslintrc.js
Normal file
@ -0,0 +1,28 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true
|
||||
},
|
||||
extends: [
|
||||
'plugin:vue/essential',
|
||||
'@vue/standard'
|
||||
],
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint'
|
||||
},
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: [
|
||||
'**/__tests__/*.{j,t}s?(x)',
|
||||
'**/tests/unit/**/*.spec.{j,t}s?(x)'
|
||||
],
|
||||
env: {
|
||||
jest: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
24
vr/.gitignore
vendored
Normal file
24
vr/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
/tests/e2e/videos/
|
||||
/tests/e2e/screenshots/
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
36
vr/README.md
Normal file
36
vr/README.md
Normal file
@ -0,0 +1,36 @@
|
||||
# vue-vr
|
||||
|
||||
基于threejs,html5,hlsjs,flvjs编写的全景播放器,播放普通视频,hls及flv直播流
|
||||
|
||||
## Project setup
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Run your unit tests
|
||||
```
|
||||
npm run test:unit
|
||||
```
|
||||
|
||||
### Run your end-to-end tests
|
||||
```
|
||||
npm run test:e2e
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
45
vr/aisettings
Normal file
45
vr/aisettings
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"model": {
|
||||
"provider": "anthropic",
|
||||
"name": "claude-3-sonnet",
|
||||
"temperature": 0.7,
|
||||
"contextLength": 200000,
|
||||
"maxTokens": 4096
|
||||
},
|
||||
|
||||
"behavior": {
|
||||
"role": "Expert software developer and technical consultant",
|
||||
"expertise": [
|
||||
"Video player development",
|
||||
"WebGL and 3D graphics",
|
||||
"JavaScript/TypeScript",
|
||||
"Web development",
|
||||
"Accessibility features",
|
||||
"Media streaming"
|
||||
],
|
||||
"communication": {
|
||||
"style": "Professional and technical",
|
||||
"format": "Clear explanations with code examples",
|
||||
"codeStyle": {
|
||||
"language": "JavaScript",
|
||||
"formatting": "Standard JS",
|
||||
"comments": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"capabilities": {
|
||||
"codeAnalysis": true,
|
||||
"debugging": true,
|
||||
"refactoring": true,
|
||||
"bestPractices": true,
|
||||
"documentation": true
|
||||
},
|
||||
|
||||
"preferences": {
|
||||
"outputFormat": "markdown",
|
||||
"codeHighlighting": true,
|
||||
"includeExplanations": true,
|
||||
"showLineNumbers": true
|
||||
}
|
||||
}
|
11
vr/babel.config.js
Normal file
11
vr/babel.config.js
Normal file
@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
],
|
||||
compact: true,
|
||||
// 增加 videojs-vr.js 的特殊处理
|
||||
overrides: [{
|
||||
test: /videojs-vr\.js$/,
|
||||
compact: false
|
||||
}]
|
||||
}
|
3
vr/cypress.json
Normal file
3
vr/cypress.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"pluginsFile": "tests/e2e/plugins/index.js"
|
||||
}
|
0
vr/debug.log
Normal file
0
vr/debug.log
Normal file
3
vr/jest.config.js
Normal file
3
vr/jest.config.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
preset: '@vue/cli-plugin-unit-jest'
|
||||
}
|
26191
vr/package-lock.json
generated
Normal file
26191
vr/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
47
vr/package.json
Normal file
47
vr/package.json
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "vr",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"test:unit": "vue-cli-service test:unit",
|
||||
"test:e2e": "vue-cli-service test:e2e",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.12.0",
|
||||
"deasync": "^0.1.30",
|
||||
"flv.js": "^1.5.0",
|
||||
"hls.js": "^0.13.2",
|
||||
"three": "^0.116.1",
|
||||
"three-orbit-controls": "^82.1.0",
|
||||
"videojs-flash": "^2.2.1",
|
||||
"videojs-panorama": "^0.1.7",
|
||||
"videojs-vr": "^1.7.1",
|
||||
"vue": "^2.6.12",
|
||||
"vue-router": "^3.5.1",
|
||||
"vuex": "^3.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^4.3.1",
|
||||
"@vue/cli-plugin-e2e-cypress": "^4.3.1",
|
||||
"@vue/cli-plugin-eslint": "^4.3.1",
|
||||
"@vue/cli-plugin-router": "^4.3.1",
|
||||
"@vue/cli-plugin-unit-jest": "^4.3.1",
|
||||
"@vue/cli-plugin-vuex": "^4.3.1",
|
||||
"@vue/cli-service": "^4.3.1",
|
||||
"@vue/eslint-config-standard": "^5.1.2",
|
||||
"@vue/test-utils": "^1.0.0-beta.31",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.3.1",
|
||||
"eslint-plugin-standard": "^4.1.0",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"sass": "^1.32.13",
|
||||
"sass-loader": "^10.1.1",
|
||||
"vue-template-compiler": "^2.6.12"
|
||||
}
|
||||
}
|
BIN
vr/public/favicon.ico
Normal file
BIN
vr/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
19
vr/public/index.html
Normal file
19
vr/public/index.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
<link href="https://vjs.zencdn.net/7.7.6/video-js.css" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
<!-- <script src="https://threejs.org/build/three.js"></script> -->
|
||||
</body>
|
||||
</html>
|
14
vr/src/App.vue
Normal file
14
vr/src/App.vue
Normal file
@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import url('http://at.alicdn.com/t/font_1857388_u76j431l9gp.css');
|
||||
@import "./assets/css/reset.scss";
|
||||
#app{
|
||||
height: 100%;
|
||||
background: rgb(75,75,75);
|
||||
}
|
||||
</style>
|
465
vr/src/assets/css/reset.scss
Normal file
465
vr/src/assets/css/reset.scss
Normal file
@ -0,0 +1,465 @@
|
||||
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in
|
||||
* IE on Windows Phone and in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
line-height: 1.15; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers (opinionated).
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
footer,
|
||||
header,
|
||||
nav,
|
||||
section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
* 1. Add the correct display in IE.
|
||||
*/
|
||||
|
||||
figcaption,
|
||||
figure,
|
||||
main { /* 1 */
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct margin in IE 8.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Remove the gray background on active links in IE 10.
|
||||
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent; /* 1 */
|
||||
-webkit-text-decoration-skip: objects; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Chrome 57- and Firefox 39-.
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none; /* 1 */
|
||||
text-decoration: underline; /* 2 */
|
||||
text-decoration: underline dotted; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font style in Android 4.3-.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct background and color in IE 9-.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background-color: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
audio,
|
||||
video {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in iOS 4-7.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10-.
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the overflow in IE.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers (opinionated).
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: sans-serif; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
button,
|
||||
input { /* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
|
||||
* controls in Android 4.
|
||||
* 2. Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
html [type="button"], /* 1 */
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
box-sizing: border-box; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
display: table; /* 1 */
|
||||
max-width: 100%; /* 1 */
|
||||
padding: 0; /* 3 */
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct display in IE 9-.
|
||||
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10-.
|
||||
* 2. Remove the padding in IE 10-.
|
||||
*/
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-cancel-button,
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in IE 9-.
|
||||
* 1. Add the correct display in Edge, IE, and Firefox.
|
||||
*/
|
||||
|
||||
details, /* 1 */
|
||||
menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* Scripting
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
canvas {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hidden
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10-.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置button及input预置样式
|
||||
*/
|
||||
|
||||
button,
|
||||
input { /* 1 */
|
||||
all: unset;
|
||||
}
|
||||
button{
|
||||
text-align:center;
|
||||
&:hover{
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
34
vr/src/assets/css/videojs-vr.css
Normal file
34
vr/src/assets/css/videojs-vr.css
Normal file
@ -0,0 +1,34 @@
|
||||
.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
|
||||
}
|
BIN
vr/src/assets/img/logo.png
Normal file
BIN
vr/src/assets/img/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
8
vr/src/assets/js/flv.js
Normal file
8
vr/src/assets/js/flv.js
Normal file
File diff suppressed because one or more lines are too long
8
vr/src/assets/js/video-flash.js
Normal file
8
vr/src/assets/js/video-flash.js
Normal file
File diff suppressed because one or more lines are too long
56374
vr/src/assets/js/video.js
Normal file
56374
vr/src/assets/js/video.js
Normal file
File diff suppressed because it is too large
Load Diff
43971
vr/src/assets/js/videojs-vr.js
Normal file
43971
vr/src/assets/js/videojs-vr.js
Normal file
File diff suppressed because one or more lines are too long
851
vr/src/components/VRLive/index.vue
Normal file
851
vr/src/components/VRLive/index.vue
Normal file
@ -0,0 +1,851 @@
|
||||
<template>
|
||||
<div id="videoContainer" class="vr-video">
|
||||
<div class="video-wrapper">
|
||||
<div id="video" @mousemove="ControlVisible()">
|
||||
</div>
|
||||
<div v-if="playVariables.statistics" class="vr-statistics">
|
||||
<p>type:{{playVariables.type || '???'}}</p>
|
||||
<p>status:{{playVariables.status || '???'}}</p>
|
||||
<p>currentTime: {{playVariables.currentTime}}</p>
|
||||
<p>totalTime: {{playVariables.totalTime}}</p>
|
||||
<span v-if="deviceOrientationData.isSupported">
|
||||
<p>
|
||||
陀螺仪数据:
|
||||
</p>
|
||||
<p>
|
||||
alpha(z轴):{{deviceOrientationData.alpha||'手机查看参数'}}
|
||||
</p>
|
||||
<p>
|
||||
beta(x轴):{{deviceOrientationData.beta||'手机查看参数'}}
|
||||
</p>
|
||||
<p>
|
||||
gamma(y轴):{{deviceOrientationData.gamma||'手机查看参数'}}
|
||||
</p></span>
|
||||
|
||||
</div>
|
||||
<div class="vr-func">
|
||||
<div v-if="playVariables.status == 'pause'&&!playVariables.playClick"
|
||||
@click="player.play();playVariables.playClick=true" class="btns-play">
|
||||
<i class="iconfont icon-icon_play"></i>
|
||||
</div>
|
||||
<div v-else-if="playVariables.status == 'playing'&&!playVariables.playClick" @click="player.pause()"
|
||||
class="btns-pause">
|
||||
<i class="iconfont icon-ai07"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="playVariables.status == 'loading'" class="vr-loading">
|
||||
<div class="border"></div>
|
||||
<div class="slow"></div>
|
||||
<div class="fast"></div>
|
||||
</div>
|
||||
<div class="vr-bar" v-if="playVariables.playClick" id="control">
|
||||
<div class="bg"></div>
|
||||
<div class="btns">
|
||||
<div v-if="playVariables.status === 'playing'" @click="player.pause()" class="btns-pause">
|
||||
<i class="iconfont icon-ai07"></i>
|
||||
</div>
|
||||
<div v-else @click="player.play()" class="btns-play">
|
||||
<i class="iconfont icon-icon_play"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="playVariables.type == 'normal'" class="progress-container">
|
||||
<div @click="jumpTo($event)" class="progress-wrapper">
|
||||
<div class="progress" id="progress-play"></div>
|
||||
</div>
|
||||
<div class="btn-wrapper">
|
||||
<div class="btn" id="progress-btn"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="type">
|
||||
<span class="statu-circle"></span>
|
||||
<span>{{playVariables.type}}</span>
|
||||
</div>
|
||||
<div @click="changeFullscreenStatu()" class="fullscreen">
|
||||
<i class="iconfont icon-quanping"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vr-notice" id="vrNotice" v-html="playVariables.notice">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as THREE from 'three'
|
||||
import threeOrbitControls from 'three-orbit-controls'
|
||||
import flvjs from 'flv.js'
|
||||
const OrbitControls = threeOrbitControls(THREE)
|
||||
|
||||
export default {
|
||||
name: 'VRLive',
|
||||
props: {
|
||||
option: {
|
||||
default: Object
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
camera: null,
|
||||
scene: null,
|
||||
renderer: null,
|
||||
mesh: null,
|
||||
video: null,
|
||||
controls: null,
|
||||
deviceOrientationData: {},
|
||||
hls: null,
|
||||
player: {},
|
||||
videoContainer: '',
|
||||
playVariables: {
|
||||
/*
|
||||
视频类型,默认Normal
|
||||
Normal
|
||||
HLS
|
||||
FLV
|
||||
*/
|
||||
type: 'Normal',
|
||||
/*
|
||||
播放状态,与视频播放状态对应
|
||||
loading:加载中,
|
||||
playing:视频播放中,包括视频中间加载后继续播放
|
||||
pause:暂停或用户未点开始按钮
|
||||
*/
|
||||
status: 'pause',
|
||||
playClick: false,
|
||||
// 控件显示状态
|
||||
currentTime: 0,
|
||||
progress: 0,
|
||||
// fullscreenStatu: false,
|
||||
notice: '',
|
||||
statistics: false,
|
||||
error: {
|
||||
code: 0,
|
||||
msg: ''
|
||||
}
|
||||
}
|
||||
// cameraVariables: {
|
||||
// isUserInteracting: false,
|
||||
// lon: 0,
|
||||
// lat: 0,
|
||||
// phi: 0,
|
||||
// theta: 0,
|
||||
// distance: 1,
|
||||
// onPointerDownPointerX: 0,
|
||||
// onPointerDownPointerY: 0,
|
||||
// onPointerDownLon: 0,
|
||||
// onPointerDownLat: 0,
|
||||
// sensitivity: 0.1
|
||||
// }
|
||||
}
|
||||
},
|
||||
// computed: {
|
||||
// fullScreenStatu () {
|
||||
// return document.mozFullScreen || document.webkitIsFullScreen
|
||||
// }
|
||||
// },
|
||||
// watch: {
|
||||
// playVariables (val) {
|
||||
|
||||
// },
|
||||
// // fullScreenStatu (val) {
|
||||
// // console.log(val)
|
||||
// // if (val) {
|
||||
// // this.videoContainer.classList.add('fullScreen-mobile')
|
||||
// // } else {
|
||||
// // this.videoContainer.classList.remove('fullScreen-mobile')
|
||||
// // }
|
||||
// // }
|
||||
// },
|
||||
mounted () {
|
||||
if (this.check()) {
|
||||
this.playVariables.statistics = this.option.statistics
|
||||
this.playVariables.type = this.option.source.type
|
||||
this.videoContainer = document.getElementById('videoContainer')
|
||||
this.init()
|
||||
}
|
||||
// 检查浏览器音频支持
|
||||
if (!flvjs.isSupported()) {
|
||||
console.error('Browser does not support flv.js')
|
||||
return
|
||||
}
|
||||
|
||||
// 检查浏览器音频编解码器支持
|
||||
const audioTest = document.createElement('audio')
|
||||
if (!audioTest.canPlayType('audio/aac')) {
|
||||
console.warn('Browser might not support AAC audio codec')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
check () {
|
||||
if (!this.option.source) {
|
||||
console.log(new Error('无播放源'))
|
||||
} else if (!this.option.source.type) {
|
||||
console.log(new Error('播放源type不能为空'))
|
||||
} else if (!this.option.source.url) {
|
||||
console.log(new Error('播放源url不能为空'))
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
},
|
||||
init () {
|
||||
const container = document.getElementById('video')
|
||||
this.initScene()
|
||||
this.initCamera(container)
|
||||
this.initRenderer(container)
|
||||
this.initContent()
|
||||
this.initControls(container)
|
||||
this.render()
|
||||
// this.addMouseEvent(container)
|
||||
window.addEventListener('deviceorientation', function (event) {
|
||||
this.deviceOrientationData.isSupported = true
|
||||
this.deviceOrientationData = event
|
||||
}.bind(this), false)
|
||||
window.addEventListener('resize', function () {
|
||||
this.onWindowResize(container)
|
||||
}.bind(this))
|
||||
},
|
||||
initScene () {
|
||||
this.scene = new THREE.Scene()
|
||||
},
|
||||
initCamera (el) {
|
||||
this.camera = new THREE.PerspectiveCamera(75, el.clientWidth / el.clientHeight, 1, 1100)
|
||||
this.camera.position.set(1, 0, 0)
|
||||
// this.camera.target = new THREE.Vector3(0, 0, 0)
|
||||
},
|
||||
initRenderer (el) {
|
||||
this.renderer = new THREE.WebGLRenderer()
|
||||
this.renderer.setSize(el.offsetWidth, el.offsetHeight)
|
||||
el.appendChild(this.renderer.domElement)
|
||||
},
|
||||
initVideo () {
|
||||
this.video = document.createElement('video')
|
||||
this.video.preload = 'auto'
|
||||
this.video.muted = false
|
||||
this.video.volume = 1.0
|
||||
this.video.crossOrigin = 'anonymous'
|
||||
// 立即设置 player 为 video 元素
|
||||
this.player = this.video
|
||||
|
||||
this.video.addEventListener('waiting', function (event) {
|
||||
this.playVariables.status = 'loading'
|
||||
}.bind(this))
|
||||
this.video.addEventListener('playing', function (event) {
|
||||
this.playVariables.status = 'playing'
|
||||
}.bind(this))
|
||||
this.video.addEventListener('pause', function (event) {
|
||||
this.playVariables.status = 'pause'
|
||||
}.bind(this))
|
||||
this.video.addEventListener('canplay', function (event) {
|
||||
this.playVariables.duration = this.player.duration
|
||||
if (this.playVariables.status === 'loading') {
|
||||
this.playVariables.status = 'playing'
|
||||
}
|
||||
}.bind(this))
|
||||
|
||||
// 判断视频类型
|
||||
switch (this.option.source.type) {
|
||||
case 'flv':
|
||||
this.getFLV()
|
||||
break
|
||||
case 'hls':
|
||||
this.getHLS(this.option.source.url, this.video)
|
||||
break
|
||||
case 'normal':
|
||||
this.getNormalVideo(this.option.source.url, this.video)
|
||||
break
|
||||
default:
|
||||
this.playVariables.error.code = 1
|
||||
this.playVariables.error.msg = '未知的视频类型'
|
||||
break
|
||||
}
|
||||
},
|
||||
initContent () {
|
||||
this.initVideo()
|
||||
var geometry = new THREE.SphereBufferGeometry(300, 90, 90)
|
||||
geometry.scale(-1, 1, 1)
|
||||
var texture = new THREE.VideoTexture(this.video)
|
||||
texture.minFilter = THREE.LinearFilter
|
||||
texture.format = THREE.RGBFormat
|
||||
var material = new THREE.MeshBasicMaterial({
|
||||
map: texture
|
||||
})
|
||||
this.mesh = new THREE.Mesh(geometry, material)
|
||||
this.mesh.position.set(0, 0, 0)
|
||||
this.scene.add(this.mesh)
|
||||
},
|
||||
initControls (el) {
|
||||
this.controls = new OrbitControls(this.camera, el)
|
||||
// this.controls.target = new THREE.Vector3(0, Math.PI, 0)
|
||||
this.controls.rotateSpeed = 0.05
|
||||
this.controls.enableDamping = true
|
||||
this.controls.dampingFactor = 0.05
|
||||
},
|
||||
render () {
|
||||
requestAnimationFrame(this.render)
|
||||
this.controls.update()
|
||||
// this.cameraUpdate()
|
||||
this.renderer.render(this.scene, this.camera)
|
||||
},
|
||||
getNormalVideo (sourceURL, el) {
|
||||
const source = document.createElement('source')
|
||||
source.src = sourceURL
|
||||
// source.type = 'video/mp4'
|
||||
el.appendChild(source)
|
||||
this.player = el
|
||||
},
|
||||
getHLS (sourceURL, el) {
|
||||
const Hls = require('hls.js')
|
||||
if (Hls.isSupported()) {
|
||||
this.hls = new Hls()
|
||||
this.hls.loadSource(sourceURL)
|
||||
this.hls.attachMedia(el)
|
||||
this.hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||
console.log('加载成功')
|
||||
})
|
||||
this.hls.on(Hls.Events.ERROR, (event, data) => {
|
||||
throw new Error(data.response.code + ' ' + data.response.text)
|
||||
})
|
||||
}
|
||||
this.player = el
|
||||
},
|
||||
// abandoned 对接rtmp流
|
||||
// 非原生video标签。
|
||||
// confuse object?如何作为纹理渲染?
|
||||
// getRTMP (sourceURL, el) {
|
||||
// el.id = 'rtmpVideo'
|
||||
// console.log(el)
|
||||
// this.player = videojs(el, {
|
||||
// sources: [{
|
||||
// src: sourceURL
|
||||
// }]
|
||||
// })
|
||||
// this.player.on('ready', function () {
|
||||
// console.log('准备就绪')
|
||||
// })
|
||||
// },
|
||||
getFLV () {
|
||||
if (flvjs.isSupported()) {
|
||||
const flvPlayer = flvjs.createPlayer({
|
||||
type: 'flv',
|
||||
hasAudio: true,
|
||||
hasVideo: true,
|
||||
url: this.option.source.url
|
||||
})
|
||||
|
||||
// 添加事件监听器
|
||||
flvPlayer.on(flvjs.Events.ERROR, (errorType, errorDetail) => {
|
||||
console.error('FLV Player Error:', errorType, errorDetail)
|
||||
})
|
||||
|
||||
flvPlayer.on(flvjs.Events.MEDIA_INFO, (mediaInfo) => {
|
||||
console.log('FLV Media Info:', mediaInfo)
|
||||
})
|
||||
|
||||
flvPlayer.attachMediaElement(this.video)
|
||||
flvPlayer.load()
|
||||
return flvPlayer
|
||||
}
|
||||
},
|
||||
onWindowResize (el) {
|
||||
this.camera.aspect = el.clientWidth / el.clientHeight
|
||||
this.camera.updateProjectionMatrix()
|
||||
this.renderer.setSize(el.clientWidth, el.clientHeight)
|
||||
},
|
||||
// jumpTo ($e) {
|
||||
// console.log(e)
|
||||
// }
|
||||
async changeFullscreenStatu () {
|
||||
if (this.playVariables.fullscreenStatu) {
|
||||
this.exitFullscreen()
|
||||
// screen.orientation.unlock()
|
||||
// this.videoContainer.classList.remove('full-screen-mobile')
|
||||
} else {
|
||||
this.fullScreen()
|
||||
if (/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
|
||||
this.showNotice('为了更好的观看体验<br>请关闭屏幕锁定横屏观看该视频')
|
||||
}
|
||||
// 只在谷歌浏览器下生效
|
||||
// screen.orientation.lock('landscape-primary')
|
||||
// this.videoContainer.classList.add('full-screen-mobile')
|
||||
// screen.lockOrientationUniversal = screen.lockOrientation || screen.mozLockOrientation || screen.msLockOrientation
|
||||
// new ScreenOrientation().lock('landscape-secondary')
|
||||
// console.log(screen)
|
||||
// screen.msLockOrientation.lock('landscape-primary')
|
||||
}
|
||||
this.playVariables.fullscreenStatu = !this.playVariables.fullscreenStatu
|
||||
},
|
||||
fullScreen () {
|
||||
const el = this.videoContainer
|
||||
if (el.requestFullscreen) {
|
||||
el.requestFullscreen()
|
||||
} else if (el.mozRequestFullScreen) {
|
||||
el.mozRequestFullScreen()
|
||||
} else if (el.webkitRequestFullScreen) {
|
||||
el.webkitRequestFullScreen()
|
||||
}
|
||||
},
|
||||
exitFullscreen () {
|
||||
const el = document
|
||||
el.exitFullscreen()
|
||||
if (el.exitFullscreen) {
|
||||
el.exitFullscreen()
|
||||
} else if (el.mozCancelFullScreen) {
|
||||
el.mozCancelFullScreen()
|
||||
} else if (el.webkitCancelFullScreen) {
|
||||
el.webkitCancelFullScreen()
|
||||
}
|
||||
},
|
||||
showNotice (msg) {
|
||||
this.playVariables.notice = msg
|
||||
const notice = document.getElementById('vrNotice')
|
||||
if (notice.classList.contains('vr-notice-show')) {
|
||||
notice.classList.remove('vr-notice-show')
|
||||
setTimeout(() => {
|
||||
notice.classList.add('vr-notice-show')
|
||||
}, 0)
|
||||
} else {
|
||||
notice.classList.add('vr-notice-show')
|
||||
}
|
||||
},
|
||||
ControlVisible () {
|
||||
const control = document.getElementById('control')
|
||||
if (this.playVariables.status === 'playing') {
|
||||
if (control.classList.contains('control-hidden')) {
|
||||
control.classList.remove('control-hidden')
|
||||
setTimeout(() => {
|
||||
control.classList.add('control-hidden')
|
||||
}, 0)
|
||||
} else {
|
||||
control.classList.add('control-hidden')
|
||||
}
|
||||
}
|
||||
}
|
||||
// 有更好的选择 three轨道控制器
|
||||
// abandoned 对接鼠标移动事件,剩余惯性尚需对接,使滑动体验更加流畅
|
||||
// addMouseEvent (el) {
|
||||
// el.addEventListener('mousedown', onDocumentMouseDown.bind(this), false)
|
||||
// el.addEventListener('mousemove', onDocumentMouseMove.bind(this), false)
|
||||
// el.addEventListener('mouseup', onDocumentMouseUp.bind(this), false)
|
||||
// el.addEventListener('touchstart', onDocumentTouchStart.bind(this), false)
|
||||
// el.addEventListener('touchmove', onDocumentTouchMove.bind(this), false)
|
||||
// el.addEventListener('touchend', onDocumentTouchEnd.bind(this), false)
|
||||
|
||||
// function onDocumentMouseDown (event) {
|
||||
// event.preventDefault()
|
||||
|
||||
// this.cameraVariables.isUserInteracting = true
|
||||
|
||||
// this.cameraVariables.onPointerDownPointerX = event.clientX
|
||||
// this.cameraVariables.onPointerDownPointerY = event.clientY
|
||||
|
||||
// this.cameraVariables.onPointerDownLon = this.cameraVariables.lon
|
||||
// this.cameraVariables.onPointerDownLat = this.cameraVariables.lat
|
||||
// }
|
||||
|
||||
// function onDocumentMouseMove (event) {
|
||||
// if (this.cameraVariables.isUserInteracting === true) {
|
||||
// this.cameraVariables.lon =
|
||||
// (this.cameraVariables.onPointerDownPointerX - event.clientX) * this.cameraVariables.sensitivity +
|
||||
// this.cameraVariables.onPointerDownLon
|
||||
// this.cameraVariables.lat =
|
||||
// (event.clientY - this.cameraVariables.onPointerDownPointerY) * this.cameraVariables.sensitivity +
|
||||
// this.cameraVariables.onPointerDownLat
|
||||
// console.log(this.cameraVariables.lat)
|
||||
// }
|
||||
// }
|
||||
|
||||
// function onDocumentMouseUp () {
|
||||
// this.cameraVariables.isUserInteracting = false
|
||||
// }
|
||||
|
||||
// function onDocumentTouchStart (event) {
|
||||
// event.preventDefault()
|
||||
|
||||
// this.cameraVariables.isUserInteracting = true
|
||||
|
||||
// this.cameraVariables.onPointerDownPointerX = event.touches[0].clientX
|
||||
// this.cameraVariables.onPointerDownPointerY = event.touches[0].clientY
|
||||
|
||||
// this.cameraVariables.onPointerDownLon = this.cameraVariables.lon
|
||||
// this.cameraVariables.onPointerDownLat = this.cameraVariables.lat
|
||||
// }
|
||||
|
||||
// function onDocumentTouchMove (event) {
|
||||
// if (this.cameraVariables.isUserInteracting === true) {
|
||||
// this.cameraVariables.lon =
|
||||
// (this.cameraVariables.onPointerDownPointerX - event.touches[0].clientX) * this.cameraVariables
|
||||
// .sensitivity +
|
||||
// this.cameraVariables.onPointerDownLon
|
||||
// this.cameraVariables.lat =
|
||||
// (event.touches[0].clientY - this.cameraVariables.onPointerDownPointerY) * this.cameraVariables
|
||||
// .sensitivity +
|
||||
// this.cameraVariables.onPointerDownLat
|
||||
// }
|
||||
// }
|
||||
|
||||
// function onDocumentTouchEnd () {
|
||||
// this.cameraVariables.isUserInteracting = false
|
||||
// }
|
||||
// // const pre = {
|
||||
// // x: '',
|
||||
// // y: ''
|
||||
// // }
|
||||
// // // const cur = {
|
||||
// // // x: '',
|
||||
// // // y: ''
|
||||
// // // }
|
||||
// // let isDown = false
|
||||
// // const self = this
|
||||
// // el.onmousedown = function (event) {
|
||||
// // isDown = true
|
||||
// // }
|
||||
// // el.onmouseup = function (event) {
|
||||
// // isDown = false
|
||||
// // }
|
||||
// // el.onmousemove = function (event) {
|
||||
// // if (isDown) {
|
||||
// // console.log(event)
|
||||
// // console.log(pre)
|
||||
// // console.log(self.camera)
|
||||
// // if (event.movementY && !event.movementX) {
|
||||
// // self.camera.rotation.x -= event.movementY / 500
|
||||
// // } else if (!event.movementY && event.movementX) {
|
||||
// // self.camera.rotation.y += event.movementX / 500
|
||||
// // } else {
|
||||
// // pre.x = event.clientX
|
||||
// // }
|
||||
// // pre.y = event.clientY
|
||||
// // }
|
||||
// // }
|
||||
// },
|
||||
// cameraUpdate () {
|
||||
// this.cameraVariables.lat = Math.max(-85, Math.min(85, this.cameraVariables.lat))
|
||||
// this.cameraVariables.phi = THREE.Math.degToRad(90 - this.cameraVariables.lat)
|
||||
// this.cameraVariables.theta = THREE.Math.degToRad(this.cameraVariables.lon)
|
||||
// this.camera.position.x = this.cameraVariables.distance * Math.sin(this.cameraVariables.phi) * Math.cos(this.cameraVariables.theta)
|
||||
// this.camera.position.y = this.cameraVariables.distance * Math.cos(this.cameraVariables.phi)
|
||||
// this.camera.position.z = this.cameraVariables.distance * Math.sin(this.cameraVariables.phi) * Math.sin(this.cameraVariables.theta)
|
||||
// this.camera.lookAt(this.camera.target)
|
||||
// // 为后面的惯性对接
|
||||
// setTimeout(() => {
|
||||
// }, 1000)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.vr-video {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.video-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
// min-height: 300px;
|
||||
}
|
||||
|
||||
#video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
&:hover {
|
||||
.control {
|
||||
display: block;
|
||||
animation: mousehover 3s;
|
||||
animation-delay: 5s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.control-hidden {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
animation: mousehover 2s;
|
||||
animation-delay: 3s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
@keyframes mousehover {
|
||||
100% {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.vr {
|
||||
&-func {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
height: 50px;
|
||||
font-size: 16px;
|
||||
|
||||
.btns-play,
|
||||
.btns-pause {
|
||||
i {
|
||||
font-size: 4em;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
transition: color .3s;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
|
||||
i {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-loading {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
border-radius: 50%;
|
||||
width: 3em;
|
||||
height: 3em;
|
||||
|
||||
.border {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0.45em solid rgba(99, 149, 168, 0.5);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.slow {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-width: 0.45em;
|
||||
border-style: solid;
|
||||
border: 0.45em solid rgba(0, 0, 0, 0);
|
||||
border-top-color: rgb(7, 186, 241);
|
||||
animation: slow 1.5s linear infinite;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.fast {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-width: 0.45em;
|
||||
border-style: solid;
|
||||
border: 0.45em solid rgba(0, 0, 0, 0);
|
||||
border-top-color: rgb(10, 126, 161);
|
||||
animation: fast 0.75s linear infinite;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
@keyframes slow {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fast {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
25% {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
border-top-color: rgb(195, 236, 248);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: rotate(315deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-bar {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 1em 1em;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
background-image: linear-gradient(to top, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0));
|
||||
|
||||
.btns {
|
||||
padding: 0.5em;
|
||||
|
||||
&-play,
|
||||
&-pause {
|
||||
i {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.progress-container {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 1em;
|
||||
|
||||
.progress-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 0.2em;
|
||||
border-radius: 30px;
|
||||
background-color: rgba(150, 150, 150, 1);
|
||||
overflow: hidden;
|
||||
|
||||
.progress {
|
||||
position: absolute;
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
background-color: rgb(22, 175, 236);
|
||||
transition: width .5s;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-wrapper {
|
||||
position: absolute;
|
||||
z-index: 9;
|
||||
left: 1em;
|
||||
width: calc(100% - 2em);
|
||||
|
||||
.btn {
|
||||
margin-left: 0;
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
border-radius: 50%;
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.type {
|
||||
padding: 0 2em;
|
||||
width: 100%;
|
||||
font-size: 0.95em;
|
||||
font-weight: 300;
|
||||
color: white;
|
||||
|
||||
.statu-circle {}
|
||||
}
|
||||
|
||||
.fullscreen {
|
||||
i {
|
||||
font-size: 1.4em;
|
||||
color: white;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-notice {
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
padding: 0.5em 1em;
|
||||
white-space: nowrap;
|
||||
font-size: 1em;
|
||||
color: white;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
border-radius: 0.5em;
|
||||
|
||||
&-show {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
animation: notice 2s;
|
||||
animation-delay: 3s;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
@keyframes notice {
|
||||
100% {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-statistics {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 1em;
|
||||
left: 1em;
|
||||
padding: 0.2em 1em;
|
||||
font-size: 13px;
|
||||
color: white;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
border-radius: 0.2em;
|
||||
}
|
||||
}
|
||||
|
||||
&:fullscreen {
|
||||
.video-wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
// transform-origin: top left;
|
||||
// transform: rotate(90deg) translate(-0vh, -100vw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// .full-screen-mobile {
|
||||
// .video-wrapper {
|
||||
// position: absolute;
|
||||
// z-index: 99;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// width: 100vh;
|
||||
// height: 100vw;
|
||||
// transform-origin: top left;
|
||||
// transform: rotate(90deg) translate(-0vh, -100vw);
|
||||
// }
|
||||
|
||||
// // #video {
|
||||
// // width: 100%;
|
||||
// // height: calc(100vw / 16 * 9);
|
||||
// // }
|
||||
// }
|
||||
</style>
|
10
vr/src/main.js
Normal file
10
vr/src/main.js
Normal file
@ -0,0 +1,10 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
Vue.config.productionTip = false
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
36
vr/src/router/index.js
Normal file
36
vr/src/router/index.js
Normal file
@ -0,0 +1,36 @@
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/vrlive'
|
||||
},
|
||||
{
|
||||
path: '/home',
|
||||
name: 'Home',
|
||||
component: () => import('../views/Home.vue')
|
||||
}, {
|
||||
path: '/live',
|
||||
name: 'Live',
|
||||
component: () => import('../views/Live')
|
||||
}, {
|
||||
path: '/vrlive',
|
||||
name: 'VRLive',
|
||||
component: () => import('../views/VRLive')
|
||||
}, {
|
||||
path: '/test',
|
||||
name: 'Test',
|
||||
component: () => import('../views/Test')
|
||||
}
|
||||
]
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
base: process.env.BASE_URL,
|
||||
routes
|
||||
})
|
||||
|
||||
export default router
|
15
vr/src/store/index.js
Normal file
15
vr/src/store/index.js
Normal file
@ -0,0 +1,15 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
export default new Vuex.Store({
|
||||
state: {
|
||||
},
|
||||
mutations: {
|
||||
},
|
||||
actions: {
|
||||
},
|
||||
modules: {
|
||||
}
|
||||
})
|
0
vr/src/views/Home.vue
Normal file
0
vr/src/views/Home.vue
Normal file
52
vr/src/views/Live/index.vue
Normal file
52
vr/src/views/Live/index.vue
Normal file
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div class="live">
|
||||
<video class="video-js my-video" ref="video"></video>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import videojs from 'video.js'
|
||||
import 'videojs-flash'
|
||||
|
||||
export default {
|
||||
name: 'Live',
|
||||
data () {
|
||||
return {
|
||||
player: null,
|
||||
opt: {
|
||||
techOrder: ['flash', 'html5'],
|
||||
sources: [{
|
||||
withCredentials: false,
|
||||
type: 'rtmp/flv',
|
||||
// rtmp://202.69.69.180:443/webcast/bshdlive-pc
|
||||
// rtmp://live.xshaitt.com/kxh/demo
|
||||
src: 'rtmp://localhost:8000/live/livestream'
|
||||
}, {
|
||||
withCredentials: false,
|
||||
type: 'application/x-mpegURL',
|
||||
// http://ivi.bupt.edu.cn/hls/cctv3hd.m3u8
|
||||
// http://live.xshaitt.com/kxh/demo.m3u8
|
||||
src: 'http://localhost:8079/live/livestream.flv'
|
||||
}],
|
||||
controls: true,
|
||||
poster: 'https://images.pexels.com/photos/3518091/pexels-photo-3518091.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500'
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
console.log(1, this.$refs.video)
|
||||
this.player = videojs(this.$refs.video, this.opt)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.live{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
.video-js{
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
}
|
||||
}
|
||||
</style>
|
100
vr/src/views/Test/index.vue
Normal file
100
vr/src/views/Test/index.vue
Normal file
@ -0,0 +1,100 @@
|
||||
<template>
|
||||
<div class="vrlive">
|
||||
<video class="video-js my-video" ref="video"></video>
|
||||
<div class="func">
|
||||
<button @click="player.play()">播放</button>
|
||||
<button @click="player.pause()">暂停</button>
|
||||
</div>
|
||||
123
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import videojs from 'video.js'
|
||||
|
||||
import 'videojs-flash'
|
||||
import '@a/js/videojs-vr'
|
||||
|
||||
export default {
|
||||
name: 'VRLive',
|
||||
data () {
|
||||
return {
|
||||
player: null,
|
||||
opt: {
|
||||
techOrder: ['flash', 'html5'],
|
||||
sources: [{
|
||||
withCredentials: false,
|
||||
type: 'rtmp/flv',
|
||||
// rtmp://202.69.69.180:443/webcast/bshdlive-pc
|
||||
// rtmp://live.xshaitt.com/kxh/demo
|
||||
src: 'rtmp://202.69.69.180:443/webcast/bshdlive-pc'
|
||||
}, {
|
||||
withCredentials: false,
|
||||
type: 'application/x-mpegURL',
|
||||
// http://ivi.bupt.edu.cn/hls/cctv3hd.m3u8
|
||||
// http://live.xshaitt.com/kxh/demo.m3u8
|
||||
src: ' http://ivi.bupt.edu.cn/hls/cctv3hd.m3u8'
|
||||
}],
|
||||
controls: true,
|
||||
poster: 'https://images.pexels.com/photos/3518091/pexels-photo-3518091.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500'
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
this.player = videojs(this.$refs.video, this.opt)
|
||||
this.player.vr({ projection: '360' })
|
||||
},
|
||||
getRTMP (sourceURL, el) {
|
||||
el.id = 'rtmpVideo'
|
||||
console.log(el)
|
||||
this.player = videojs(el, {
|
||||
height: '432',
|
||||
sources: [{
|
||||
type: 'rtmp/flv',
|
||||
src: sourceURL
|
||||
}]
|
||||
})
|
||||
this.player.on('ready', function () {
|
||||
console.log('准备就绪')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.vrlive{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
.my-video{
|
||||
margin-top: 40px;
|
||||
width: 800px;
|
||||
height: 600px;
|
||||
}
|
||||
.func{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
width: 800px;
|
||||
button{
|
||||
margin-right: 20px;
|
||||
padding: 10px 15px;
|
||||
font-size: 15px;
|
||||
color: white;
|
||||
background-image: linear-gradient( 135deg, #ABDCFF 10%, #0396FF 100%);
|
||||
border-radius: 5px;
|
||||
transition: all .3s;
|
||||
&:hover{
|
||||
transform: translateY(-2px);
|
||||
background-image: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%);
|
||||
box-shadow: 0 2px 5px #40bad5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
69
vr/src/views/VRLive.vue
Normal file
69
vr/src/views/VRLive.vue
Normal file
@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div class="vr-live">
|
||||
<p>{{opt.source.src}}</p>
|
||||
<div class="container">
|
||||
|
||||
<vr-live :option="opt"></vr-live>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import vrLive from '@c/VRLive'
|
||||
export default {
|
||||
components: {
|
||||
vrLive
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
opt: {
|
||||
statistics: false, // 统计信息
|
||||
source: {
|
||||
/*
|
||||
视频类型
|
||||
normal
|
||||
hls
|
||||
flv
|
||||
*/
|
||||
type: 'flv',
|
||||
/*
|
||||
测试地址
|
||||
https://www.wangwentehappy.tk/assets/video/1.mp4
|
||||
http://playertest.longtailvideo.com/adaptive/bipbop/gear4/prog_index.m3u8
|
||||
http://localhost:9001/live/wwt.flv
|
||||
http://localhost:9001/live/wwt/index.m3u8
|
||||
*/
|
||||
// url: 'https://www.ashenone.tk/public/video/1.mp4'
|
||||
url: 'http://localhost:8079/live/livestream.flv'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.vr-live{
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.container{
|
||||
margin: 80px auto 0 auto;
|
||||
padding: 15px;
|
||||
width: 70vw;
|
||||
height: calc(70vw / 16 * 9);
|
||||
background: rgba(125,125,125,1);
|
||||
border-radius: 10px;
|
||||
}
|
||||
@media screen and (max-width: 768px) {
|
||||
.container{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100vw;
|
||||
height: calc(100vw / 16 * 9);
|
||||
background: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
12
vr/tests/e2e/.eslintrc.js
Normal file
12
vr/tests/e2e/.eslintrc.js
Normal file
@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
'cypress'
|
||||
],
|
||||
env: {
|
||||
mocha: true,
|
||||
'cypress/globals': true
|
||||
},
|
||||
rules: {
|
||||
strict: 'off'
|
||||
}
|
||||
}
|
25
vr/tests/e2e/plugins/index.js
Normal file
25
vr/tests/e2e/plugins/index.js
Normal file
@ -0,0 +1,25 @@
|
||||
/* eslint-disable arrow-body-style */
|
||||
// https://docs.cypress.io/guides/guides/plugins-guide.html
|
||||
|
||||
// if you need a custom webpack configuration you can uncomment the following import
|
||||
// and then use the `file:preprocessor` event
|
||||
// as explained in the cypress docs
|
||||
// https://docs.cypress.io/api/plugins/preprocessors-api.html#Examples
|
||||
|
||||
// /* eslint-disable import/no-extraneous-dependencies, global-require */
|
||||
// const webpack = require('@cypress/webpack-preprocessor')
|
||||
|
||||
module.exports = (on, config) => {
|
||||
// on('file:preprocessor', webpack({
|
||||
// webpackOptions: require('@vue/cli-service/webpack.config'),
|
||||
// watchOptions: {}
|
||||
// }))
|
||||
|
||||
return Object.assign({}, config, {
|
||||
fixturesFolder: 'tests/e2e/fixtures',
|
||||
integrationFolder: 'tests/e2e/specs',
|
||||
screenshotsFolder: 'tests/e2e/screenshots',
|
||||
videosFolder: 'tests/e2e/videos',
|
||||
supportFile: 'tests/e2e/support/index.js'
|
||||
})
|
||||
}
|
8
vr/tests/e2e/specs/test.js
Normal file
8
vr/tests/e2e/specs/test.js
Normal file
@ -0,0 +1,8 @@
|
||||
// https://docs.cypress.io/api/introduction/api.html
|
||||
|
||||
describe('My First Test', () => {
|
||||
it('Visits the app root url', () => {
|
||||
cy.visit('/')
|
||||
cy.contains('h1', 'Welcome to Your Vue.js App')
|
||||
})
|
||||
})
|
25
vr/tests/e2e/support/commands.js
Normal file
25
vr/tests/e2e/support/commands.js
Normal file
@ -0,0 +1,25 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add("login", (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
20
vr/tests/e2e/support/index.js
Normal file
20
vr/tests/e2e/support/index.js
Normal file
@ -0,0 +1,20 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
12
vr/tests/unit/example.spec.js
Normal file
12
vr/tests/unit/example.spec.js
Normal file
@ -0,0 +1,12 @@
|
||||
import { shallowMount } from '@vue/test-utils'
|
||||
import HelloWorld from '@/components/HelloWorld.vue'
|
||||
|
||||
describe('HelloWorld.vue', () => {
|
||||
it('renders props.msg when passed', () => {
|
||||
const msg = 'new message'
|
||||
const wrapper = shallowMount(HelloWorld, {
|
||||
propsData: { msg }
|
||||
})
|
||||
expect(wrapper.text()).toMatch(msg)
|
||||
})
|
||||
})
|
46
vr/vue.config.js
Normal file
46
vr/vue.config.js
Normal file
@ -0,0 +1,46 @@
|
||||
const path = require('path')
|
||||
function resolve (dir) {
|
||||
return path.join(__dirname, dir)
|
||||
}
|
||||
module.exports = {
|
||||
lintOnSave: false,
|
||||
devServer: {
|
||||
open: true,
|
||||
openPage: '',
|
||||
host: '0.0.0.0',
|
||||
port: 8080,
|
||||
https: false,
|
||||
proxy: null, // 设置代理
|
||||
before: app => {}
|
||||
},
|
||||
css: {
|
||||
loaderOptions: {
|
||||
sass: {
|
||||
// 添加这个配置来支持 @import
|
||||
sassOptions: {
|
||||
quietDeps: true
|
||||
},
|
||||
// 使用新的 API
|
||||
implementation: require('sass')
|
||||
}
|
||||
}
|
||||
},
|
||||
chainWebpack: config => {
|
||||
config.resolve.alias
|
||||
.set('@', resolve('src'))
|
||||
.set('@a', resolve('src/assets'))
|
||||
.set('@c', resolve('src/components'))
|
||||
// 优化大文件处理
|
||||
config.performance
|
||||
.maxEntrypointSize(1024000)
|
||||
.maxAssetSize(1024000)
|
||||
},
|
||||
configureWebpack: {
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
chunks: 'all',
|
||||
maxSize: 250000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user