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

Three.js正交相机场景下canvas高度过大时原点偏移问题咨询

问题根源

偏移由三个核心设置错误共同导致:

  • 正交相机视口高宽比和画布实际显示高宽比不匹配:你将相机的top/bottom参数和自定义逻辑变量height绑定,但实际canvas被CSS限制为800px高、1568px宽,当height设为40000时,相机高宽比(40000:1568)和画布实际显示高宽比(800:1568)完全错位,自然会出现中心偏移、内容拉伸的问题。
  • 渲染画布尺寸设置错误:不需要把renderer.setSize的高度设为和逻辑变量height一致,画布尺寸只需要匹配实际DOM容器的尺寸即可,过大的画布尺寸只会造成不必要的性能损耗,还会因为CSS缩放导致显示异常。
  • 远裁剪面参数设置不合理:当前相机far参数仅为8000,当逻辑高度变大后,部分场景元素可能超出裁剪范围被剔除,也会影响显示效果。

修复方案

  1. 保持renderer.setSize的参数和DOM容器实际尺寸一致,固定为1568、800
  2. 正交相机的top/bottom参数按画布实际高宽比计算,不要和逻辑世界的高度变量绑定
  3. 调大相机far参数,保证所有场景元素都在视锥体内

修复后代码

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../three.min.js"></script>
    <style>
        #webGL {
            width: 1568px;
            height: 800px;
        }
    </style>
</head>
<body>
        <div id="webGL">

        </div>
    <script>
        /* Boilerplate */
        var scene = new THREE.Scene();
        // 逻辑世界尺寸,和渲染、相机参数解耦
        var worldWidth = 1568  
        var worldHeight = 40000
        // 画布实际渲染尺寸,和DOM容器保持一致
        var canvasWidth = 1568
        var canvasHeight = 800

        // 相机参数按画布高宽比设置,far调大到100000覆盖世界范围
        var camera = new THREE.OrthographicCamera(-canvasWidth/2,canvasWidth/2,canvasHeight/2,-canvasHeight/2,1,100000)
        camera.position.set(0,100,0)
        camera.up.set(0,0,1)
        camera.lookAt(new THREE.Vector3(0,0,0))

        var renderer = new THREE.WebGLRenderer({
            antialias: true
        });
        renderer.setSize(canvasWidth, canvasHeight);
        renderer.setClearColor("white")

        document.getElementById("webGL").appendChild(renderer.domElement);
        let testGeom = new THREE.PlaneGeometry(200,200)
        let material = new THREE.MeshBasicMaterial({color:'black',side: THREE.DoubleSide})
        var cube = new THREE.Mesh(testGeom,material)
        cube.rotation.x+=Math.PI/2
        cube.position.z = worldHeight/2
        scene.add(cube);

        let origin  = new THREE.PlaneGeometry(50,50)
        let originMaterial = new THREE.MeshBasicMaterial({color:'red',side:THREE.DoubleSide})
        let originMesh = new THREE.Mesh(origin,originMaterial)
        originMesh.rotation.x+=Math.PI/2
        scene.add(originMesh)

        scene.position.set(0,0,0)
        var helper = new THREE.GridHelper(80,5,0x000ff,0x808080) //size,step
        scene.add(helper)
        var flag = false
        var render = function() {
            requestAnimationFrame(render);
            renderer.render(scene, camera);
        };
        render();
    </script>
</body>
</html>

如果需要调整视野显示的范围,只需要修改正交相机的left/right/top/bottom的缩放系数即可,不需要修改渲染画布尺寸。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 14:54:02