【问题标题】:Uncaught SyntaxError: Cannot use import statement outside a module未捕获的语法错误:无法在模块外使用 import 语句
【发布时间】:2020-04-13 15:21:25
【问题描述】:

https://www.youtube.com/watch?v=1TeMXIWRrqE

<!DOCTYPE html>
<html>
<head>
	<title>Three.js</title>
	<style type="text/css">
		html, body {margin: 0; padding: 0; overflow: hidden}
	</style>
</head>
<body>
  <div id="webgl"></div>
	<script src="three.js"></script>
    <script src="GLTFLoader.js"></script>
	<script>
        
    let scene,camera,renderer;
    function init(){
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0xdddddd);
    
    camera = new THREE.PerspectiveCamera(40,window.innerWidth/window.innerHeight,1,5000);
    
    hlight = new THREE.AmbientLight(0x404040,100);
    scene.add(hlight);
    
    renderer = new THREE.WebGLRenderer({antialias:true});
    renderer.setSize(window.innerWidth,window.innerHeight);
    document.getElementById('webgl').appendChild(renderer.domElement);
    
    let loader = new THREE.GLTFLoader();  //THE ERROR WITH THIS, I TRIED WITHOUT THREE. ONLY GLTLOADER() BUT DID NOT WORK 
    loader.load('scene.gltf', function(gltf){
        scene.add(gltf.scene);
        renderer.render(scene,camera);
    });
}
init();
    </script>
      
</body>
</html>
https://sketchfab.com/3d-models/1972-datsun-240k-gt-non-commercial-use-only-b2303a552b444e5b8637fdf5169b41cb //https://www.youtube.com/watch?v=1TeMXIWRrqE 这是 GLTFLOADER 的教程,我也导入了相同的 3d 文件并编写了相同的代码,但是当我在本地服务器上打开文件时,我在控制台中收到 2 个错误: 1) “GLTFLoader.js:9 Uncaught SyntaxError: Cannot use import statement outside a module” 2) “(index):29 Uncaught TypeError: THREE.GLTFLoader is not a constructor。” 虽然在 youtube 视频中它会立即与他一起打开! :( 如果有人能帮我解决这个问题,我将不胜感激。太感谢了

GLTFLoader.js:9 未捕获的语法错误

(index):29 未捕获的类型错误

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    Here's a newer tutorialthis article 的底部解释了发生了什么变化。

    短版本是three.js,改为更喜欢使用es6模块,而不是

    <script src="three.js"></script>
    <script src="GLTFLoader.js"></script>
    <script>
    
    let scene,camera,renderer;
    function init(){
      ...
      THREE.GLTFLoader.load(...
    

    你会这样做

    <script type="module">
    import * as THREE from './build/three.module.js';
    import {GLTFLoader} from './examples/jsm/loaders/GLTFLoader.js';
    
    let scene,camera,renderer;
    function init(){
      ...
      GLTFLoader.load(...
    

    但要这样使用它需要将三个.js 文件复制到相同的文件夹结构中。

    someFolder
     |
     ├-build
     | |
     | +-three.module.js
     |
     +-examples
       |
       +-jsm
         |
         +-controls
         | |
         | +-OrbitControls.js
         | +-TrackballControls.js
         | +-...
         |
         +-loaders
         | |
         | +-GLTFLoader.js
         | +-...
         |
         ...
    

    如果你想使用旧方法&lt;script&gt;标签样式,那么你需要确保你使用来自the js folder的文件,而不是the jsm folder

    注意:您必须使用此文件夹结构,因为示例/jsm 文件夹中的文件(如 GLTFLoader.js)通过相对但硬编码的路径引用各种其他文件(如 three.module.js)。例如在GLTFLoader.js 中有一行是有效的

    import {stuff} from "../../../build/three.module.js";
    

    新样式的几个优点是

    1. 各种模块可以引入他们需要的其他部分。

      过去要使用一个额外的部分,您可能需要添加 1 到 10 个其他 &lt;script&gt; 标签。现在您只需要 1 个导入,该部分可以自己拉入其他 1 到 10 个部分

    2. 如果您使用 Web 构建器构建页面,它可以去除您不使用的部分。

    有传言称,有计划在未来某个时候完全摆脱 &lt;script&gt; 方法。


    只是想弄清楚为什么 ES6 模块更好以及为什么需要保持相同的结构。

    在 r105 之前使用 EffectComposer 你会这样做

    <script src="threejs/examples/js/postprocessing/EffectComposer.js"></script>
    

    你运行,你会得到一个错误

    THREE.EffectComposer relies on THREE.CopyShader
    

    所以你会四处寻找它,它与 EffectsComposer.js 不在同一个文件夹中。当你最终找到它时,你添加它

    <script src="threejs/examples/js/postprocessing/EffectComposer.js"></script>
    <script src="threejs/examples/js/shaders/CopyShader.js"></script>
    

    再次运行并得到另一个错误THREE.EffectComposer relies on THREE.ShaderPass 所以再次挖掘你添加它

    <script src="threejs/examples/js/postprocessing/EffectComposer.js"></script>
    <script src="threejs/examples/js/shaders/CopyShader.js"></script>
    <script src="threejs/examples/js/postprocessing/ShaderPass.js"></script>
    

    这太糟糕了。

    现在从 r105 开始,您可以使用 es6 模块进行操作

    import {EffectComposer} from './threejs/examples/jsm/postprocessing/EffectComposer.js';
    

    这可以说是更好。您不会得到其他错误,因为 ES6 模块版本 EffectComposer.js 可以引用它需要的文件、它的依赖项本身。 top of EffectComposer.js 是对其依赖项的引用。

    import {
        Clock,
        LinearFilter,
        Mesh,
        OrthographicCamera,
        PlaneBufferGeometry,
        RGBAFormat,
        Vector2,
        WebGLRenderTarget
    } from "../../../build/three.module.js";
    import { CopyShader } from "../shaders/CopyShader.js";
    import { ShaderPass } from "../postprocessing/ShaderPass.js";
    import { MaskPass } from "../postprocessing/MaskPass.js";
    import { ClearMaskPass } from "../postprocessing/MaskPass.js";
    

    但是,正如您在上面看到的,EffectsComposer.js 预计 three.module.js 位于名为 build 的文件夹中,距其自身 3 个子文件夹。它预计CopyShader.js 位于一个名为shaders 的文件夹中,距其自身一个文件夹。等等……

    换句话说,需要相同的文件夹结构

    【讨论】:

    • 你也可以讽刺,希望削弱某人的正确和准确的观点。但是,只要您了解幕后发生的事情。您将始终能够推理并决定哪种方法最适合您的用例。
    • 我没有删除任何 cmets,即使我不想这样做,我也没有能力这样做。您完全有权根据需要更改 three.js。将 Mesh 重命名为 Foobar。剪掉不需要的部分。将其重构为其他内容。大多数人选择按原样使用它,它需要一定的文件夹结构。我不知道为什么这对你来说是个问题,但你有权发表你的意见并为自己创造更多的工作。
    • 你总是偏离我所说的,因为你不能接受不同的观点。我从未说过要更改 Three.js 的核心,例如 Mesh,我什至从未说过要更改示例文件的实现,尽管您也可以这样做。我所说的是任何人都可以并且应该将模块导入路径更改为适合他们喜欢的路径。 Three.js 的合作者总是说示例文件只是示例文件。用户不需要按原样使用它们,它们是用来参考的,它们是用来适应的。更改模块导入路径不过是预期的结果。
    【解决方案2】:

    我遇到了类似的问题,我就是这样解决的。

    在您的 HTML 中,添加其他脚本时的顺序很重要,因为它需要 Three.js 中的某些内容。

    应该是

       <script src="../build/three.min.js"></script>
       <script src="three.js-master/examples/js/controls/OrbitControls.js"></script>
       <script src="three.js-master/examples/js/loaders/GLTFLoader.js"></script>
    

    我建议尝试从本地 javascript 文件夹导入,而不是使用 jsm。我希望这能解决您的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-04
      • 2021-05-15
      • 2023-03-17
      • 2020-10-10
      • 2020-10-25
      • 2020-09-19
      相关资源
      最近更新 更多