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

如何正确导入THREE.InfiniteGridHelper并解决本地运行报错

解决THREE.InfiniteGridHelper本地运行报错问题

遇到的报错汇总

尝试使用THREE.InfiniteGridHelper时,无论采用复制代码到main.js、单独文件导入、远程链接导入等方式,均出现以下报错:

Uncaught TypeError: "InfiniteGridHelper" is read-only
Uncaught TypeError: THREE.InfiniteGridHelper is not a constructor
SyntaxError: import declarations may only appear at top level of a module
Uncaught SyntaxError: The requested module doesn't provide an export named: 'InfiniteGridHelper'
Uncaught ReferenceError: THREE is not defined
Cross-Origin Request Blocked: Same Origin Policy限制,远程链接无CORS头

核心问题分析

  1. ES模块中导入的THREE对象是只读的,原代码直接修改THREE.InfiniteGridHelper导致只读错误
  2. 单独文件导入时未正确处理模块依赖,导致THREE未定义或导出错误

修复方案

1. 封装独立的InfiniteGridHelper模块

新建InfiniteGridHelper.js文件,内容如下:

import * as THREE from 'three';

export class InfiniteGridHelper extends THREE.Mesh {
    constructor(size1 = 10, size2 = 100, color = new THREE.Color('white'), distance = 8000, axes = 'xzy') {
        const planeAxes = axes.substr(0, 2);
        const geometry = new THREE.PlaneBufferGeometry(2, 2, 1, 1);
        
        const material = new THREE.ShaderMaterial({
            side: THREE.DoubleSide,
            uniforms: {
                uSize1: { value: size1 },
                uSize2: { value: size2 },
                uColor: { value: color },
                uDistance: { value: distance }
            },
            transparent: true,
            vertexShader: `
                varying vec3 worldPosition;
                uniform float uDistance;
                
                void main() {
                    vec3 pos = position.${axes} * uDistance;
                    pos.${planeAxes} += cameraPosition.${planeAxes};
                    
                    worldPosition = pos;
                    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
                }
            `,
            fragmentShader: `
                varying vec3 worldPosition;
                uniform float uSize1;
                uniform float uSize2;
                uniform vec3 uColor;
                uniform float uDistance;
                
                float getGrid(float size) {
                    vec2 r = worldPosition.${planeAxes} / size;
                    vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);
                    float line = min(grid.x, grid.y);
                    return 1.0 - min(line, 1.0);
                }
                
                void main() {
                    float d = 1.0 - min(distance(cameraPosition.${planeAxes}, worldPosition.${planeAxes}) / uDistance, 1.0);
                    float g1 = getGrid(uSize1);
                    float g2 = getGrid(uSize2);
                    
                    gl_FragColor = vec4(uColor.rgb, mix(g2, g1, g1) * pow(d, 3.0));
                    gl_FragColor.a = mix(0.5 * gl_FragColor.a, gl_FragColor.a, g2);
                    
                    if (gl_FragColor.a <= 0.0) discard;
                }
            `,
            extensions: { derivatives: true }
        });
        
        super(geometry, material);
        this.frustumCulled = false;
    }
}

说明:移除原代码中兼容旧版本THREE的冗余逻辑,直接通过类继承THREE.Mesh并以模块方式导出,避免修改只读的THREE全局对象。

2. 修改main.js导入并使用

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

// 创建场景
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 5);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 窗口resize处理
window.addEventListener('resize', () => {
    const width = window.innerWidth;
    const height = window.innerHeight;
    renderer.setSize(width, height);
    camera.aspect = width / height;
    camera.updateProjectionMatrix();
});

// 轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.update();

// 使用InfiniteGridHelper
const gridHelper = new InfiniteGridHelper(10, 100);
scene.add(gridHelper);

// 创建立方体
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshNormalMaterial();
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// 动画循环
function animate() {
    requestAnimationFrame(animate);
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    renderer.render(scene, camera);
    controls.update();
}

animate();

说明:直接导入封装好的InfiniteGridHelper类,避免修改THREE全局对象,解决只读错误。

3. 确保HTML结构正确

保持原HTML的importmap和模块引用,注意文件路径匹配:

<!DOCTYPE html>
<html>
<head>
    <title>Three.js Scene</title>
    <style>
        body { margin: 0; }
        canvas { width: 100%; height: 100% }
    </style>
</head>
<body>
    <script type="importmap">
        {
            "imports": {
                "three": "https://cdn.jsdelivr.net/npm/three@0.169.0/build/three.module.js",
                "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.169.0/examples/jsm/"
            }
        }
    </script>
    <script type="module" src="static/main.js"></script>
</body>
</html>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 19:17:05