经纬志
首页 / 实战手册 / 3D 与 Cesium

CesiumWidget 尺寸为 0,地球建不出来

先看结论

页面一打开就报错,容器明明写了 width: 100%; height: 100%, 浏览器算出来的却是 0×0。

最后验证 2026-11-03 · 多技术栈 · 更新 2026-10-29 · 引用本文

现象

控制台报出一条来自 CesiumWidget 构造过程的错误, 之后整个地图区域保持空白:

DeveloperError: Expected width to be greater than 0, actual value was 0
    at CesiumWidget.draw (CesiumWidget.js:1042)
    at Viewer.resize (Viewer.js:1301)

同时 viewer.canvas.width 为 0,缩放手柄、版权信息也全部错位在左上角。

原因

Cesium 在构造时读取容器的 clientWidth 与 clientHeight 来创建 WebGL 画布。 百分比高度只有在父级有确定高度时才成立,以下三种情况都会让结果变成 0:

  • 容器或任一祖先节点处于 display: none,常见于标签页、抽屉、弹窗未展开时初始化。
  • 父级是 flex 布局,子项设了 flex: 1 却没有 min-height: 0,被内容压成 0。
  • 脚本在 DOMContentLoaded 之前执行,样式表还没应用。

排查过程

在初始化前打印容器尺寸,并逐级向上查找第一个高度为 0 的祖先:

var el = document.getElementById('cesiumContainer');
console.log(el.clientWidth, el.clientHeight);       // 0 0

var p = el;
while (p && p !== document.body) {
  console.log(p.tagName, p.className, p.clientHeight);
  p = p.parentElement;
}

解决方案

CSS 侧给容器一个明确的尺寸来源。height: 100% 必须有一连串确定高度的父级:

html, body {
  height: 100%;
  margin: 0;
}
#app {
  display: flex;
  flex-direction: column;
  height: 100%;
}
#cesiumContainer {
  flex: 1;
  min-height: 0;      /* 关键:允许 flex 子项收缩 */
  position: relative;
}

容器在隐藏状态下创建时,等它可见再初始化,而不是先建再补尺寸:

function initWhenVisible(el, callback) {
  if (el.clientWidth > 0 && el.clientHeight > 0) {
    callback();
    return;
  }
  var ro = new ResizeObserver(function () {
    if (el.clientWidth > 0 && el.clientHeight > 0) {
      ro.disconnect();
      callback();
    }
  });
  ro.observe(el);
}

initWhenVisible(document.getElementById('cesiumContainer'), function () {
  window.viewer = new Cesium.Viewer('cesiumContainer');
});

已经创建了 viewer,只是窗口或面板尺寸变化,直接调 resize 即可:

var ro = new ResizeObserver(function () {
  viewer.resize();
  viewer.scene.requestRender();
});
ro.observe(document.getElementById('cesiumContainer'));

验证

viewer.canvas.width 与容器 clientWidth × devicePixelRatio 一致; 拖动窗口改变宽度,画布跟着变化且不出现拉伸; 在弹窗中打开地图,首次显示就铺满而不是缩在角落。

顺序很重要:先让容器有尺寸,再 new Viewer。 反过来先创建再调 resize,Cesium 内部的一些缓冲区已按 0 尺寸初始化, 部分版本仍会出现画面缺失,需要重建 viewer。

引用本文

经纬志(2026)。《CesiumWidget 尺寸为 0,地球建不出来》。https://www.jingweizhi.com/cookbook/cesium-widget-zero-size.html(访问日期 2026-11-03)。