You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Three.js开发水面效果时遭遇模块解析错误,求排查方案

Three.js水面效果模块解析错误排查

错误信息

Uncaught TypeError: Error resolving module specifier “three”. Relative module specifiers must start with “./”, “../” or “/”.

问题代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>My first three.js app</title>
        <style>
            body { margin: 0; }
        </style>
                <script type="importmap">
        {
            "imports": {
                "three": "./build/three.module.js",
                "three.js-master/examples/jsm/controls/OrbitControls":"./jsm/controls/OrbitControls.js",
                "three.js-master/examples/jsm/libs/stats.module":"./jsm/libs/stats.module.js",
            }
        }
    </script>
    </head>
    <body>
        
        <script type="module" src="https://cdn.jsdelivr.net/npm/three@0.143/build/three.min.js"></script>
        <script type="module" src="https://cdn.jsdelivr.net/npm/three@0.143/examples/js/controls/OrbitControls.js"></script> 
        
        
        </script>
        <script  type="module">

            import { Water } from 'http://localhost/Lines/jsm/objects/Water.js';
            import * as THREE from 'http://localhost/Lines/build/three.module.js';

            const scene = new THREE.Scene();
            const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
            camera.position.set( 0, 0, 50 );
            camera.lookAt( 0, 0, 0 );
            

            const renderer = new THREE.WebGLRenderer();
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.body.appendChild( renderer.domElement );

        

            const WaterGeometry = new THREE.PlaneGeometry( 45, 45 );
            const texture = new THREE.TextureLoader().load( 'https://i.imgur.com/mK9cHLq.jpeg' );
            const material = new THREE.MeshBasicMaterial( { map: texture, side: THREE.DoubleSide } );
            const controls = new THREE.OrbitControls( camera, renderer.domElement );

            let water = new Water
                (
                    WaterGeometry,
                    {
                        textureWidth: 512,
                        textureHeight: 512,
                        waterNormals: new THREE.TextureLoader().load
                        ( 'textures/waternormals.jpg', function ( texture ) 
                        
                            {

                             texture.wrapS = texture.wrapT = THREE.RepeatWrapping;

                            } 
                        ),
                        sunDirection: new THREE.Vector3(),
                        sunColor: 0xffffff,
                        waterColor: 0x001e0f,
                        distortionScale: 3.7,
                        fog: scene.fog !== undefined
                    }
                );



            controls.update();

            scene.add( water );



            function animate() 
            {
                requestAnimationFrame( animate );

                water.rotation.x += 0.00;
                water.rotation.y += 0.00;
                water.rotation.z += 0.01;

                renderer.render( scene, camera );
            };

            animate();
        </script>
    </body>
</html>

错误原因

  1. 模块映射未生效且混合引入冲突:配置了importmap却未用模块名引入依赖,反而用绝对路径导入Three.js和Water.js。Water.js内部依赖three模块名,浏览器无法解析该非相对路径的模块,触发错误。
  2. 冗余且错误的CDN脚本:引入的CDN版Three.js是全局脚本,与ES模块环境冲突;OrbitControls用的是examples/js下的非模块版本,不兼容模块导入规则。
  3. HTML语法错误:存在多余的</script>标签,干扰脚本解析流程。

解决方法

1. 修复语法与清理冗余代码

删除多余的</script>标签,移除所有CDN引入的脚本,统一使用本地模块。

2. 完善importmap配置

更新importmap,加入Water.js的映射,确保所有依赖模块都能通过模块名解析:

<script type="importmap">
{
    "imports": {
        "three": "./build/three.module.js",
        "three/addons/controls/OrbitControls.js": "./jsm/controls/OrbitControls.js",
        "three/addons/objects/Water.js": "./jsm/objects/Water.js"
    }
}
</script>

3. 修改模块引入方式

用模块名代替绝对路径导入依赖:

import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { Water } from 'three/addons/objects/Water.js';

4. 修正OrbitControls实例化代码

模块导入的OrbitControls不属于THREE的属性,直接使用导入的类:

const controls = new OrbitControls(camera, renderer.domElement);

5. 验证本地文件路径

确保build/three.module.js、jsm/controls/OrbitControls.js、jsm/objects/Water.js的相对路径与HTML文件匹配,比如HTML在项目根目录时,上述路径需对应正确的本地文件位置。

内容的提问来源于stack exchange,提问作者Cambria

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 15:54:36