-
-
Notifications
You must be signed in to change notification settings - Fork 35.7k
/
Copy pathdebugging-javascript.html
446 lines (410 loc) · 39.5 KB
/
debugging-javascript.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
<!DOCTYPE html><html lang="ru"><head>
<meta charset="utf-8">
<title>Отладка JavaScript</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 – Отладка JavaScript">
<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>Отладка JavaScript</h1>
</div>
<div class="lesson">
<div class="lesson-main">
<p>Большая часть этой статьи посвящена не непосредственно
THREE.js, а скорее об отладке JavaScript в целом.
Мне показалось важным, что многие люди, начинающие с THREE.js,
также начинают с JavaScript, поэтому я надеюсь, что это поможет
им легче решать любые возникающие проблемы. </p>
<p>Отладка - большая тема, и я, вероятно, не смогу охватить все, что нужно знать, но если вы новичок в JavaScript,
вот несколько советов. Я настоятельно рекомендую вам потратить некоторое время на их изучение. Они очень помогут вам в вашем обучении. </p>
<h2 id="-">Изучите инструменты разработчика вашего браузера</h2>
<p>Все браузеры имеют инструменты разработчика.
<a href="https://developers.google.com/web/tools/chrome-devtools/">Chrome</a>,
<a href="https://developer.mozilla.org/en-US/docs/Tools">Firefox</a>,
<a href="https://developer.apple.com/safari/tools/">Safari</a>,
<a href="https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide">Edge</a>.</p>
<p>В Chrome вы можете кликнуть значок <code class="notranslate" translate="no">⋮</code> , выбрать More Tools->Developer Tools
чтобы перейти к инструментам разработчика. Сочетание клавиш также показано там. </p>
<div class="threejs_center"><img class="border" src="../resources/images/devtools-chrome.jpg" style="width: 789px;"></div>
<p>В Firefox вы кликаете значок <code class="notranslate" translate="no">☰</code> , выбираете "Web Developer", затем выбираете
"Toggle Tools"</p>
<div class="threejs_center"><img class="border" src="../resources/images/devtools-firefox.jpg" style="width: 786px;"></div>
<p>В Safari сначала необходимо включить меню «Разработка» в разделе
«Дополнительные настройки Safari».</p>
<div class="threejs_center"><img class="border" src="../resources/images/devtools-enable-safari.jpg" style="width: 775px;"></div>
<p>Затем в меню «Разработка» вы можете выбрать «Показать / подключить веб-инспектора». </p>
<div class="threejs_center"><img class="border" src="../resources/images/devtools-safari.jpg" style="width: 777px;"></div>
<p>С Chrome вы также можете
<a href="https://developers.google.com/web/tools/chrome-devtools/remote-debugging/">использовать Chrome на своем компьютере для отладки веб-страниц, работающих на Chrome, на вашем телефоне или планшете Android</a>.
Точно так же с Safari вы можете
<a href="https://www.google.com/search?q=safari+remote+debugging+ios">использовать свой компьютер для отладки веб-страниц, работающих в Safari на iPhone и iPad</a>.</p>
<p>Я наиболее знаком с Chrome, поэтому в этом руководстве будет использоваться Chrome в качестве примера при обращении к инструментам,
но большинство браузеров имеют схожие функции, поэтому здесь должно быть легко применить что-либо для всех браузеров. </p>
<h2 id="-">Выключить кеш</h2>
<p>Браузеры пытаются повторно использовать уже загруженные данные. Это очень удобно для пользователей,
поэтому, если вы заходите на веб-сайт во второй раз, многие файлы, используемые для отображения сайта, больше не будут загружаться. </p>
<p>С другой стороны, это может быть плохо для веб-разработки.
Вы изменяете файл на своем компьютере, перезагружаете страницу
и не видите изменений, потому что браузер использует версию, полученную в прошлый раз. </p>
<p>Сначала выберите настройки из углового меню </p>
<div class="threejs_center"><img class="border" src="../resources/images/devtools-chrome-settings.jpg" style="width: 778px"></div>
<p>Затем выберите "Отключить кэш (пока открыт DevTools)".</p>
<div class="threejs_center"><img class="border" src="../resources/images/devtools-chrome-disable-cache.jpg" style="width: 779px"></div>
<h2 id="-javascript">Используйте консоль JavaScript</h2>
<p>Внутри всех devtools есть <em>консоль</em>. Показывает предупреждения и сообщения об ошибках. </p>
<p><strong> ЧИТАЙТЕ СООБЩЕНИЯ!! </strong></p>
<p>Обычно должно быть только 1 или 2 сообщения. </p>
<div class="threejs_center"><img class="border" src="../resources/images/devtools-no-errors.jpg" style="width: 779px"></div>
<p>Если вы видите какие-либо другие <strong>ПРОЧИТАЙТЕ ИХ</strong>. Например:</p>
<div class="threejs_center"><img class="border" src="../resources/images/devtools-errors.jpg" style="width: 779px"></div>
<p>Я неправильно написал «three» как «threee» </p>
<p>Вы также можете распечатать свою собственную информацию на консоли с помощью <code class="notranslate" translate="no">console.log</code>, как в</p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">console.log(someObject.position.x, someObject.position.y, someObject.position.z);
</pre>
<p>Даже круче, если вы регистрируете объект, вы можете инспектировать его. Например, если мы регистрируем объект корневой сцены из <a href="load-gltf.html">статьи gLTF</a></p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no"> {
const gltfLoader = new GLTFLoader();
gltfLoader.load('resources/models/cartoon_lowpoly_small_city_free_pack/scene.gltf', (gltf) => {
const root = gltf.scene;
scene.add(root);
+ console.log(root);
</pre>
<p>Затем мы можем развернуть этот объект в консоли JavaScript </p>
<div class="threejs_center"><img class="border" src="../resources/images/devtools-console-object.gif"></div>
<p>Вы также можете использовать <code class="notranslate" translate="no">console.error</code>, который сообщает, что сообщение красным цветом включает в себя трассировку стека.</p>
<h2 id="-">Поместить данные на экран</h2>
<p>Другой очевидный, но часто упускаемый из виду способ - добавить теги <code class="notranslate" translate="no"><div></code> или <code class="notranslate" translate="no"><pre></code> и поместить в них данные. </p>
<p>Самый очевидный способ - сделать некоторые элементы HTML </p>
<pre class="prettyprint showlinemods notranslate lang-html" translate="no"><canvas id="c"></canvas>
+<div id="debug">
+ <div>x:<span id="x"></span></div>
+ <div>y:<span id="y"></span></div>
+ <div>z:<span id="z"></span></div>
+</div>
</pre>
<p>Разместите стиле вверху холста. (при условии, что ваш холст заполняет страницу)</p>
<pre class="prettyprint showlinemods notranslate lang-html" translate="no"><style>
#debug {
position: absolute;
left: 1em;
top: 1em;
padding: 1em;
background: rgba(0, 0, 0, 0.8);
color: white;
font-family: monospace;
}
</style>
</pre>
<p>А затем найдите элементы и настройте их содержимое.</p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">// at init time
const xElem = document.querySelector('#x');
const yElem = document.querySelector('#y');
const zElem = document.querySelector('#z');
// at render or update time
xElem.textContent = someObject.position.x.toFixed(3);
yElem.textContent = someObject.position.y.toFixed(3);
zElem.textContent = someObject.position.z.toFixed(3);
</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/debug-js-html-elements.html"></iframe></div>
<a class="threejs_center" href="/manual/examples/debug-js-html-elements.html" target="_blank">нажмите здесь, чтобы открыть в отдельном окне</a>
</div>
<p></p>
<p>Еще один способ вывести данные на экран - это очистить регистратор.
Я только что придумал этот термин, но многие игры, над которыми я работал,
использовали это решение. Идея в том, что у вас есть буфер, который
отображает сообщения только для одного кадра. Любая часть вашего кода, которая хочет отображать данные,
вызывает некоторую функцию для добавления данных в этот буфер каждый кадр.
Это гораздо меньше работы, чем создание элемента на часть данных выше. </p>
<p>Например, давайте изменим HTML сверху только на это</p>
<pre class="prettyprint showlinemods notranslate lang-html" translate="no"><canvas id="c"></canvas>
<div id="debug">
<pre></pre>
</div>
</pre>
<p>И давайте создадим простой класс для управления этим <em>буфером очистки</em>.</p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">class ClearingLogger {
constructor(elem) {
this.elem = elem;
this.lines = [];
}
log(...args) {
this.lines.push([...args].join(' '));
}
render() {
this.elem.textContent = this.lines.join('\n');
this.lines = [];
}
}
</pre>
<p>Тогда давайте сделаем простой пример, который каждый раз, когда мы щелкаем мышью,
создает сетку, которая движется в произвольном направлении в течение 2 секунд.
Мы начнем с одного из примеров из статьи о <a href="responsive.html">том, как сделать вещи отзывчивыми</a></p>
<p>Вот код, который добавляет новую сетку каждый раз, когда мы щелкаем мышью</p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const geometry = new THREE.SphereGeometry();
const material = new THREE.MeshBasicMaterial({color: 'red'});
const things = [];
function rand(min, max) {
if (max === undefined) {
max = min;
min = 0;
}
return Math.random() * (max - min) + min;
}
function createThing() {
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
things.push({
mesh,
timer: 2,
velocity: new THREE.Vector3(rand(-5, 5), rand(-5, 5), rand(-5, 5)),
});
}
canvas.addEventListener('click', createThing);
</pre>
<p>А вот код, который перемещает созданные нами meshes, регистрирует их и удаляет их, когда у них заканчивается таймер </p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const logger = new ClearingLogger(document.querySelector('#debug pre'));
let then = 0;
function render(now) {
now *= 0.001; // convert to seconds
const deltaTime = now - then;
then = now;
...
logger.log('fps:', (1 / deltaTime).toFixed(1));
logger.log('num things:', things.length);
for (let i = 0; i < things.length;) {
const thing = things[i];
const mesh = thing.mesh;
const pos = mesh.position;
logger.log(
'timer:', thing.timer.toFixed(3),
'pos:', pos.x.toFixed(3), pos.y.toFixed(3), pos.z.toFixed(3));
thing.timer -= deltaTime;
if (thing.timer <= 0) {
// remove this thing. Note we don't advance `i`
things.splice(i, 1);
scene.remove(mesh);
} else {
mesh.position.addScaledVector(thing.velocity, deltaTime);
++i;
}
}
renderer.render(scene, camera);
logger.render();
requestAnimationFrame(render);
}
</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/debug-js-clearing-logger.html"></iframe></div>
<a class="threejs_center" href="/manual/examples/debug-js-clearing-logger.html" target="_blank">нажмите здесь, чтобы открыть в отдельном окне</a>
</div>
<p></p>
<h2 id="-">Параметры запроса</h2>
<p>Следует также помнить, что на веб-страницах могут передаваться данные либо через параметры запроса, либо через привязку, иногда называемую поиском и хэшем.</p>
<pre class="prettyprint showlinemods notranslate notranslate" translate="no">https://domain/path/?query#anchor
</pre><p>Вы можете использовать это, чтобы сделать функции необязательными или передать параметры.</p>
<p>Например, давайте возьмем предыдущий пример и сделаем так, чтобы материал отладки отображался только в том случае, если мы добавили <code class="notranslate" translate="no">?debug=true</code> в URL.</p>
<p>Сначала нам нужен код для разбора строки запроса</p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">/**
* Returns the query parameters as a key/value object.
* Example: If the query parameters are
*
* abc=123&def=456&name=gman
*
* Then `getQuery()` will return an object like
*
* {
* abc: '123',
* def: '456',
* name: 'gman',
* }
*/
function getQuery() {
return Object.fromEntries(new URLSearchParams(window.location.search).entries());
}
</pre>
<p>Тогда мы можем сделать элемент отладки скрытым по умолчанию</p>
<pre class="prettyprint showlinemods notranslate lang-html" translate="no"><canvas id="c"></canvas>
+<div id="debug" style="display: none;">
<pre></pre>
</div>
</pre>
<p>Затем в коде мы читаем параметры и выбираем не скрывать отладочную информацию тогда и только тогда, когда передается <code class="notranslate" translate="no">?debug=true</code></p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">const query = getQuery();
const debug = query.debug === 'true';
const logger = debug
? new ClearingLogger(document.querySelector('#debug pre'))
: new DummyLogger();
if (debug) {
document.querySelector('#debug').style.display = '';
}
</pre>
<p>Мы также создали <code class="notranslate" translate="no">DummyLogger</code>, который ничего не делает, и решили использовать его, если <code class="notranslate" translate="no">?debug=true</code> не был передан. </p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">class DummyLogger {
log() {}
render() {}
}
</pre>
<p>Вы можете увидеть, если мы используем этот URL:</p>
<p><a target="_blank" href="../examples/debug-js-params.html">debug-js-params.html</a></p>
<p>отладочной информации нет, но если мы используем этот URL:</p>
<p><a target="_blank" href="../examples/debug-js-params.html?debug=true">debug-js-params.html?debug=true</a></p>
<p>есть отладочная информация..</p>
<p>Несколько параметров можно передать, разделив их символом '&' как в <code class="notranslate" translate="no">somepage.html?someparam=somevalue&someotherparam=someothervalue</code>.
Используя такие параметры, мы можем передавать все виды опций. Может быть <code class="notranslate" translate="no">speed=0.01</code> чтобы замедлить наше приложение для облегчения понимания чего-либо, или <code class="notranslate" translate="no">showHelpers=true</code>
для того, чтобы добавлять или нет помощников, которые показывают свет, тень или усечение камеры, рассматриваемые в других уроках. </p>
<h2 id="-">Научитесь пользоваться отладчиком</h2>
<p>В каждом браузере есть отладчик, в котором вы можете останавливать
вашу программу шаг за шагом и проверять все переменные. </p>
<p>Обучение тому, как использовать отладчик - слишком большая тема для этой статьи, но вот несколько ссылок </p>
<ul>
<li><a href="https://developers.google.com/web/tools/chrome-devtools/javascript/">Get Started with Debugging JavaScript in Chrome DevTools</a></li>
<li><a href="https://javascript.info/debugging-chrome">Debugging in Chrome</a></li>
<li><a href="https://hackernoon.com/tips-and-tricks-for-debugging-in-chrome-developer-tools-458ade27c7ab">Tips and Tricks for Debugging in Chrome Developer Tools</a></li>
</ul>
<h2 id="-nan-">Проверьте <code class="notranslate" translate="no">NaN</code> в отладчике или в другом месте</h2>
<p><code class="notranslate" translate="no">NaN</code> это сокращение от Not A Number.
Это то, что JavaScript будет назначать в качестве значения, когда вы делаете что-то, что не имеет смысла математически. </p>
<p>В качестве простого примера</p>
<div class="threejs_center"><img class="border" src="../resources/images/nan-banana.png" style="width: 180px;"></div>
<p>Часто, когда я что-то делаю и на экране ничего не появляется,
я проверяю некоторые значения, и если я вижу <code class="notranslate" translate="no">NaN</code>, имеет место быть, чтобы начать поиск. </p>
<p>В качестве примера, когда я впервые начал создавать путь для
<a href="load-gltf.html">статьи о загрузке файлов gLTF</a> я сделал кривую, используя класс <a href="/docs/#api/en/extras/curves/SplineCurve"><code class="notranslate" translate="no">SplineCurve</code></a>, который создает 2D-кривую. </p>
<p>Затем я использовал эту кривую, чтобы двигать автомобили</p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">curve.getPointAt(zeroToOnePointOnCurve, car.position);
</pre>
<p>Внутренне <code class="notranslate" translate="no">curve.getPointAt</code> вызывает функцию <code class="notranslate" translate="no">set</code> для объекта, переданного в качестве второго аргумента.
В этом случае вторым аргументом является <code class="notranslate" translate="no">car.position</code>, который является <a href="/docs/#api/en/math/Vector3"><code class="notranslate" translate="no">Vector3</code></a>.
Функция <code class="notranslate" translate="no">set</code> в <a href="/docs/#api/en/math/Vector3"><code class="notranslate" translate="no">Vector3</code></a> требует 3 аргумента, x, y и z, но <a href="/docs/#api/en/extras/curves/SplineCurve"><code class="notranslate" translate="no">SplineCurve</code></a> является 2D-кривой и поэтому вызывает <code class="notranslate" translate="no">car.position.set</code> только с x и y. </p>
<p>В результате <code class="notranslate" translate="no">car.position.set</code> устанавливает x в x, y в y, а z в <code class="notranslate" translate="no">undefined</code>.</p>
<p>Беглый взгляд в отладчике <code class="notranslate" translate="no">matrixWorld</code> автомобиля
показал множество значений <code class="notranslate" translate="no">NaN</code>. </p>
<div class="threejs_center"><img class="border" src="../resources/images/debugging-nan.gif" style="width: 476px;"></div>
<p>Видя, что в матрице присутствуют <code class="notranslate" translate="no">NaN</code> можно предположить что-то вроде <code class="notranslate" translate="no">position</code>,
<code class="notranslate" translate="no">rotation</code>, <code class="notranslate" translate="no">scale</code> или какой-либо другой функции, которая влияет на то, что в матрице содержались неверные данные.
Работая в обратном направлении, было легко отследить проблему. </p>
<p>В верхней части <code class="notranslate" translate="no">NaN</code> есть также <code class="notranslate" translate="no">Infinity</code>, что является аналогичным признаком того, что где-то есть математическая ошибка. </p>
<h2 id="-">Смотри в коде!</h2>
<p>THREE.js является открытым исходным кодом. Не бойтесь заглянуть внутрь кода! Вы можете заглянуть внутрь на <a href="https://github.com/mrdoob/three.js">github</a>.
Вы также можете заглянуть внутрь, войдя в функции в отладчике.
Когда вы сделаете это, рассмотрите возможность использования <code class="notranslate" translate="no">three.js</code> вместо более распространенного <code class="notranslate" translate="no">three.min.js</code>.
<code class="notranslate" translate="no">three.min.js</code> - уменьшенная, сжатая и поэтому уменьшенная для загрузки версия. <code class="notranslate" translate="no">three.js</code> - более крупная, но более простая в отладке версия.
Я часто переключаю свой код на использование <code class="notranslate" translate="no">three.js</code>, чтобы пройтись по коду и посмотреть, что происходит. </p>
<h2 id="-requestanimationframe-">Поместите <code class="notranslate" translate="no">requestAnimationFrame</code> внизу вашей функции рендеринга.</h2>
<p>Я часто вижу эту закономерность</p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render() {
requestAnimationFrame(render);
// -- do stuff --
renderer.render(scene, camera);
}
requestAnimationFrame(render);
</pre>
<p>Я бы предложил поместить вызов <code class="notranslate" translate="no">requestAnimationFrame</code> внизу, как в</p>
<pre class="prettyprint showlinemods notranslate lang-js" translate="no">function render() {
// -- do stuff --
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
</pre>
<p>Основная причина в том, что ваш код остановится – возникновение ошибки.
Помещение <code class="notranslate" translate="no">requestAnimationFrame</code> вверху означает, что ваш код будет продолжать работать,
даже если у вас есть ошибка, так как вы уже запросили другой кадр. Лучше найти эти ошибки, чем игнорировать их.
Они могут быть причиной того, что что-то не появляется так, как вы ожидаете, но если ваш код не остановится, вы можете даже не заметить. </p>
<h2 id="-">Проверьте свои единицы!</h2>
<p>Это в основном означает понимание, например, когда использовать градусы, а когда использовать радианы.
К сожалению, THREE.js не использует везде одинаковые единицы измерения. Всё что в
поле зрении камеры - в градусах. Все остальные углы указаны в радианах. </p>
<p>Другое место, на которое стоит обратить внимание - ваши единицы измерения.
До недавнего времени 3D-приложения могли выбирать любую единицу измерения, который они хотели.
Одно приложение может выбрать 1 единицу = 1 см. Другой может выбрать 1 единицу = 1 фут.
На самом деле все еще верно, что вы можете выбрать любые единицы измерения для определенных приложений.
Тем не менее, THREE.js предполагает 1 единицу = 1 метр. Это важно для таких вещей, как физический рендеринг с использованием метров для вычисления световых эффектов.
Это также важно для AR и VR, которые должны иметь дело с реальными устройствами, такими как ваш телефон или как контроллеры VR. </p>
<h2 id="-minimal-complete-verifiable-example-stack-overflow">Создание <em>Minimal, Complete, Verifiable, Example</em> для Stack Overflow</h2>
<p>Если вы решите задать вопрос о THREE.js,
вам почти всегда необходимо предоставить MCVE, что означает «Минимальный, Полный, Проверяемый, Пример». </p>
<p><strong>Минимальная</strong> часть важна. Допустим, у вас возникла проблема с перемещением пути в последнем примере <a href="load-gltf.html">загрузки статьи gLTF</a>.
Этот пример имеет много частей. Включите их в список </p>
<ol>
<li>A bunch of HTML</li>
<li>Some CSS</li>
<li>Lights</li>
<li>Shadows</li>
<li>lil-gui code to manipulate shadows</li>
<li>Code to load a .GLTF file</li>
<li>Code to resize the canvas.</li>
<li>Code to move the cars along paths</li>
</ol>
<p>Это довольно много. Если ваш вопрос касается только пути, вы можете удалить большую часть HTML,
так как вам нужен только тег <code class="notranslate" translate="no"><canvas></code> и <code class="notranslate" translate="no"><script></code> для THREE.js. Вы можете удалить CSS и код изменения размера.
Вы можете удалить код .GLTF, потому что вам нужен только путь.
Вы можете удалить источники света и тени с помощью <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a>.
Вы, конечно, можете удалить код <code class="notranslate" translate="no">lil-gui</code>. Код создает плоскость с текстурой. Было бы проще использовать <a href="/docs/#api/en/helpers/GridHelper"><code class="notranslate" translate="no">GridHelper</code></a>.
Наконец, если наш вопрос касается перемещения объектов по пути,
мы могли бы просто использовать кубы на пути вместо загруженных моделей автомобилей. </p>
<p>Вот более минимальный пример, учитывающий все вышеперечисленное. Он сократился с 271 строки до 135.
Мы могли бы подумать об уменьшении его еще больше, упрощая наш путь. Возможно, путь с 3 или 4 точками будет работать так же хорошо, как и наш путь с 21 точкой. </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/debugging-mcve.html"></iframe></div>
<a class="threejs_center" href="/manual/examples/debugging-mcve.html" target="_blank">нажмите здесь, чтобы открыть в отдельном окне</a>
</div>
<p></p>
<p>Я сохранил <code class="notranslate" translate="no">OrbitController</code> только потому, что полезно перемещать камеру и выяснять, что происходит, но в зависимости от вашей проблемы вы также можете удалить это.</p>
<p>Лучшее в создании MCVE - это то, что мы часто решаем нашу собственную проблему. Процесс удаления всего, что не нужно, и делая наименьший пример, мы решаем проблему, чем наоборот. </p>
<p>Вдобавок ко всему, с уважением относимся к тому времени, за которое люди будут смотреть на ваш код в Stack Overflow.
Делая минимальный пример, вы облегчаете им задачу. Вы также будете учиться в процессе. </p>
<p>Также важно, когда вы отправляете свой вопрос в Stack Overflow, <strong>поместите свой код <a href="https://stackoverflow.blog/2014/09/16/introducing-runnable-javascript-css-and-html-code-snippets/">во фрагмент</a>.</strong>
Конечно, вы можете использовать JSFiddle, Codepen или аналогичный сайт для тестирования MCVE, но как только вы действительно отправите свой вопрос в Stack Overflow,
вам потребуется поместить код для воспроизведения вашей проблемы <strong>в сам вопрос</strong>.
Делая фрагмент, вы удовлетворяете это требование. </p>
<p>Также обратите внимание, что все живые примеры на этом сайте должны работать как фрагменты. Просто скопируйте части HTML, CSS и JavaScript в соответствующие части
<a href="https://stackoverflow.blog/2014/09/16/introducing-runnable-javascript-css-and-html-code-snippets/">редактора фрагментов</a>.
Просто не забудьте попытаться удалить части, не относящиеся к вашей проблеме, и постарайтесь сделать свой код минимально необходимым. </p>
<p>Следуйте этим советам, и у вас будет гораздо больше шансов получить помощь по вашей проблеме.</p>
<h2 id="-meshbasicmaterial-">Используйте <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a></h2>
<p>Поскольку <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a> не использует источники света, это один из способов устранения причин, по которым что-то может не отображаться.
Если ваши объекты отображаются с использованием <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a>, но не с какими-либо материалами, которые вы использовали, то вы знаете,
что проблема, скорее всего, связана с материалами или источниками света, а не с какой-либо другой частью кода. </p>
<h2 id="-near-far-">Проверьте <code class="notranslate" translate="no">near</code> и <code class="notranslate" translate="no">far</code> настройки вашей камеры</h2>
<p><a href="/docs/#api/en/cameras/PerspectiveCamera"><code class="notranslate" translate="no">PerspectiveCamera</code></a> имеет ближние и дальние настройки, которые описаны в
<a href="cameras.html">статье о камерах</a>. Убедитесь, что они установлены в соответствии с пространством, в котором находятся ваши объекты.
Возможно, даже просто <em>временно</em> установите для них что-то большое, например, <code class="notranslate" translate="no">near</code> = 0,001 и <code class="notranslate" translate="no">far</code> = 1000000.
Скорее всего, у вас возникнут проблемы с разрешением по глубине, но вы по крайней мере сможете увидеть ваши объекты, если они находятся перед камерой. </p>
<h2 id="-">Проверьте вашу сцену перед камерой</h2>
<p>Иногда вещи не появляются, потому что они не перед камерой.Если ваша камера не управляема попробуйте добавить управление камерой,
как <code class="notranslate" translate="no">OrbitControlle</code>r так что вы можете посмотреть вокруг и найти вашу сцену. Или, попробовать кадрирование сцены, используя код, который транслируется в <a href="load-obj.html">этой статье</a>.
Этот код находит размер части сцены, а затем перемещает камеру и регулирует <code class="notranslate" translate="no">near</code> и <code class="notranslate" translate="no">far</code> настройки, чтобы сделать его видимым. Затем можно заглянуть в
отладчик или добавить некоторые в <code class="notranslate" translate="no">console.log</code> сообщения для печати размера и центра сцены.</p>
<h2 id="-">Поставь что-нибудь перед сценой камеры</h2>
<p>Это просто еще один способ сказать, если все остальное терпит неудачу начнем с того, что работает, а потом потихоньку будем добавлять код обратно.
Если вы получаете пустой экран, то попробуйте поместить что-то прямо перед камерой. Сделать сферу или поле, дать ему простой материал,
как <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a> и убедитесь, что вы можете сделать это на экране.
Затем начать добавлять код немного назад во времени и тестирования.
В конце концов вы либо найдёте вашу ошибку, или вы найдете пути её решения. </p>
<hr>
<p>Это были несколько советов для отладки JavaScript. Давайте перейдём к <a href="debugging-glsl.html">некоторым советам для отладки на GLSL</a>.</p>
</div>
</div>
</div>
<script src="../resources/prettify.js"></script>
<script src="../resources/lesson.js"></script>
</body></html>