Selaa lähdekoodia

docs: add zh translation for webxr-basics.html (#31575)

This commit adds the Simplified Chinese translation for the WebXR "basics" tutorial page.

The translated file is located at:
manual/zh/webxr-basics.html

This helps improve accessibility for Chinese-speaking developers learning WebXR and Three.js.

Related to #31573
yuangang123 5 kuukautta sitten
vanhempi
sitoutus
9db2595bc9
1 muutettua tiedostoa jossa 278 lisäystä ja 35 poistoa
  1. 278 35
      manual/zh/webxr-basics.html

+ 278 - 35
manual/zh/webxr-basics.html

@@ -1,43 +1,286 @@
-<!DOCTYPE html><html lang="zh"><head>
-    <meta charset="utf-8">
-    <title>VR</title>
-    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-    <meta name="twitter:card" content="summary_large_image">
-    <meta name="twitter:site" content="@threejs">
-    <meta name="twitter:title" content="Three.js – VR">
-    <meta property="og:image" content="https://threejs.org/files/share.png">
-    <link rel="shortcut icon" href="../../files/favicon_white.ico" media="(prefers-color-scheme: dark)">
-    <link rel="shortcut icon" href="../../files/favicon.ico" media="(prefers-color-scheme: light)">
-
-    <link rel="stylesheet" href="../resources/lesson.css">
-    <link rel="stylesheet" href="../resources/lang.css">
-<script type="importmap">
-{
-  "imports": {
-    "three": "../../build/three.module.js"
+<!DOCTYPE html><html lang="zh-CN"><head>
+	<meta charset="utf-8">
+	<title>VR</title>
+	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+	<meta name="twitter:card" content="summary_large_image">
+	<meta name="twitter:site" content="@threejs">
+	<meta name="twitter:title" content="Three.js – VR">
+	<meta property="og:image" content="https://threejs.org/files/share.png">
+	<link rel="shortcut icon" href="../../files/favicon_white.ico" media="(prefers-color-scheme: dark)">
+	<link rel="shortcut icon" href="../../files/favicon.ico" media="(prefers-color-scheme: light)">
+
+	<link rel="stylesheet" href="../resources/lesson.css">
+	<link rel="stylesheet" href="../resources/lang.css">
+	<script type="importmap">
+		{
+		  "imports": {
+			"three": "../../build/three.module.js"
+		  }
+		}
+	</script>
+</head>
+<body>
+<div class="container">
+	<div class="lesson-title">
+		<h1>VR</h1>
+	</div>
+	<div class="lesson">
+		<div class="lesson-main">
+			<p>在 three.js 中制作一个 VR 应用相当简单。你基本上只需要告诉 three.js 你想使用 WebXR。关于 WebXR,有几点应该很容易理解。摄像机的朝向是由 VR 系统提供的,因为用户会转动头部来选择观看的方向。同样,视野范围(field of view)和长宽比也是由 VR 系统提供的,因为每个系统的视野和显示比例都不同。</p>
+			<p>我们来看一个来自<a href="responsive.html">制作响应式网页</a>的示例,并让它支持 VR。</p>
+			<p>在开始之前,你需要一台支持 VR 的设备,比如 Android 智能手机、Google Daydream、Oculus Go、Oculus Rift、Vive、Samsung Gear VR,或者一部安装了<a href="https://apps.apple.com/us/app/webxr-viewer/id1295998056">WebXR 浏览器</a>的 iPhone。</p>
+			<p>接下来,如果你在本地运行,你需要像<a href="setup.html">设置教程</a>中提到的那样运行一个简单的 Web 服务器。</p>
+			<p>如果你用于查看 VR 的设备不是运行服务的同一台电脑,那么你需要通过 https 来访问网页,否则浏览器将不允许使用 WebXR API。<a href="setup.html">设置教程</a>中提到的名为 <a href="https://greggman.github.io/servez" target="_blank">Servez</a> 的服务器支持启用 https。勾选该选项并启动服务器。</p>
+			<div class="threejs_center"><img src="../resources/images/servez-https.png" class="nobg" style="width: 912px;"></div>
+			<p>请注意 URL,你需要使用你电脑的本地 IP 地址。它通常会以 <code class="notranslate" translate="no">192</code>、<code class="notranslate" translate="no">172</code> 或 <code class="notranslate" translate="no">10</code> 开头。在 VR 设备的浏览器中输入完整地址,包括 <code class="notranslate" translate="no">https://</code> 部分。注意:你的电脑和 VR 设备必须在同一个本地网络或 WiFi 上,并且最好是在家庭网络中。注意:许多咖啡馆的网络配置不允许设备间直接通信。</p>
+			<p>你可能会看到如下图所示的错误提示。点击“高级”,然后点击<em>继续</em>。</p>
+			<div class="threejs_center"><img src="../resources/images/https-warning.gif"></div>
+			<p>现在你可以运行示例代码了。</p>
+			<p>如果你打算真正进行 WebXR 开发,你还应该了解一下 <a href="https://developers.google.com/web/tools/chrome-devtools/remote-debugging/">远程调试</a>,这样你就可以查看控制台警告、错误,当然也可以<a href="debugging-javascript.html">调试你的代码</a>。</p>
+			<p>如果你只是想看看下面的代码是否可运行,你可以直接在本网站运行它。</p>
+			<p>我们首先需要在引入 three.js 之后引入对 VR 的支持:</p>
+			<pre class="prettyprint showlinemods notranslate lang-js" translate="no">import * as THREE from 'three';
++import {VRButton} from 'three/addons/webxr/VRButton.js';  // 引入 VR 按钮模块
+</pre>
+			<p>然后我们需要启用 three.js 的 WebXR 支持,并将 VR 按钮添加到页面中:</p>
+			<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function main() {
+  const canvas = document.querySelector('#c');
+  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
++  renderer.xr.enabled = true;  // 启用 WebXR 支持
++  document.body.appendChild(VRButton.createButton(renderer));  // 将 VR 按钮添加到页面
+</pre>
+			<p>我们需要让 three.js 来运行渲染循环。在此之前我们一直使用 <code class="notranslate" translate="no">requestAnimationFrame</code> 循环,但为了支持 VR,我们需要让 three.js 自己控制渲染循环。我们可以调用 <a href="/docs/#api/en/renderers/WebGLRenderer.setAnimationLoop"><code class="notranslate" translate="no">WebGLRenderer.setAnimationLoop</code></a> 并传入一个回调函数来实现:</p>
+			<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render(time) {
+  time *= 0.001;
+
+  if (resizeRendererToDisplaySize(renderer)) {
+    const canvas = renderer.domElement;
+    camera.aspect = canvas.clientWidth / canvas.clientHeight;
+    camera.updateProjectionMatrix();
   }
+
+  cubes.forEach((cube, ndx) =&gt; {
+    const speed = 1 + ndx * .1;
+    const rot = time * speed;
+    cube.rotation.x = rot;
+    cube.rotation.y = rot;
+  });
+
+  renderer.render(scene, camera);
+
+-  requestAnimationFrame(render);  // 原来的 requestAnimationFrame 被移除
 }
-</script>
-    <link rel="stylesheet" href="/manual/zh/lang.css">
-  </head>
-  <body>
-    <div class="container">
-      <div class="lesson-title">
-        <h1>VR</h1>
-      </div>
-      <div class="lesson">
-        <div class="lesson-main">
-          <p>抱歉,还没有中文翻译哦。 <a href="https://github.com/mrdoob/three.js">欢迎加入翻译</a>! 😄</p>
-<p><a href="/manual/en/webxr.html">英文原文链接</a>.</p>
 
-        </div>
-      </div>
-    </div>
+-requestAnimationFrame(render);  // 原调用被注释
++renderer.setAnimationLoop(render);  // 改为使用 WebXR 的渲染循环方式
+</pre>
+			<p>还有一个细节:我们最好设置一个摄像机的高度,使其符合站立用户的平均视角高度。</p>
+			<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
++camera.position.set(0, 1.6, 0);  // 设置摄像机高度为 1.6 米,符合站立用户的平均视角
+</pre>
+			<p>并将立方体上移,使其位于摄像机前方:</p>
+			<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const cube = new THREE.Mesh(geometry, material);
+scene.add(cube);
+
+cube.position.x = x;
++cube.position.y = 1.6;  // 与摄像机高度一致
++cube.position.z = -2;  // 放置在摄像机前方 2 米处
+</pre>
+			<p>我们将 z 设置为 <code class="notranslate" translate="no">-2</code>,因为摄像机现在位于 <code class="notranslate" translate="no">z = 0</code>,默认朝向 -z 轴方向。</p>
+			<p>这引出了一个非常重要的点:<strong>VR 中的单位是以米为单位</strong>。换句话说,<strong>一个单位 = 一米</strong>。这意味着摄像机在距离地面 1.6 米的位置,立方体的中心位于摄像机前方 2 米处。每个立方体的大小是 1x1x1 米。这一点非常关键,因为 VR 需要将虚拟世界中的尺寸与用户在现实世界中的动作相匹配。</p>
+			<p>现在,我们应该可以在摄像机前方看到三个旋转的立方体,并且有一个进入 VR 的按钮。</p>
+			<p></p><div translate="no" class="threejs_example_container notranslate">
+			<div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/webxr-basic.html"></iframe></div>
+			<a class="threejs_center" href="/manual/examples/webxr-basic.html" target="_blank">点击此处在新窗口中打开</a>
+		</div>
+
+			<p></p>
+			<p>我发现 VR 效果更好一些时,是摄像机周围有一些参考物,比如一个房间。因此我们来添加一个简单的网格立方体贴图,就像我们在<a href="backgrounds.html">背景文章</a>中讲到的那样。我们会使用相同的网格纹理贴图在立方体的每一面上,这样可以创建一个“网格房间”。</p>
+			<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const scene = new THREE.Scene();
++{
++  const loader = new THREE.CubeTextureLoader();  // 创建立方体贴图加载器
++  const texture = loader.load([
++    'resources/images/grid-1024.png',  // 六个面的纹理都用同一张图
++    'resources/images/grid-1024.png',
++    'resources/images/grid-1024.png',
++    'resources/images/grid-1024.png',
++    'resources/images/grid-1024.png',
++    'resources/images/grid-1024.png',
++  ]);
++  scene.background = texture;  // 设置场景背景为加载的立方体贴图
++}
+</pre>
+			<p>这样看起来会更好一些。</p>
+
+			<p></p><div translate="no" class="threejs_example_container notranslate">
+			<div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/webxr-basic-w-background.html"></iframe></div>
+			<a class="threejs_center" href="/manual/examples/webxr-basic-w-background.html" target="_blank">点击此处在新窗口中打开</a>
+		</div>
+
+			<p></p>
+			<p>注意:要实际看到 VR 效果,你需要一台兼容 WebXR 的设备。我相信大多数 Android 手机在使用 Chrome 或 Firefox 时都支持 WebXR。至于 iOS,你也许可以使用这个 <a href="https://apps.apple.com/us/app/webxr-viewer/id1295998056">WebXR 应用</a>,但总体上 WebXR 在 iOS 上的支持在 2019 年 5 月时仍处于不支持状态。</p>
+			<p>在 Android 或 iPhone 上使用 WebXR,你需要一个<em>手机专用的 VR 头显</em>。你可以以很便宜的价格购买,比如用纸板做的只需约 5 美元,高端一些的可能需要 100 美元左右。不幸的是,我也不清楚该推荐哪款产品。我这些年买过 6 个设备,质量参差不齐,最贵的也没超过 25 美元。</p>
+			<p>以下是一些可能遇到的问题:</p>
+			<ol>
+				<li><p>是否适配你的手机尺寸</p>
+					<p>手机尺寸各异,因此 VR 头显需要与之匹配。很多头显声称支持多种尺寸。从我的经验来看,适配尺寸越多,实际效果越差,因为它们不得不在多个尺寸之间做出妥协。不幸的是,支持多尺寸的头显是最常见的类型。</p>
+				</li>
+				<li><p>是否能够调节焦距以适配你的脸型</p>
+					<p>有些设备的可调节性更强。通常最多提供两种调节方式:镜片与眼睛之间的距离,以及两只眼睛之间的镜片间距。</p>
+				</li>
+				<li><p>镜片是否太反光</p>
+					<p>许多头显的镜片连接区域是一段塑料通道。如果这些塑料材质是光滑或反光的,那么它会像镜子一样反射屏幕内容,造成强烈干扰。</p>
+					<p>几乎没有评论会提及这个问题。</p>
+				</li>
+				<li><p>佩戴是否舒适</p>
+					<p>大多数设备像眼镜一样压在鼻梁上。几分钟后可能就会感觉不适。有些设备配有环绕头部的固定带,有些还有一条从上方穿过头顶的第三条带子。这些可能或可能不会起到将设备固定在合适位置的作用。</p>
+					<p>事实是,对大多数(甚至所有)设备来说,眼睛必须正对镜片中心。如果镜片略微偏高或偏低,图像就会变模糊。这可能非常令人沮丧,因为一开始图像是清晰的,但使用 45 到 60 秒后设备稍微移位 1 毫米,你会突然发现自己在努力看一个模糊的图像。</p>
+				</li>
+				<li><p>是否支持眼镜</p>
+					<p>如果你戴眼镜,你需要查看评论确认该设备是否支持眼镜佩戴。</p>
+				</li>
+			</ol>
+			<p>很遗憾,我没法给出推荐。<a href="https://vr.google.com/cardboard/get-cardboard/">Google 提供了一些便宜的纸板 VR 眼镜建议</a>,有些仅需 5 美元左右,不妨从那里开始尝试。如果你喜欢这个体验,再考虑升级。5 美元也就一杯咖啡的钱,试一试也无妨!</p>
+			<p>VR 设备大致可以分为 3 种类型:</p>
+			<ol>
+				<li><p>三自由度(3DoF),无输入设备</p>
+					<p>这通常指的是手机类设备,尽管有时也可以购买第三方输入设备。所谓三自由度是指你可以上下转头(1)、左右转头(2)、以及左右倾斜头部(3)。</p>
+				</li>
+
+				<li><p>三自由度(3DoF)+ 一个三自由度输入设备</p>
+					<p>这类设备包括 Google Daydream 和 Oculus GO。</p>
+					<p>它们同样支持三自由度,并配有一个小型控制器,在 VR 中像激光指针一样使用。激光指针本身也只有三自由度,系统只能识别它的指向方向,不能识别它的位置。</p>
+				</li>
+
+				<li><p>六自由度(6DoF)+ 六自由度输入设备</p>
+					<p>这些是<em>真正的 VR 设备</em>(哈哈)。六自由度意味着设备不仅知道你头部的朝向,还知道你头部的实际位置。这意味着你左右移动、前后移动、或坐下/站起,设备都能感知并在 VR 中进行同步。</p>
+					<p>体验非常真实,令人惊艳。在一个好的演示中你可能会被震撼到,我至今仍然会被打动。</p>
+					<p>此外,这类设备通常配有两个控制器,分别对应左右手。系统可以准确识别你双手的位置和朝向,因此你可以在 VR 中通过触摸、推动、扭动等手势操作物体。</p>
+					<p>支持六自由度的设备包括 Vive、Vive Pro、Oculus Rift、Quest 以及我相信所有 Windows MR 设备。</p>
+				</li>
+			</ol>
+
+			<p>讲了这么多,我也不能完全确认哪些设备确实能与 WebXR 配合使用。但我 99% 确信,大多数 Android 手机在使用 Chrome 时是可以的。你可能需要在 <a href="about:flags"><code class="notranslate" translate="no">about:flags</code></a> 中启用 WebXR 支持。我也知道 Google Daydream 是可用的,同样需要在 <a href="about:flags"><code class="notranslate" translate="no">about:flags</code></a> 中启用支持。Oculus Rift、Vive、Vive Pro 可以通过 Chrome 或 Firefox 使用。我对 Oculus Go 和 Oculus Quest 不太确定,因为它们使用的是定制操作系统,但根据网络信息,它们似乎也是可以的。</p>
+
+			<p>好了,介绍完 VR 设备和 WebXR,我们继续讲其他内容。</p>
+
+			<ul>
+				<li><p>同时支持 VR 和 非 VR 模式</p>
+					<p>据我所知(截至 r112 版本),three.js 并没有提供一个简单的方法来同时支持 VR 和非 VR 模式。理想情况下,如果不处于 VR 模式,我们希望可以使用任何方式控制摄像机,例如使用 <a href="/docs/#examples/controls/OrbitControls"><code class="notranslate" translate="no">OrbitControls</code></a>,并且在切换进出 VR 模式时可以接收到事件,以便启用或禁用控制器。</p>
+				</li>
+			</ul>
+
+			<p>如果 future 的 three.js 添加了支持,我会尝试更新本文。在此之前,你可能需要制作两个版本的页面,或者在 URL 中传入一个标记参数,例如:</p>
+			<pre class="prettyprint showlinemods notranslate notranslate" translate="no">https://mysite.com/mycooldemo?allowvr=true
+</pre>
+			<p>然后我们可以加一些链接来切换模式:</p>
+			<pre class="prettyprint showlinemods notranslate lang-html" translate="no">&lt;body&gt;
+  &lt;canvas id="c"&gt;&lt;/canvas&gt;
++  &lt;div class="mode"&gt;
++    &lt;a href="?allowvr=true" id="vr"&gt;启用 VR 模式&lt;/a&gt;
++    &lt;a href="?" id="nonvr"&gt;使用非 VR 模式&lt;/a&gt;
++  &lt;/div&gt;
+&lt;/body&gt;
+</pre>
+
+			<p>并加上一些 CSS 来定位这些链接:</p>
+			<pre class="prettyprint showlinemods notranslate lang-css" translate="no">body {
+    margin: 0;
+}
+#c {
+    width: 100%;
+    height: 100%;
+    display: block;
+}
++.mode {
++  position: absolute;
++  right: 1em;  /* 右上角显示 */
++  top: 1em;
++}
+</pre>
+
+			<p>你可以在代码中这样读取参数:</p>
+			<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function main() {
+  const canvas = document.querySelector('#c');
+  const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
+-  renderer.xr.enabled = true;
+-  document.body.appendChild(VRButton.createButton(renderer));
+
+  const fov = 75;
+  const aspect = 2;  // canvas 默认宽高比
+  const near = 0.1;
+  const far = 5;
+  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
+  camera.position.set(0, 1.6, 0);
+
++  const params = (new URL(document.location)).searchParams;
++  const allowvr = params.get('allowvr') === 'true';  // 从 URL 中读取 allowvr 参数
++  if (allowvr) {
++    renderer.xr.enabled = true;
++    document.body.appendChild(VRButton.createButton(renderer));
++    document.querySelector('#vr').style.display = 'none';  // 隐藏“启用 VR”按钮
++  } else {
++    // 非 VR 模式,添加控制器
++    const controls = new OrbitControls(camera, canvas);
++    controls.target.set(0, 1.6, -2);
++    controls.update();
++    document.querySelector('#nonvr').style.display = 'none';  // 隐藏“非 VR 模式”按钮
++  }
+</pre>
+
+			<p>这到底好不好我也说不准。我感觉 VR 模式和非 VR 模式之间所需的实现差异通常非常大,
+				所以除了最简单的应用场景外,或许制作两个单独的页面会更合适?你需要自己决定。</p>
+
+			<p>注意:由于种种原因,这段代码在本网站的在线编辑器中是无法运行的,
+				所以如果你想试试看,可以<a href="../examples/webxr-basic-vr-optional.html" target="_blank">点击这里</a>。
+				页面会以非 VR 模式启动,你可以用鼠标或手指来移动摄像机。
+				点击“允许 VR”按钮后,页面会切换为支持 VR 模式,
+				如果你使用的是 VR 设备,就可以点击“进入 VR”按钮。</p>
+			<ul>
+				<li>
+					<p>决定支持哪种等级的 VR 设备</p>
+					<p>上文我们介绍了三种类型的 VR 设备。</p>
+
+					<ul>
+						<li>3DOF 无输入设备</li>
+						<li>3DOF + 3DOF 输入设备</li>
+						<li>6DOF + 6DOF 输入设备</li>
+					</ul>
+
+					<p>你需要决定你愿意投入多少精力来支持每种类型的设备。</p>
+
+					<p>例如,对于最简单的无输入设备,你能做的通常就是在用户视野中放置一些按钮或物体,
+						当用户将视图中心的某个指示器对准这些物体大约 0.5 秒时,就触发点击。
+						常见的用户体验方式是在目标物体上显示一个小型的计时圈,
+						表示“如果你继续把视线保持在这里一会儿,这个按钮将被选中”。</p>
+
+					<p>由于没有其他输入方式,这已经是你能做的最好的交互方式了。</p>
+
+					<p>下一级别是用户拥有一个 3DOF 的输入设备。通常它可以用来指向目标,
+						并且用户至少有两个按钮可以使用。Daydream 控制器还有一个触控板,
+						可以提供常规的触摸输入。</p>
+
+					<p>无论如何,如果用户使用这类设备,让他们使用控制器指向目标,
+						会比强迫他们通过头部移动去“看”目标舒适得多。</p>
 
-  <script src="../resources/prettify.js"></script>
-  <script src="../resources/lesson.js"></script>
+					<p>一个类似等级的设备可能是 3DOF 或 6DOF 的头显配合游戏手柄使用。
+						你需要自己决定该如何支持这种情况。常见的方式是用户仍然需要转头瞄准目标,
+						而手柄只是用来触发按钮。</p>
 
+					<p>最后一个层级是使用 6DOF 头显配合两个 6DOF 控制器的用户。
+						对于这类用户来说,如果你的应用只有 3DOF 的交互,
+						往往会让他们感到沮丧。同样,他们通常期望能够在 VR 中用手操作物体,
+						你需要决定是否要支持这种高度自由的交互方式。</p>
+				</ul>
 
+				<p>如你所见,入门 VR 开发相对简单,但如果你真的想做出一个可发布的 VR 应用,
+					那就需要大量的决策和设计。</p>
 
+				<p>这篇文章只是使用 three.js 进行 VR 开发的简要介绍。
+					我们将在 <a href="webxr-look-to-select.html">后续文章</a> 中介绍各种输入方式。</p>
+		</div>
+	</div>
+</div>
 
-</body></html>
+<script src="../resources/prettify.js"></script>
+<script src="../resources/lesson.js"></script>

粤ICP备19079148号