我正在尝试使用 cdn 导入三个库以及几个附加组件和 N8AO。正如标题中所述,我遇到了列出的错误:
未捕获的类型错误:无法解析模块说明符“三”。相对引用必须以“/”、“./”或“../”开头..
我在 Chrome 中收到错误,但我还没有尝试过任何其他浏览器。我也使用 WebStorm 作为我的开发环境。
我安装了 Node.js 版本 22.12.0,但是我只是在 html 文件中编写全部功能的脚本,而不是为了将所有内容集中在一处而创建单独的 javascript 文件。
我认为它来自此处给出的导入声明之一。 还包括项目的其余部分,因为它可能提供其他见解:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js Terrain with Grass and N8AO</title>
<style>
body { margin: 0; overflow: hidden; }
canvas { display: block; }
</style>
</head>
<body>
<script type="module">
import * as THREE from 'https://unpkg.com/[email protected]/build/three.module.js';
import { OrbitControls } from 'https://unpkg.com/[email protected]/examples/jsm/controls/OrbitControls.js';
import { EffectComposer } from 'https://unpkg.com/[email protected]/examples/jsm/postprocessing/EffectComposer.js';
import { N8AOPass } from "https://unpkg.com/n8ao@latest/dist/N8AO.js";
// Scene, Camera, Renderer
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(15, 15, 10);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
// Controls
const controls = new OrbitControls(camera, renderer.domElement);
controls.minPolarAngle = Math.PI / 2.5;
controls.maxPolarAngle = Math.PI / 2.5;
// Sky and lighting
scene.background = new THREE.Color(0xaabbff); // Sky color
scene.add(new THREE.AmbientLight(0x404040)); // Soft ambient light
const pointLight = new THREE.PointLight(0xffffff, 1);
pointLight.position.set(10, 10, 10);
pointLight.castShadow = true;
scene.add(pointLight);
// Terrain
const width = 100;
const terrainGeometry = new THREE.PlaneGeometry(width, width, 64, 64);
terrainGeometry.rotateX(-Math.PI / 2);
// Generate elevation for terrain
const simplex = new THREE.SimplexNoise();
for (let i = 0; i < terrainGeometry.attributes.position.count; i++) {
const x = terrainGeometry.attributes.position.array[i * 3];
const z = terrainGeometry.attributes.position.array[i * 3 + 2];
const y = 2 * simplex.noise2D(x / 10, z / 10) + 3 * simplex.noise2D(x / 15, z / 15);
terrainGeometry.attributes.position.array[i * 3 + 1] = y;
}
terrainGeometry.computeVertexNormals();
const terrainMaterial = new THREE.MeshStandardMaterial({ color: 0x228b22 });
const terrain = new THREE.Mesh(terrainGeometry, terrainMaterial);
terrain.receiveShadow = true;
scene.add(terrain);
// Grass
const grassGroup = new THREE.Group();
const bladeGeometry = new THREE.PlaneGeometry(0.12, 1, 1, 4).translate(0, 0.5, 0);
const grassMaterial = new THREE.MeshStandardMaterial({ color: 0x32cd32, side: THREE.DoubleSide });
for (let i = 0; i < 50000; i++) {
const blade = new THREE.Mesh(bladeGeometry, grassMaterial);
blade.position.set(
Math.random() * width - width / 2,
0,
Math.random() * width - width / 2
);
blade.rotation.y = Math.random() * Math.PI * 2;
blade.scale.y = 0.5 + Math.random() * 0.5;
grassGroup.add(blade);
}
scene.add(grassGroup);
// Post-Processing with N8AOPass
const composer = new EffectComposer(renderer);
const n8aoPass = new N8AOPass(scene, camera, window.innerWidth, window.innerHeight);
composer.addPass(n8aoPass);
// Adjust N8AOPass Parameters
n8aoPass.configuration.aoRadius = 5.0; // Set AO radius
n8aoPass.configuration.distanceFalloff = 1.0; // Distance attenuation
n8aoPass.configuration.intensity = 3.0; // AO intensity
n8aoPass.configuration.color = new THREE.Color(0, 0, 0); // AO color
n8aoPass.configuration.halfRes = false; // Full resolution for better quality
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Simulate grass swaying in the wind
grassGroup.children.forEach((blade) => {
blade.rotation.x = 0.1 * Math.sin(performance.now() / 1000 + blade.position.x);
});
composer.render();
}
animate();
// Handle resizing
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
composer.setSize(window.innerWidth, window.innerHeight);
});
</script>
</body>
</html>
我使用的Chrome版本是131.0.6778.109
我使用的 Webstorm 版本是#WS-242.21829.149
如果您打开例如https://unpkg.com/n8ao@latest/dist/N8AO.js你可能会注意到:
import {Color as $5Whe3$Color, ...a lot of stuff here} from "three";
import {Pass as $5Whe3$Pass} from "three/examples/jsm/postprocessing/Pass.js";
import {Pass as $5Whe3$Pass1} from "postprocessing";
这就是您看到的错误的根源。浏览器可以使用模块说明符导入模块,该模块说明符可以是绝对 URL,也可以是使用基本 URL 解析的相对 URL。要解决这个问题,您可以使用:
<script type="importmap">
您的情况:
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/[email protected]/build/three.module.js",
"three/examples/": "https://unpkg.com/[email protected]/examples/",
"postprocessing" : "https://unpkg.com/[email protected]/build/index.js"
}
}
</script>
<script type="module">
// your code here
<script>