脚本宝典收集整理的这篇文章主要介绍了

VR大潮来袭 —前端开发能做些什么

脚本宝典小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助你少写一行代码,多一份安全和惬意。
<p><code></p> <p><span class="img-wrap"><img data-src="/img/remote/1460000008904026" src="/img/remote/1460000008904026" alt="WebVR未来新潮" title="WebVR未来新潮" style="cursor: pointer; display: inline;"></span></p> <p>WebVR即web + VR的体验方式,我们可以戴着头显享受沉浸式的网页,新的<a href="http://www.js-code.com/tag/api" title="API" target="_blank">API</a>标准让我们可以使用js语言来开发。本文将介绍如何快速开发一个WebVR网页,在此之前,我们有必要了解WebVR的体验方式。</p> <h3 id="articleHeader0">WebVR体验模式</h3> <hr> <p><span class="img-wrap"><img data-src="/img/remote/1460000008904027" src="/img/remote/1460000008904027" alt="体验WebVR的方式" title="体验WebVR的方式" style="cursor: pointer; display: inline;"></span><br /><strong><em>WebVR的体验方式可以分为VR模式和裸眼模式</em></strong></p> <h4>VR模式</h4> <p><strong><em>1.Mobile VR</em></strong></p> <p>如使用cardboard眼镜来体验手机浏览器的webVR网页,浏览器将根据水平陀螺仪的参数来获取用户的头部倾斜和转动的朝向,并告知页面需要渲染哪一个朝向的场景。</p> <p><strong><em>2.PC VR</em></strong></p> <p>通过佩戴Oculus R<a href="http://www.js-code.com/tag/if" title="if" target="_blank">if</a>t的分离式头显浏览连接在PC主机端的网页,现支持WebVR <a href="http://www.js-code.com/tag/api" title="API" target="_blank">API</a>的浏览器主要是火狐的&nbsp;<a href="https://nightly.mozilla.org/" rel="nofollow noreferrer" target="_blank">Firefox Nightly</a>和设置VR enabled的谷歌chrome beta。</p> <h4>裸眼模式</h4> <p>除了VR模式下的体验方式,这里还考虑了裸眼下的体验浏览网页的方式,在PC端如果探测的用户选择进入VR模式,应让用户可以使用鼠标拖拽场景,而在智能手机上则应让用户可以使用touchmove或旋转倾斜手机的方式来改变场景视角。<br />WebVR的概念大概就如此,这次我们将采用cardboard + mobile的方式来测试我们的WebVR场景,现在踏上我们的开发之旅。</p> <h3 id="articleHeader1">准备工作</h3> <hr> <blockquote> <p>测试工具:智能手机 + cardboard式头显 + chrome beta 60+(需开启WebVR选项)</p> </blockquote> <p>如果你练就了裸眼就能将手机双屏画面看成单屏的能力也可以省下头显。</p> <blockquote> <p>技术和框架:three.js <a href="http://www.js-code.com/tag/for" title="for" target="_blank">for</a> WebGL</p> </blockquote> <p><a href="http://threejs.org" rel="nofollow noreferrer" target="_blank">Three.js</a>是构建3d场景的框架,它封装了WebGL函数,简化了创建场景的代码成本,利用three.js我们可以更优雅地创建出三维场景和三维动画,这里我使用的是0.86版本。<br />如果想了解纯WebGL开发WebVR应用以及WebVR具体环境配置,可以参考 <a href="https://zhuanlan.zhihu.com/p/28324884" rel="nofollow noreferrer" target="_blank">webvr教程--深度剖析</a>。</p> <blockquote> <p>需要引入的js插件:</p> </blockquote> <p>1.<a href="https://github.com/mrdoob/three.js/blob/dev/build/three.min.js" rel="nofollow noreferrer" target="_blank">three.min.js</a><br /> 2.<a href="https://github.com/googlevr/webvr-polyfill/" rel="nofollow noreferrer" target="_blank">webvr-polyfill.js</a> 由于<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebVR_API" rel="nofollow noreferrer" target="_blank">WebVR API</a>还没被各大主流浏览器支持,因此需要引入它来解决兼容性问题。</p> <h3 id="articleHeader2">3D场景构建</h3> <hr> <p>首先我们创建一个<a href="http://www.js-code.com/tag/html" title="HTML" target="_blank">HTML</a>文件</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="<a href="http://www.js-code.com/tag/button" title="button" target="_blank">button</a>" <a href="http://www.js-code.com/tag/class" title="class" target="_blank">class</a>="copyCode code-tool" data-toggle="tooltip" data-placement="<a href="http://www.js-code.com/tag/top" title="top" target="_blank">top</a>" data-clipboard-<a href="http://www.js-code.com/tag/text" title="text" target="_blank">text</a>="<!DOCTYPE html><br /> <html lang=&quot;en&quot;><br /> <head><br /> <meta charset=&quot;UTF-8&quot;><br /> <meta name=&quot;viewport&quot; content=&quot;width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0, shrink-to-fit=no&quot;><br /> <title>webVR-helloworld</title></p> <style type=&quot;text/css&quot;> * { marg<a href="http://www.js-code.com/tag/in" title="in" target="_blank">in</a>: 0; padd<a href="http://www.js-code.com/tag/in" title="in" target="_blank">in</a>g: 0; } html,body { height: 100%; overflow: <a href="http://www.js-code.com/tag/hidden" title="hidden" target="_blank">hidden</a>; } </style> <p></head><br /> <body><br /> </body><br /> <script src=&quot;./vendor/three.min.js&quot;></script><br /> <script src=&quot;./vendor/webvr-polyfill.js&quot;></script><br /> <script></script><br /> </html>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs xml"><code><span class="hljs-meta">&lt;!DOCTYPE html&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr"><a href="http://www.js-code.com/tag/char" title="浏览关于“char”的文章" target="_blank" class="tag_link">char</a>set</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr"><a href="http://www.js-code.com/tag/name" title="浏览关于“name”的文章" target="_blank" class="tag_link">name</a></span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, user-scalable=no, m<a href="http://www.js-code.com/tag/in" title="浏览关于“in”的文章" target="_blank" class="tag_link">in</a>imum-scale=1.0, maximum-scale=1.0, shrink-to-fit=no"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>webVR-helloworld<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"<a href="http://www.js-code.com/tag/text" title="浏览关于“text”的文章" target="_blank" class="tag_link">text</a>/css"</span>&gt;</span><span class="css"> * { <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>; <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>; } <span class="hljs-selector-tag">html</span>,<span class="hljs-selector-tag">body</span> { <span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>; <span class="hljs-attribute">overflow</span>: <a href="http://www.js-code.com/tag/hidden" title="浏览关于“hidden”的文章" target="_blank" class="tag_link">hidden</a>; } </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./ven<a href="http://www.js-code.com/tag/do" title="浏览关于“do”的文章" target="_blank" class="tag_link">do</a>r/three.min.js"</span>&gt;</span><span class="undefined"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"./vendor/webvr-polyfill.js"</span>&gt;</span><span class="undefined"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="undefined"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></code></pre> <p>接下来编写js脚本,开始创建我们的3d场景。</p> <h4>1.创建场景</h4> <p>Three.js中的scene场景是绘制我们3d对象的整个容器</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="var scene = new THREE.Scene();" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs scala"><code style="word-break: break-word; white-space: initial;"><span class="hljs-keyword"><a href="http://www.js-code.com/tag/var" title="浏览关于“var”的文章" target="_blank" class="tag_link">var</a></span> scene = <span class="hljs-keyword"><a href="http://www.js-code.com/tag/new" title="浏览关于“new”的文章" target="_blank" class="tag_link">new</a></span> <span class="hljs-type">THREE</span>.<span class="hljs-type">Scene</span>();</code></pre> <h4>2.添加相机</h4> <p><span class="img-wrap"><img data-src="/img/remote/1460000008904028" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="Three.js的相机" title="Three.js的相机" style="cursor: pointer;"></span></p> <p>Three.js中的camera相机代表用户的眼睛,我们通过设置FOV确定视野范围,</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="//定义一个60°的视角,视线范围在1到1000的透视相机 var camera = new THREE. new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,1,1000); scene.add(camera);" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-comment">//定义一个60°的视角,视线范围在1到1000的透视相机</span> <span class="hljs-keyword">var</span> camera = <span class="hljs-keyword">new</span> THREE. <span class="hljs-keyword">new</span> THREE.PerspectiveCamera(<span class="hljs-number">60</span>,<span class="hljs-built_in"><a href="http://www.js-code.com/tag/window" title="浏览关于“window”的文章" target="_blank" class="tag_link">window</a></span>.<a href="http://www.js-code.com/tag/innerWidth" title="浏览关于“innerWidth”的文章" target="_blank" class="tag_link">innerWidth</a>/<span class="hljs-built_in">window</span>.<a href="http://www.js-code.com/tag/innerHeight" title="浏览关于“innerHeight”的文章" target="_blank" class="tag_link">innerHeight</a>,<span class="hljs-number">1</span>,<span class="hljs-number">1000</span>); scene.add(camera);</code></pre> <h4>3.添加渲染器</h4> <p>Three.js的渲染器用来渲染camera所看到的画面</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="//初始化渲染器 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);" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-comment">//初始化渲染器 antialias参数为ture表示开启抗锯齿策略</span> <span class="hljs-keyword">var</span> renderer = <span class="hljs-keyword">new</span> THREE.WebGLRenderer({ antialias: <span class="hljs-literal"><a href="http://www.js-code.com/tag/true" title="浏览关于“true”的文章" target="_blank" class="tag_link">true</a></span> } ); <span class="hljs-comment">//设置渲染器渲染尺寸</span> renderer.setSize(<span class="hljs-built_in">window</span>.innerWidth,<span class="hljs-built_in">window</span>.innerHeight); <span class="hljs-comment">//设置渲染背景为白色</span> renderer.setClearColor(<span class="hljs-number">0xeeeeee</span>); <span class="hljs-comment">//将渲染场景的canvas放入body标签里</span> <span class="hljs-built_in"><a href="http://www.js-code.com/tag/document" title="浏览关于“document”的文章" target="_blank" class="tag_link">document</a></span>.body.appendChild(renderer.domElement);</code></pre> <h6>4.添加一个立方体网格</h6> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="// 创建立方体 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);" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs cs"><code><span class="hljs-comment">// 创建立方体</span> <span class="hljs-keyword">var</span> geome<a href="http://www.js-code.com/tag/try" title="浏览关于“try”的文章" target="_blank" class="tag_link">try</a> = <span class="hljs-keyword">new</span> THREE.CubeGeometry( <span class="hljs-number">10</span>,<span class="hljs-number">10</span>,<span class="hljs-number">10</span>); <span class="hljs-keyword">var</span> material = <span class="hljs-keyword">new</span> THREE.MeshLambertMaterial( { color: <span class="hljs-number">0xef6500</span>,needsUpdate: <span class="hljs-literal">true</span>,opacity:<span class="hljs-number">1</span>,trans<a href="http://www.js-code.com/tag/parent" title="浏览关于“parent”的文章" target="_blank" class="tag_link">parent</a>:<span class="hljs-literal">true</span>} ); <span class="hljs-keyword">var</span> cube = <span class="hljs-keyword">new</span> THREE.Mesh( geometry, material ); cube.position.<span class="hljs-keyword">set</span>(<span class="hljs-number">0</span>,<span class="hljs-number">100</span>,<span class="hljs-number">-50</span>); cube.rotation.<span class="hljs-keyword">set</span>(<a href="http://www.js-code.com/tag/Math" title="浏览关于“Math”的文章" target="_blank" class="tag_link">Math</a>.PI/<span class="hljs-number">6</span>,Math.PI/<span class="hljs-number">4</span>,<span class="hljs-number">0</span>); scene.<span class="hljs-keyword">add</span>(cube);</code></pre> <h4>5.启动动画</h4> <p>动画渲染的原理:渲染器的持续调用绘制方法,方法里动态改变物体的属性。<br />旧版的three.js需要手动调用requestAnimationFrame()方法递归的方式来渲染动画,新版three.js已经封装了该属性,因此只需要通过渲染器<code>renderer.animate(c<a href="http://www.js-code.com/tag/all" title="all" target="_blank">all</a>back)</code>。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="function update() { //让立方体旋转 cube.rotation.y += 0.01; //渲染器渲染场景,等同于给相机按下快门 renderer.render(scene, camera); } renderer.animate(update);//启动动画" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs actionscript"><code><span class="hljs-function"><span class="hljs-keyword"><a href="http://www.js-code.com/tag/function" title="浏览关于“function”的文章" target="_blank" class="tag_link">function</a></span> <span class="hljs-title">update</span><span class="hljs-params">()</span> </span>{ <span class="hljs-comment">//让立方体旋转</span> cube.rotation.y += <span class="hljs-number">0.01</span>; <span class="hljs-comment">//渲染器渲染场景,等同于给相机按下快门</span> renderer.render(scene, camera); } renderer.animate(update);<span class="hljs-comment">//启动动画</span></code></pre> <p><span class="img-wrap"><img data-src="/img/remote/1460000008904029" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="基本的3d场景" title="基本的3d场景" style="cursor: pointer;"></span></p> <p>至此,我们已经绘制了一个简单的3d场景并且让它动了起来,接下来,我们需要让我们的场景可以支持WebVR模式。</p> <h2 id="articleHeader3">WebVR场景开发</h2> <p>WebVR网页开发的基本原理是通过WebVR <a href="http://www.js-code.com/tag/api" title="浏览关于“API”的文章" target="_blank" class="tag_link">API</a>获取VR动态数据(VR Display <a href="http://www.js-code.com/tag/frame" title="frame" target="_blank">frame</a>Data),渲染器根据VR数据来分别绘制左右屏场景,具体步骤如下:</p> <ol> <li>使用<code><a href="http://www.js-code.com/tag/navigator" title="navigator" target="_blank">navigator</a>.getVRDisplays</code>获取vr设备示例<br /><span class="img-wrap"><img data-src="/img/remote/1460000008904030" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="WebVR网页分屏" title="WebVR网页分屏" style="cursor: pointer;"></span> </li> </ol> <p>vrdisplay是vr设备的实例,我们需要将它传给当前运行的renderer渲染器。</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="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));<br /> }<br /> " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs javascript"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initVR</span>(<span class="hljs-params">renderer</span>) </span>{ renderer.vr.enabled = <span class="hljs-literal">true</span>; <a href="http://www.js-code.com/tag/navigator" title="浏览关于“navigator”的文章" target="_blank" class="tag_link">navigator</a>.getVRDisplays().then( <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">display</span>) </span>{ renderer.vr.setDevice(display[<span class="hljs-number">0</span>]); <span class="hljs-keyword"><a href="http://www.js-code.com/tag/const" title="浏览关于“const”的文章" target="_blank" class="tag_link">const</a></span> <a href="http://www.js-code.com/tag/button" title="浏览关于“button”的文章" target="_blank" class="tag_link">button</a> = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.vr-btn'</span>); VRbutton(display[<span class="hljs-number">0</span>],renderer,button,<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ button.textContent = <span class="hljs-string">'退出VR'</span>; },<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ button.textContent = <span class="hljs-string">'进入VR'</span>; }); }).<a href="http://www.js-code.com/tag/catch" title="浏览关于“catch”的文章" target="_blank" class="tag_link">catch</a>(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-built_in">console</span>.warn(err)); } </code></pre> <p>这里需要通过按钮来控制当前的渲染模式:</p> <ol> <li>当点击按钮时,根据<code>display.isPresenting</code>判断当前是否是使用vr设备下进行渲染,如果<a href="http://www.js-code.com/tag/false" title="false" target="_blank">false</a>,进入2,否则<a href="http://www.js-code.com/tag/true" title="true" target="_blank">true</a>进入3</li> <li>当前非VR模式,点击按钮进入VR模式,此时调用<code>display.requestPresent()</code>,<code>display.isPresenting</code>被设置为<a href="http://www.js-code.com/tag/true" title="true" target="_blank">true</a>,触发win<a href="http://www.js-code.com/tag/do" title="do" target="_blank">do</a>w的<code>vrdisplaypresentchange</code>事件</li> <li>当前为VR模式,点击按钮退出模式,此时调用<code>display.exitPresent()</code>,<code>display.isPresenting</code>被设置为<a href="http://www.js-code.com/tag/false" title="false" target="_blank">false</a>,触发<a href="http://www.js-code.com/tag/window" title="window" target="_blank">window</a>的<code>vrdisplaypresentchange</code>事件</li> </ol> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="/** 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(); } } " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs php"><code><span class="hljs-comment">/** VR按钮控制 * <span class="hljs-doctag">@param</span> {VRDisplay} display VRDisplay实例 * <span class="hljs-doctag">@param</span> {THREE.WebGLRenderer} renderer 渲染器 * <span class="hljs-doctag">@param</span> {<a href="http://www.js-code.com/tag/html" title="浏览关于“HTML”的文章" target="_blank" class="tag_link">HTML</a>Element} button VR控制按钮 * <span class="hljs-doctag">@param</span> {Function} enterVR 点击进入VR模式时回调 * <span class="hljs-doctag">@param</span> {Function} exitVR 点击退出VR模式时回调 **/</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">VRbutton</span><span class="hljs-params">(display,renderer,button,enterVR,exitVR)</span> </span>{ <span class="hljs-keyword"><a href="http://www.js-code.com/tag/if" title="浏览关于“if”的文章" target="_blank" class="tag_link">if</a></span> ( display ) { button.addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{ <span class="hljs-comment">// 点击vr按钮控制`isPresenting`状态</span> display.isPresenting ? display.exitPresent() : display.requestPresent( [ { source: renderer.domElement } ] ); }); window.addEventListener( <span class="hljs-string">'vrdisplaypresentchange'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> </span>{ <span class="hljs-comment">// 是否处于vr体验模式中,是则触发enterVR,否则触发exitVR</span> display.isPresenting ? enterVR() : exitVR(); }, <span class="hljs-keyword"><a href="http://www.js-code.com/tag/false" title="浏览关于“false”的文章" target="_blank" class="tag_link">false</a></span> ); } <span class="hljs-keyword"><a href="http://www.js-code.com/tag/else" title="浏览关于“else”的文章" target="_blank" class="tag_link">else</a></span> { <span class="hljs-comment">// 找不到vr设备实例,则移除按钮</span> button.remove(); } } </code></pre> <p>我们可以在<code>vrdisplaypresentchange</code>事件中根据<code>isPresenting</code>的值来改变按钮的UI,而three.js将根据<code>isPresenting</code>的值来决定是常规渲染还是vr模式渲染,在vr模式下,three.js将创建两个camera进行渲染。</p> <h3 id="articleHeader4">代码优化</h3> <p>最后,将WebVR应用写成ES6 <a href="http://www.js-code.com/tag/class" title="class" target="_blank">class</a>,后面开发流程将按如下图结构来规范代码:</p> <p><span class="img-wrap"><img data-src="/img/remote/1460000011813632?w=1198&amp;h=1042" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="WebVRApp类" title="WebVRApp类" style="cursor: pointer;"></span></p> <p>第一步,构造函数先初始化VR场景、相机和渲染器;第二步,在渲染之前调用start方法,在start方法里我们为场景创建3d物体;最后,调起<code>renderer.animate(<a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.update)</code>开启动画渲染,update方法里我们可动态操作物体属性,具体代码如下:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="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; // 创建光线 scene.add(new THREE.AmbientLight(0xFFFFFF)); this.addLight(); // 创建地面 this.addGround(1000,1000); // 创建立方体 this.addCube(2,2,2, 2,-1,-3); } // VR模式初始化 initVR() { const {renderer} = this; renderer.vr.enabled = true; // 获取VRDisplay实例 navigator.getVRDisplays().then( display => {<br /> // 将display实例传给renderer渲染器<br /> renderer.vr.setDevice(display[0]);<br /> const button = document.querySelector('.vr-btn');<br /> VRButton.init(display[0],renderer,button,() => button.textContent = '退出VR',() => button.textContent = '进入VR');<br /> }).catch(err => console.warn(err));<br /> }<br /> // 窗口调整监听<br /> resize() {<br /> const {camera,renderer} = this;<br /> // 窗口调整重新调整渲染器<br /> camera.aspect = window.innerWidth / window.innerHeight;<br /> camera.updateProjectionMatrix();<br /> renderer.setSize(window.innerWidth, window.innerHeight);<br /> }<br /> addCube(width=2,height=2,depth=2, posX,posY,posZ) {<br /> const {scene} = this;<br /> // 创建立方体<br /> const geometry = new THREE.CubeGeometry(width,height,depth);<br /> const material = new THREE.MeshLambertMaterial({<br /> color: 0xef6500,<br /> needsUpdate: true,<br /> opacity:1,<br /> transparent:true<br /> });<br /> const cube = new THREE.Mesh( geometry, material );<br /> cube.position.set({<br /> x: posX,<br /> y: posY,<br /> z: posZ<br /> });<br /> this.cube = cube;<br /> scene.add(cube);<br /> }<br /> addGround(width,height) {<br /> const {scene} = this;<br /> // 创建地平面<br /> const geometry = new THREE.PlaneBufferGeometry( width, height );<br /> const material = new THREE.MeshPhongMaterial( { color: 0xaaaaaa } );<br /> const ground = new THREE.Mesh( geometry, material );<br /> ground.rotation.x = - Math.PI / 2;<br /> ground.position.y = -10;<br /> scene.add(cube);<br /> }<br /> // 动画更新<br /> update() {<br /> const {scene,camera,renderer,clock} = this;<br /> const delta = clock.getDelta() * 60;<br /> // 启动渲染<br /> this.cube.rotation.y += 0.1 * delta;<br /> renderer.render(scene, camera);<br /> }<br /> }<br /> new WebVRApp();" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-keyword">class</span> WebVRApp { <span class="hljs-keyword"><a href="http://www.js-code.com/tag/constructor" title="浏览关于“constructor”的文章" target="_blank" class="tag_link">constructor</a></span>(<span class="hljs-params"></span>) { <span class="hljs-comment">// 初始化场景</span> <span class="hljs-keyword"><a href="http://www.js-code.com/tag/this" title="浏览关于“this”的文章" target="_blank" class="tag_link">this</a></span>.scene = <span class="hljs-keyword">new</span> THREE.Scene(); <span class="hljs-comment">// 初始化相机</span> <span class="hljs-keyword">this</span>.camera = <span class="hljs-keyword">new</span> THREE.PerspectiveCamera(<span class="hljs-number">60</span>,<span class="hljs-built_in">window</span>.innerWidth/<span class="hljs-built_in">window</span>.innerHeight,<span class="hljs-number">0.1</span>,<span class="hljs-number">1000</span>); <span class="hljs-keyword">this</span>.scene.add(<span class="hljs-keyword">this</span>.camera); <span class="hljs-comment">// 初始化渲染器</span> <span class="hljs-keyword">this</span>.renderer = <span class="hljs-keyword">new</span> THREE.WebGLRenderer({ antialias: <span class="hljs-literal">true</span> } ); <span class="hljs-keyword">this</span>.renderer.setSize(<span class="hljs-built_in">window</span>.innerWidth,<span class="hljs-built_in">window</span>.innerHeight); <span class="hljs-keyword">this</span>.renderer.setClearColor(<span class="hljs-number">0x519EcB</span>); <span class="hljs-keyword">this</span>.renderer.setPixelRatio(<span class="hljs-built_in">window</span>.devicePixelRatio); <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.main-page'</span>).appendChild(<span class="hljs-keyword">this</span>.renderer.domElement); <span class="hljs-keyword">this</span>.clock = <span class="hljs-keyword">new</span> THREE.Clock(); <span class="hljs-comment">// VR初始化</span> <span class="hljs-keyword">this</span>.initVR(); <span class="hljs-comment">// 往场景添加3d物体</span> <span class="hljs-keyword">this</span>.start(); <span class="hljs-comment">// 窗口大小调整监听</span> <span class="hljs-built_in">window</span>.addEventListener( <span class="hljs-string">'resize'</span>, <span class="hljs-keyword">this</span>.resize.bind(<span class="hljs-keyword">this</span>), <span class="hljs-literal">false</span> ); <span class="hljs-comment">// 渲染动画</span> <span class="hljs-keyword">this</span>.renderer.animate(<span class="hljs-keyword">this</span>.update.bind(<span class="hljs-keyword">this</span>)); } <span class="hljs-comment">// 创建3d物体</span> start() { <span class="hljs-keyword">const</span> {scene,camera} = <span class="hljs-keyword">this</span>; <span class="hljs-comment">// 创建光线</span> scene.add(<span class="hljs-keyword">new</span> THREE.AmbientLight(<span class="hljs-number">0xFFFFFF</span>)); <span class="hljs-keyword">this</span>.addLight(); <span class="hljs-comment">// 创建地面</span> <span class="hljs-keyword">this</span>.addGround(<span class="hljs-number">1000</span>,<span class="hljs-number">1000</span>); <span class="hljs-comment">// 创建立方体</span> <span class="hljs-keyword">this</span>.addCube(<span class="hljs-number">2</span>,<span class="hljs-number">2</span>,<span class="hljs-number">2</span>, <span class="hljs-number">2</span>,<span class="hljs-number">-1</span>,<span class="hljs-number">-3</span>); } <span class="hljs-comment">// VR模式初始化</span> initVR() { <span class="hljs-keyword">const</span> {renderer} = <span class="hljs-keyword">this</span>; renderer.vr.enabled = <span class="hljs-literal">true</span>; <span class="hljs-comment">// 获取VRDisplay实例</span> navigator.getVRDisplays().then( <span class="hljs-function"><span class="hljs-params">display</span> =&gt;</span> { <span class="hljs-comment">// 将display实例传给renderer渲染器</span> renderer.vr.setDevice(display[<span class="hljs-number">0</span>]); <span class="hljs-keyword">const</span> button = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.vr-btn'</span>); VRButton.init(display[<span class="hljs-number">0</span>],renderer,button,<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> button.textContent = <span class="hljs-string">'退出VR'</span>,<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> button.textContent = <span class="hljs-string">'进入VR'</span>); }).catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-built_in">console</span>.warn(err)); } <span class="hljs-comment">// 窗口调整监听</span> resize() { <span class="hljs-keyword">const</span> {camera,renderer} = <span class="hljs-keyword">this</span>; <span class="hljs-comment">// 窗口调整重新调整渲染器</span> camera.aspect = <span class="hljs-built_in">window</span>.innerWidth / <span class="hljs-built_in">window</span>.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(<span class="hljs-built_in">window</span>.innerWidth, <span class="hljs-built_in">window</span>.innerHeight); } addCube(width=<span class="hljs-number">2</span>,height=<span class="hljs-number">2</span>,depth=<span class="hljs-number">2</span>, posX,posY,posZ) { <span class="hljs-keyword">const</span> {scene} = <span class="hljs-keyword">this</span>; <span class="hljs-comment">// 创建立方体</span> <span class="hljs-keyword">const</span> geometry = <span class="hljs-keyword">new</span> THREE.CubeGeometry(width,height,depth); <span class="hljs-keyword">const</span> material = <span class="hljs-keyword">new</span> THREE.MeshLambertMaterial({ color: <span class="hljs-number">0xef6500</span>, needsUpdate: <span class="hljs-literal">true</span>, opacity:<span class="hljs-number">1</span>, transparent:<span class="hljs-literal">true</span> }); <span class="hljs-keyword">const</span> cube = <span class="hljs-keyword">new</span> THREE.Mesh( geometry, material ); cube.position.set({ x: posX, y: posY, z: posZ }); <span class="hljs-keyword">this</span>.cube = cube; scene.add(cube); } addGround(width,height) { <span class="hljs-keyword">const</span> {scene} = <span class="hljs-keyword">this</span>; <span class="hljs-comment">// 创建地平面</span> <span class="hljs-keyword">const</span> geometry = <span class="hljs-keyword">new</span> THREE.PlaneBufferGeometry( width, height ); <span class="hljs-keyword">const</span> material = <span class="hljs-keyword">new</span> THREE.MeshPhongMaterial( { color: <span class="hljs-number">0xaaaaaa</span> } ); <span class="hljs-keyword">const</span> ground = <span class="hljs-keyword">new</span> THREE.Mesh( geometry, material ); ground.rotation.x = - <span class="hljs-built_in">Math</span>.PI / <span class="hljs-number">2</span>; ground.position.y = <span class="hljs-number">-10</span>; scene.add(cube); } <span class="hljs-comment">// 动画更新</span> update() { <span class="hljs-keyword">const</span> {scene,camera,renderer,clock} = <span class="hljs-keyword">this</span>; <span class="hljs-keyword">const</span> delta = clock.getDelta() * <span class="hljs-number">60</span>; <span class="hljs-comment">// 启动渲染</span> <span class="hljs-keyword">this</span>.cube.rotation.y += <span class="hljs-number">0.1</span> * delta; renderer.render(scene, camera); } } <span class="hljs-keyword">new</span> WebVRApp();</code></pre> <p><span class="img-wrap"><img data-src="/img/remote/1460000008904031" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="demo示例" title="demo示例" style="cursor: pointer;"></span></p> <p>完整代码:<a href="https://github.com/YoneChen/WebVR-helloworld" rel="nofollow noreferrer" target="_blank">github.com/YoneChen/WebVR-helloworld</a>。</p> <h3 id="articleHeader5">结语</h3> <hr> <p>目前,国外的谷歌、火狐、Facebook和国内百度已推出支持WebVR浏览器的版本,微软也宣布将推出自己的VR浏览器,随着后期5g网络极速时代的到来以及HMD头显的价格和平台的成熟,WebVR的体验方式将是革命性的,用户通过WebVR浏览网上商店,线上教学可进行“面对面”师生交流等,基于这种种应用场景,我们可以找到一个更好的动力去学习WebVR。</p> <h3 id="articleHeader6">参考链接</h3> <hr> <p><a href="http://smus.com/responsive-vr/" rel="nofollow noreferrer" target="_blank">responisve WebVR</a>: 探讨WebVR在不同头显(HMD)的适配方案<br /><a href="https://mozvr.com/#showcase" rel="nofollow noreferrer" target="_blank">MolizaVR example</a>: 火狐WebVR示例<br /><a href="https://github.com/borismus/webvr-boilerplate" rel="nofollow noreferrer" target="_blank">webvr-boilerplate</a>: A starting po<a href="http://www.js-code.com/tag/int" title="int" target="_blank">int</a> <a href="http://www.js-code.com/tag/for" title="for" target="_blank">for</a> web-based VR experiences that work on <a href="http://www.js-code.com/tag/all" title="all" target="_blank">all</a> VR headsets.<br /><a href="https://www.sitepoint.com/how-to-build-vr-on-the-web-today/" rel="nofollow noreferrer" target="_blank">how to build webvr</a>: How to Build VR on the Web Today</p> <p></code></p>

总结

以上是脚本宝典为你收集整理的

VR大潮来袭 —前端开发能做些什么

全部内容,希望文章能够帮你解决

VR大潮来袭 —前端开发能做些什么

所遇到的程序开发问题,欢迎加入QQ群277859234一起讨论学习。如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典网站推荐给程序员好友。 本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。

80%的人都看过