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

如何用Flexbox+Three.js让Canvas填充视口垂直剩余空间

问题描述

我正在使用Three.js渲染Canvas,希望在Canvas上方和下方各放置一个<div>,让Canvas填充两者之间的剩余空间(视口尺寸变化时Canvas比例改变也可)。三个元素需始终占满100%视口,且不超出视口产生滚动条。

我本以为这是简单的Flexbox布局,但尝试后要么出现滚动条,要么底部元素被推出视口。奇怪的是,将flex-direction改为row时,横向布局能正常实现需求,我想实现垂直方向的同样效果,是否可行?

解决方案

垂直方向的Flex布局完全可以实现需求,问题出在两个容易忽略的细节:

  • 用100vh替代100%定义视口高度,避免DOM继承链的高度计算偏差导致溢出
  • 给Canvas所在的.middle容器添加overflow: hidden,防止Canvas默认固定尺寸撑开布局
修正后的完整代码

HTML

<div class="container">
  <div class="top">Top</div>
  <div class="middle">
    <canvas></canvas>
  </div>
  <div class="bottom">Bottom</div>
</div>

<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>
<script type="importmap">
  {
    "imports": {
      "three": "https://unpkg.com/three@v0.155.0/build/three.module.js",
      "three/addons/": "https://unpkg.com/three@v0.155.0/examples/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from 'three';
  window.THREE = THREE;
</script>

CSS

html, body {
  min-height: 100vh;
  margin: 0;
  overflow: hidden;
}

.container {
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 100vh;
}

.top, .bottom {
  padding: 10px;
}

.middle {
  flex: 1;
  overflow: hidden;
}

.middle canvas {
  width: 100%;
  height: 100%;
  display: block;
}

JavaScript

const canvas = document.querySelector('canvas');
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera();
camera.position.z = 5;
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: '#ff0000' });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

requestAnimationFrame(render);

function render() {
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;

  if (resizeRendererToDisplaySize(renderer)) {
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
  }

  renderer.render(scene, camera);
  requestAnimationFrame(render);
}

function resizeRendererToDisplaySize(renderer) {
  const width = canvas.clientWidth;
  const height = canvas.clientHeight;
  const needResize = canvas.width !== width || canvas.height !== height;

  if (needResize) {
    renderer.setSize(width, height, false);
  }

  return needResize;
}

内容的提问来源于stack exchange,提问作者XåpplI'-I0llwlg'I -

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 14:28:23