WebVR大潮来袭时,前端开发能做些什么
WebVR大潮来袭时,前端开发能做些什么?

WebVR即web + VR的体验方式,我们可以戴着头显享受沉浸式的网页,新的API标准让我们可以使用js语言来开发。本文将介绍如何快速开发一个WebVR网页,在此之前,我们有必要了解WebVR的体验方式。
WebVR体验模式

WebVR的体验方式可以分为VR模式和裸眼模式
VR模式
1.Mobile VR
如使用cardboard眼镜来体验手机浏览器的webVR网页,浏览器将根据水平陀螺仪的参数来获取用户的头部倾斜和转动的朝向,并告知页面需要渲染哪一个朝向的场景。
2.PC VR
通过佩戴Oculus Rift的分离式头显浏览连接在PC主机端的网页,现支持WebVR API的浏览器主要是火狐的 Firefox Nightly和设置VR enabled的谷歌chrome beta。
裸眼模式
除了VR模式下的体验方式,这里还考虑了裸眼下的体验浏览网页的方式,在PC端如果探测的用户选择进入VR模式,应让用户可以使用鼠标拖拽场景,而在智能手机上则应让用户可以使用touchmove或旋转倾斜手机的方式来改变场景视角。
WebVR的概念大概就如此,这次我们将采用cardboard + mobile的方式来测试我们的WebVR场景,现在踏上我们的开发之旅。
准备工作
测试工具:智能手机 + cardboard式头显 + chrome beta 60+(需开启WebVR选项)
如果你练就了裸眼就能将手机双屏画面看成单屏的能力也可以省下头显。
技术和框架:three.js for WebGL
Three.js是构建3d场景的框架,它封装了WebGL函数,简化了创建场景的代码成本,利用three.js我们可以更优雅地创建出三维场景和三维动画,这里我使用的是0.86版本。
如果想了解纯WebGL开发WebVR应用以及WebVR具体环境配置,可以参考 webvr教程--深度剖析。
需要引入的js插件:
1.three.min.js
2.webvr-polyfill.js 由于WebVR API还没被各大主流浏览器支持,因此需要引入它来解决兼容性问题。
3D场景构建
首先我们创建一个HTML文件
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0, shrink-to-fit=no">
- <title>webVR-helloworld</title>
- <style type="text/css">
- * {
- margin: 0;
- padding: 0;
- }
- html,body {
- height: 100%;
- overflow: hidden;
- }
- </style>
- </head>
- <body>
- </body>
- <script src="./vendor/three.min.js"></script>
- <script src="./vendor/webvr-polyfill.js"></script>
- <script></script>
- </html>
接下来编写js脚本,开始创建我们的3d场景。
1.创建场景
Three.js中的scene场景是绘制我们3d对象的整个容器
- var scene = new THREE.Scene();
2.添加相机

Three.js中的camera相机代表用户的眼睛,我们通过设置FOV确定视野范围,
- //定义一个60°的视角,视线范围在1到1000的透视相机
- var camera = new THREE. new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,1,1000);
- scene.add(camera);
3.添加渲染器
Three.js的渲染器用来渲染camera所看到的画面
- //初始化渲染器 antialias参数为ture表示开启抗锯齿策略
- var renderer = new THREE.WebGLRenderer({ antialias: true } );
- //设置渲染器渲染尺寸
- renderer.setSize(window.innerWidth,window.innerHeight);
- //设置渲染背景为白色
- renderer.setClearColor(0xeeeeee);
- //将渲染场景的canvas放入body标签里
- document.body.appendChild(renderer.domElement);
4.添加一个立方体网格
- // 创建立方体
- var geometry = new THREE.CubeGeometry( 10,10,10);
- var material = new THREE.MeshLambertMaterial( { color: 0xef6500,needsUpdate: true,opacity:1,transparent:true} );
- var cube = new THREE.Mesh( geometry, material );
- cube.position.set(0,100,-50);
- cube.rotation.set(Math.PI/6,Math.PI/4,0);
- scene.add(cube);
5.启动动画
动画渲染的原理:渲染器的持续调用绘制方法,方法里动态改变物体的属性。
旧版的three.js需要手动调用requestAnimationFrame()方法递归的方式来渲染动画,新版three.js已经封装了该属性,因此只需要通过渲染器renderer.animate(callback)
。
- function update() {
- //让立方体旋转
- cube.rotation.y += 0.01;
- //渲染器渲染场景,等同于给相机按下快门
- renderer.render(scene, camera);
- }
- renderer.animate(update);//启动动画

至此,我们已经绘制了一个简单的3d场景并且让它动了起来,接下来,我们需要让我们的场景可以支持WebVR模式。
WebVR场景开发
WebVR网页开发的基本原理是通过WebVR API获取VR动态数据(VR Display frameData),渲染器根据VR数据来分别绘制左右屏场景,具体步骤如下:
- 使用
navigator.getVRDisplays
获取vr设备示例WebVR网页分屏vrdisplay是vr设备的实例,我们需要将它传给当前运行的renderer渲染器。
- function initVR(renderer) {
- renderer.vr.enabled = true;
- navigator.getVRDisplays().then( function(display) {
- renderer.vr.setDevice(display[0]);
- const button = document.querySelector('.vr-btn');
- VRbutton(display[0],renderer,button,function() {
- button.textContent = '退出VR';
- },function() {
- button.textContent = '进入VR';
- });
- }).catch(err => console.warn(err));
- }
这里需要通过按钮来控制当前的渲染模式:
- 当点击按钮时,根据
display.isPresenting
判断当前是否是使用vr设备下进行渲染,如果false,进入2,否则true进入3 - 当前非VR模式,点击按钮进入VR模式,此时调用
display.requestPresent()
,display.isPresenting
被设置为true,触发window的vrdisplaypresentchange
事件 - 当前为VR模式,点击按钮退出模式,此时调用
display.exitPresent()
,display.isPresenting
被设置为false,触发window的vrdisplaypresentchange
事件
- /** VR按钮控制
- * @param {VRDisplay} display VRDisplay实例
- * @param {THREE.WebGLRenderer} renderer 渲染器
- * @param {HTMLElement} button VR控制按钮
- * @param {Function} enterVR 点击进入VR模式时回调
- * @param {Function} exitVR 点击退出VR模式时回调
- **/
- function VRbutton(display,renderer,button,enterVR,exitVR) {
- if ( display ) {
- button.addEventListener('click', function() {
- // 点击vr按钮控制`isPresenting`状态
- display.isPresenting ? display.exitPresent() : display.requestPresent( [ { source: renderer.domElement } ] );
- });
- window.addEventListener( 'vrdisplaypresentchange', function() {
- // 是否处于vr体验模式中,是则触发enterVR,否则触发exitVR
- display.isPresenting ? enterVR() : exitVR();
- }, false );
- } else {
- // 找不到vr设备实例,则移除按钮
- button.remove();
- }
- }
我们可以在vrdisplaypresentchange
事件中根据isPresenting
的值来改变按钮的UI,而three.js将根据isPresenting
的值来决定是常规渲染还是vr模式渲染,在vr模式下,three.js将创建两个camera进行渲染。
代码优化
最后,将WebVR应用写成ES6 class,后面开发流程将按如下图结构来规范代码:

第一步,构造函数先初始化VR场景、相机和渲染器;
第二步,在渲染之前调用start方法,在start方法里我们为场景创建3d物体;
最后,调起renderer.animate(this.update)
开启动画渲染,update方法里我们可动态操作物体属性,具体代码如下:
- class WebVRApp {
- constructor() {
- // 初始化场景
- this.scene = new THREE.Scene();
- // 初始化相机
- this.camera = new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,0.1,1000);
- this.scene.add(this.camera);
- // 初始化渲染器
- this.renderer = new THREE.WebGLRenderer({ antialias: true } );
- this.renderer.setSize(window.innerWidth,window.innerHeight);
- this.renderer.setClearColor(0x519EcB);
- this.renderer.setPixelRatio(window.devicePixelRatio);
- document.querySelector('.main-page').appendChild(this.renderer.domElement);
- this.clock = new THREE.Clock();
- // VR初始化
- this._initVR();
- // 往场景添加3d物体
- this.start();
- // 窗口大小调整监听
- window.addEventListener( 'resize', this._resize.bind(this), false );
- // 渲染动画
- this.renderer.animate(this.update.bind(this));
- }
- // 创建3d物体
- start() {
- const { scene, camera } = this;
- // 创建光线、地面等
- ...
- // 创建立方体
- const geometry = new THREE.CubeGeometry(2, 2, 2);
- const material = new THREE.MeshLambertMaterial({
- color: 0xef6500,
- });
- this.cube = new THREE.Mesh( geometry, material );
- this.cube.position.set({ x: 0, y: 0, z: -4 });
- scene.add(this.cube);
- }
- // 动画更新
- update() {
- const {scene,camera,renderer,clock} = this;
- const delta = clock.getDelta() * 60;
- // 启动渲染
- this.cube.rotation.y += 0.1 * delta;
- renderer.render(scene, camera);
- }
- // VR模式初始化
- _initVR() {
- const { renderer } = this;
- renderer.vr.enabled = true;
- // 获取VRDisplay实例
- navigator.getVRDisplays().then( display => {
- // 将display实例传给renderer渲染器
- renderer.vr.setDevice(display[0]);
- const button = document.querySelector('.vr-btn');
- VRButton.init(display[0],renderer,button,() => button.textContent = '退出VR',() => button.textContent = '进入VR');
- }).catch(err => console.warn(err));
- }
- // 窗口调整监听
- _resize() {
- const { camera, renderer } = this;
- // 窗口调整重新调整渲染器
- camera.aspect = window.innerWidth / window.innerHeight;
- camera.updateProjectionMatrix();
- renderer.setSize(window.innerWidth, window.innerHeight);
- }
- }
- new WebVRApp();

完整代码:github.com/YoneChen/WebVR-helloworld。
结语
目前,国外的谷歌、火狐、Facebook和国内百度已推出支持WebVR浏览器的版本,微软也宣布将推出自己的VR浏览器,随着后期5g网络极速时代的到来以及HMD头显的价格和平台的成熟,WebVR的体验方式将是革命性的,用户通过WebVR浏览网上商店,线上教学可进行“面对面”师生交流等,基于这种种应用场景,我们可以找到一个更好的动力去学习WebVR。
参考链接
responisve WebVR: 探讨WebVR在不同头显(HMD)的适配方案
MolizaVR example: 火狐WebVR示例
webvr-boilerplate: A starting point for web-based VR experiences that work on all VR headsets.
how to build webvr: How to Build VR on the Web Today
作者 | YoneChen
来源 | https://www.jianshu.com/p/c9c03e14ba9d
WebVR大潮来袭时,前端开发能做些什么的更多相关文章
- 拿2k的前端开发都会做些什么?
坐标珠海,前端程序媛一枚 实习时候做的是测试,2.5k+600餐补: 后来觉得对前端更有兴趣所以重新找工作,但是苦于没有经验,毕业第一年在一个传统行业的公司找到了一个前端岗位,薪酬4k,公司主要是接政 ...
- 2017年Web前端开发工程师薪资越来越高?
放眼全球,不仅在国内的互联网行业,在国外,前端工程师一样是需求旺盛.供不应求的香饽饽.所以在供不应求的前端招聘市场上,优秀的前端工程师才是有话语权的那一方. 前端开发是做什么的? 前端是互联网时代软件 ...
- Visual Studio前端开发工具/扩展
怎么样让Visual Studio更好地编写HTML5, CSS3, JavaScript, jQuery,换句话说就是如何更好地做前端开发.Visual Studio 2010不管是旗舰版还是免费版 ...
- 【翻译】我钟爱的Visual Studio前端开发工具/扩展
原文:[翻译]我钟爱的Visual Studio前端开发工具/扩展 怎么样让Visual Studio更好地编写HTML5, CSS3, JavaScript, jQuery,换句话说就是如何更好地做 ...
- 什么是web前端开发?
Web前端开发工程师,主要职责是利用(X)HTML/CSS/JavaScript/Flash等各种Web技术进行客户端产品的开发.完成客户端程序(也就是浏览器端)的开发,开发JavaScript以及F ...
- 在做APP前端开发时应注意的一些问题
在做APP前端开发时应注意的一些问题 在整个app开发流程中,app前端开发是一个必不可少的环节,也是一个在app开发过程中重量级的角色.说到这,那么在app应用的前端开发中,又要注意什么问题呢?一. ...
- 绝对精品推荐做前端的看下:Web前端开发体会十日谈
20151208感悟: 前端人的角度来看的话,感觉像是阅读一个大牛前端的全部武功的一个秘籍说明,里面的思想高价值蛋白真是太多太多,推荐看. Web前端开发体会十日谈 一直想写这篇“十日谈”,聊聊我对W ...
- 做一个会使用PS的前端开发
做前端开发的需不需要PS 记得在之前的老东家做某一个系统开发,当时正在做界面开发,发现界面还需要添加几个图标,于是把这个需求反馈给了项目经理.过了十几分钟,项目经理跑过来告诉我:产品部的UI设计人员( ...
- 做一个会PS切图的前端开发
系列链接 做一个会使用PS的前端开发 做一个会PS切图的前端开发 切图方法分类 PhotoShop从CS版本演变到现在的CC版本,切图功能发生了比较大的变化,我们可以把PhotoShop CS版本时的 ...
随机推荐
- Django框架之ORM的相关操作(一)
一.一般操作 from django.db import models import datetime # Create your models here. class Author(models.M ...
- 喵星之旅-狂奔的兔子-centos7安装MySQL 5.5
安装环境:https://www.cnblogs.com/kittybunny/p/12296078.html 一.下载安装文件 下载地址 https://downloads.mysql.com/ar ...
- JAVA基础学习(7)之函数
7函数 7.1函数定义与调用 7.1.1函数定义 7.1.2函数调用 package com.study.main; public class ObjectStudy { public static ...
- pod的状态及操作
查看pod的标签 [root@master pod]# kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS cv- ...
- Python MySQLdb中执行SQL语句传入的参数应该要加上引号如果该字段是str类型的
如下图: username在表中是字符串类型的,所以传入的参数要加上引号
- 如何在CentOS 7上安装Apache
使用systemctl管理Apache服务 我们可以像任何其他系统单元一样管理Apache服务. 要停止Apache服务,请运行: sudo systemctl stop httpd 要再次启动,请键 ...
- PowerDesigner每点击一次就会提示打印错误对话框
把服务启用了就好了: 重启软件
- win10配置cuda和pytorch
简介 pytorch是非常流行的深度学习框架.下面是Windows平台配置pytorch的过程. 一共需要安装cuda.pycharm.anancoda.pytorch. 主要介绍cuda和pytor ...
- CentOS 7控制台屏幕分辨率问题
我们在服务器上,很少会安装图形化界面,一般都使用字符界面的控制台.CentOS 下,控制台分辨率缺省情况下,变得很高,导致在显示器上花屏或者只能显示局部. 这是由于使用了frame buffer,好处 ...
- 无线客户端掉线(Disassociate and DeleteReason)