学习:Cesium (2)

十二、相机的方向和位置

Camera - Cesium Documentation

setView

相机位置

javascript 复制代码
viewer.camera.setView({
  destination: Cesium.Cartesian3.fromDegrees(116.397, 39.917, 1000),
});

相机方向

javascript 复制代码
俯视地面 (pitch = -90°)      平视地平线 (pitch = 0°)
      ↓                            →
    [相机]                       [相机]
      |                            
    地面                         地平线 ──────


航向角 heading:
        0° (北)
          ↑
  270° ←  |  → 90° (东)
          ↓
       180° (南)
参数 名称 含义 取值范围 示例
heading 航向角 水平方向的旋转,类似指南针方向 0° ~ 360° 0° = 正北, 90° = 正东
pitch 俯仰角 相机"抬头/低头"的角度 -90° ~ 90° -90° = 垂直俯视, 0° = 平视
roll 翻滚角 相机侧向倾斜 -180° ~ 180° 0° = 水平, 45° = 向右倾斜
javascript 复制代码
viewer.camera.setView({
  destination: Cesium.Cartesian3.fromDegrees(116.397, 39.917, 1000),
  orientation: {
    heading: Cesium.Math.toRadians(0),
    pitch: Cesium.Math.toRadians(-90),
    roll: 90,
  },
});

常用方法对比

方法 特点 适用场景
setView() 立即切换,无动画 快速定位
flyTo() 平滑飞行动画 用户体验更好
lookAt() 锁定目标点观察 围绕某点旋转

使用 flyTo 替代 setView

javascript 复制代码
viewer.camera.flyTo({
  destination: Cesium.Cartesian3.fromDegrees(116.393428, 39.90923, 1000),
  orientation: {
    heading: Cesium.Math.toRadians(0), // 东北方向
    pitch: Cesium.Math.toRadians(-90), // 斜视角度
    roll: 0,
  },
  duration: 3, // 飞行动画时长(秒)
});

实时获取相机信息

javascript 复制代码
// 获取当前相机位置(Cartesian3 世界坐标)
const position = viewer.camera.position;
console.log(position);
javascript 复制代码
// 获取当前相机方向
const heading = viewer.camera.heading;  // 弧度
const pitch = viewer.camera.pitch;
const roll = viewer.camera.roll;
console.log(heading, pitch, roll);

十三、相机动画与相机动态交互

Camera - Cesium Documentation

相机移动方法对比

javascript 复制代码
setView()          flyTo()           lookAt()
   │                  │                 │
   ▼                  ▼                 ▼
 瞬间切换          平滑飞行动画        锁定目标点观察
方法 动画 特点 适用场景
setView() 立即切换位置 初始化、快速定位
flyTo() 平滑飞行轨迹 场景漫游、用户体验
lookAt() 围绕目标旋转 观察特定物体

flyTo() --- 飞行动画

lookAt() --- 锁定目标观察

javascript 复制代码
// 锁定目标点,相机围绕该点旋转
const center = Cesium.Cartesian3.fromDegrees(116.393428, 39.90923, 1000);

viewer.camera.lookAt(
  center,  // 目标点
  new Cesium.HeadingPitchRange(
    Cesium.Math.toRadians(0),    // heading
    Cesium.Math.toRadians(-30),  // pitch
    1000                          // 距离(米)
  )
);

// 解除锁定
// viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
javascript 复制代码
            相机
              ●
             /|
            / |
           /  | 距离
          /   |
         /pitch
        ●─────
       目标点
        
相机只能围绕目标点旋转,不能移动位置

相机事件监听

moveEnd、moveStart

javascript 复制代码
viewer.camera.flyTo({
 ....
});

// 1. 相机移动开始
viewer.camera.moveStart.addEventListener(function () {
  console.log("相机开始移动");
});

// 2. 相机移动结束
viewer.camera.moveEnd.addEventListener(function () {
  console.log("相机停止移动");
});

changed

javascript 复制代码
// 3. 相机变化(每帧触发)
viewer.camera.changed.addEventListener(function() {
  const position = viewer.camera.position;
  console.log("相机位置变化:", position);
});
javascript 复制代码
// 4. 实时监听相机状态(场景渲染时触发)
viewer.scene.postRender.addEventListener(function() {
  // 获取相机当前位置和方向
  const cartographic = Cesium.Cartographic.fromCartesian(viewer.camera.position);
  const lon = Cesium.Math.toDegrees(cartographic.longitude);
  const lat = Cesium.Math.toDegrees(cartographic.latitude);
  const height = cartographic.height;
  const heading = Cesium.Math.toDegrees(viewer.camera.heading);
  const pitch = Cesium.Math.toDegrees(viewer.camera.pitch);

  console.log(`位置: (${lon.toFixed(2)}, ${lat.toFixed(2)}, ${height.toFixed(0)}m)`);
  console.log(`方向: heading=${heading.toFixed(1)}°, pitch=${pitch.toFixed(1)}°`);
});

move

javascript 复制代码
// 设置初始相机位置,避免无效状态
viewer.camera.setView({
  destination: Cesium.Cartesian3.fromDegrees(116.393428, 39.90923, 10000),
  orientation: {
    heading: 0,
    pitch: Cesium.Math.toRadians(-45),
    roll: 0,
  },
});
document.addEventListener("keydown", function (e) {
  const moveAmount = 1000; // 移动量(米)

  switch (e.key) {
    case "w":
    case "W":
      viewer.camera.moveForward(moveAmount); // 前进
      break;
    case "s":
    case "S":
      viewer.camera.moveBackward(moveAmount); // 后退
      break;
    case "a":
    case "A":
      viewer.camera.moveLeft(moveAmount); // 左移
      break;
    case "d":
    case "D":
      viewer.camera.moveRight(moveAmount); // 右移
      break;
  }
});

look

javascript 复制代码
    case "q":
    case "Q":
      viewer.camera.lookLeft(Cesium.Math.toRadians(5)); // 左转
      break;
    case "e":
    case "E":
      viewer.camera.lookRight(Cesium.Math.toRadians(5)); // 右转
      break;
    case "r":
    case "R":
      viewer.camera.lookUp(Cesium.Math.toRadians(5)); // 
      break;
    case "f":
    case "F":
      viewer.camera.lookDown(Cesium.Math.toRadians(5)); // 
      break;

twistLeft

javascript 复制代码
    case "g":
    case "G":
      viewer.camera.twistLeft(Cesium.Math.toRadians(5)); //
      break;
    case "h":
    case "H":
      viewer.camera.twistRight(Cesium.Math.toRadians(5)); //
      break;

十四、添加物体与3D建筑物

javascript 复制代码
// 北京
const position = Cesium.Cartesian3.fromDegrees(116.397428, 39.90923, 1000);
// 广州塔
const position1 = Cesium.Cartesian3.fromDegrees(113.3191, 23.109, 1000);

EntityCollection - Cesium Documentation

PointGraphics - Cesium Documentation

Name Type Attributes Default Description
show Property | boolean <optional> true A boolean Property specifying the visibility of the point.
pixelSize Property | number <optional> 1 A numeric Property specifying the size in pixels.
heightReference Property | HeightReference <optional> HeightReference.NONE A Property specifying what the height is relative to.
color Property | Color <optional> Color.WHITE A Property specifying the Color of the point.
outlineColor Property | Color <optional> Color.BLACK A Property specifying the Color of the outline.
outlineWidth Property | number <optional> 0 A numeric Property specifying the the outline width in pixels.
scaleByDistance Property | NearFarScalar <optional> A NearFarScalar Property used to scale the point based on distance.
translucencyByDistance Property | NearFarScalar <optional> A NearFarScalar Property used to set translucency based on distance from the camera.
distanceDisplayCondition Property | DistanceDisplayCondition <optional> A Property specifying at what distance from the camera that this point will be displayed.
disableDepthTestDistance Property | number <optional> A Property specifying the distance from the camera at which to disable the depth test to.
splitDirection Property | SplitDirection <optional> A Property specifying the SplitDirection split to apply to this point.
javascript 复制代码
// ========== 添加点 ==========
viewer.entities.add({
  name: "北京标记点",
  position: Cesium.Cartesian3.fromDegrees(116.397428, 39.90923, 0),
  point: {
    pixelSize: 10, // 点的大小(像素)
    color: Cesium.Color.RED, // 颜色
    outlineColor: Cesium.Color.WHITE, // 轮廓颜色
    outlineWidth: 2, // 轮廓宽度
    heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, // 贴地
  },
});

添加3D模型(来自 OpenStreetMap

Global - Cesium Documentation

javascript 复制代码
添加全球 3D 建筑物(来自 OpenStreetMap)
const osmBuildings = viewer.scene.primitives.add(
  await Cesium.createOsmBuildingsAsync()
);

设置建筑样式

Cesium3DTileStyle - Cesium Documentation

ConditionsExpression - Cesium Documentation

javascript 复制代码
    style: new Cesium.Cesium3DTileStyle({
      color: {
        conditions: [
          ["${feature['building']} === 'hospital'", "color('#0000FF')"],
          ["${feature['building']} === 'school'", "color('#00FF00')"],
          [true, "color('#ffffff')"]
        ]
      }
    })

整体

javascript 复制代码
//  添加3D模型
const osmBuildings = viewer.scene.primitives.add(
  await Cesium.createOsmBuildingsAsync({
    style: new Cesium.Cesium3DTileStyle({
      color: {
        conditions: [
          ["${feature['building']} === 'hospital'", "color('#0000FF')"],
          ["${feature['building']} === 'school'", "color('#00FF00')"],
          [true, "color('#ffffff')"],
        ],
      },
    }),
  })
);

十五、标签与广告牌

标签

LabelGraphics - Cesium Documentation

javascript 复制代码
// 添加文字标签和广告牌
viewer.entities.add({
  name: "北京标记点",
  position: Cesium.Cartesian3.fromDegrees(116.397428, 39.90923, 0),
  label: {
    text: "北京",
    font: "24px Arial",
    fillColor: Cesium.Color.RED, // 颜色
    outlineColor: Cesium.Color.WHITE, // 轮廓颜色
    outlineWidth: 2, // 轮廓宽度
    style: Cesium.LabelStyle.FILL_AND_OUTLINE, // 样式
    pixelOffset: new Cesium.Cartesian2(0, -20), // 偏移量
    horizontalOrigin: Cesium.HorizontalOrigin.CENTER, // 水平对齐方式
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 贴地
  },
});
javascript 复制代码
// ========== 添加点 ==========
viewer.entities.add({
  name: "广州塔标记点",
  position: Cesium.Cartesian3.fromDegrees(113.3191, 23.109, 600),
  point: {
    pixelSize: 10, // 点的大小(像素)
    color: Cesium.Color.BLUE, // 颜色
    outlineColor: Cesium.Color.WHITE, // 轮廓颜色
    outlineWidth: 2, // 轮廓宽度
  },
});

// 添加文字标签和广告牌
viewer.entities.add({
  name: "广州塔标记点",
  position: Cesium.Cartesian3.fromDegrees(113.3191, 23.109, 600),
  label: {
    text: "广州塔",
    font: "24px Arial",
    fillColor: Cesium.Color.BLUE, // 颜色
    outlineColor: Cesium.Color.WHITE, // 轮廓颜色
    outlineWidth: 2, // 轮廓宽度
    style: Cesium.LabelStyle.FILL_AND_OUTLINE, // 样式
    pixelOffset: new Cesium.Cartesian2(0, -20), // 偏移量
    horizontalOrigin: Cesium.HorizontalOrigin.CENTER, // 水平对齐方式
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 贴地
  },
});
//  添加3D模型
const osmBuildings = viewer.scene.primitives.add(
  await Cesium.createOsmBuildingsAsync()
);

广告牌

BillboardGraphics - Cesium 文档

javascript 复制代码
// 添加文字标签和广告牌
viewer.entities.add({
  name: "广州塔标记点",
  position: Cesium.Cartesian3.fromDegrees(113.3191, 23.109, 700),
  label: {
    text: "广州塔",
    font: "24px Arial",
    fillColor: Cesium.Color.BLUE, // 颜色
    outlineColor: Cesium.Color.WHITE, // 轮廓颜色
    outlineWidth: 2, // 轮廓宽度
    style: Cesium.LabelStyle.FILL_AND_OUTLINE, // 样式
    pixelOffset: new Cesium.Cartesian2(0, -20), // 偏移量
    horizontalOrigin: Cesium.HorizontalOrigin.CENTER, // 水平对齐方式
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 贴地
  },
  billboard: {
    image: "../../img/广州塔.png",
    width: 50,
    height: 50,
    horizontalOrigin: Cesium.HorizontalOrigin.TOP, // 水平对齐方式
    verticalOrigin: Cesium.VerticalOrigin.CENTER,
  },
});

十六、3D模型添加与设置

添加 GLTF/GLB 3D模型

ModelGraphics - Cesium Documentation

javascript 复制代码
viewer.entities.add({
  position: Cesium.Cartesian3.fromDegrees(113.3191, 23.109, 900),
  model: {
    uri: "../../飞机.glb", // 模型路径
    minimumPixelSize:128, // 最小像素尺寸
  },
});
javascript 复制代码
viewer.entities.add({
  position: Cesium.Cartesian3.fromDegrees(113.3191, 23.109, 900),
  model: {
    uri: "../../飞机.glb", // 模型路径
    minimumPixelSize: 128, // 最小像素尺寸
    silhouetteSize: 5,
    silhouetteColor: Cesium.Color.BLUE, // 模型轮廓颜色
    // 设置相机距离模型的距离显示
    distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10000),
  },
});

十七、椭圆_走廊_圆柱体添加与设置

椭圆

EllipseGraphics - Cesium Documentation

javascript 复制代码
// 添加椭圆
viewer.entities.add({
  name: "椭圆示例",
  position: Cesium.Cartesian3.fromDegrees(113.3191, 23.109, 0), // 位置
  ellipse: {
    semiMinorAxis: 250.0, // 短半轴(米)
    semiMajorAxis: 500.0, // 长半轴(米)
    height: 100.0, // 离地高度(米)
    material: Cesium.Color.RED.withAlpha(0.5), // 材质颜色
    outline: true, // 是否显示轮廓线
    outlineColor: Cesium.Color.WHITE, // 轮廓线颜色
    rotation: Cesium.Math.toRadians(45), // 旋转角度
  },
});

走廊

CorridorGraphics - Cesium Documentation

javascript 复制代码
// 添加走廊
viewer.entities.add({
  name: "走廊示例",
  corridor: {
    positions: Cesium.Cartesian3.fromDegreesArray([
      113.31, 23.10,
      113.32, 23.11,
      113.33, 23.10,
    ]),
    width: 200.0,                    // 宽度(米)
    material: Cesium.Color.BLUE.withAlpha(0.5),
    outline: true,
    outlineColor: Cesium.Color.WHITE,
    height: 50.0,                    // 离地高度
  },
});

圆柱体

CylinderGraphics - Cesium Documentation

javascript 复制代码
// 添加圆柱体
viewer.entities.add({
  name: "圆柱体示例",
  position: Cesium.Cartesian3.fromDegrees(113.325, 23.115, 0),
  cylinder: {
    length: 500.0,                   // 高度(米)
    topRadius: 100.0,                // 顶部半径
    bottomRadius: 100.0,             // 底部半径
    material: Cesium.Color.GREEN.withAlpha(0.5),
    outline: true,
    outlineColor: Cesium.Color.WHITE,
  },
});
javascript 复制代码
topRadius: 0,                // 顶部半径

十八、多边形_体积折线_矩形_椭球体设置

Creating Entities -- Cesium

多边形

PolygonGraphics - Cesium Documentation

javascript 复制代码
// 添加多边形
viewer.entities.add({
  name: "多边形示例",
  polygon: {
    hierarchy: Cesium.Cartesian3.fromDegreesArray([
      113.31, 23.10,
      113.33, 23.10,
      113.33, 23.12,
      113.31, 23.13,
    ]),
    height: 100.0,                    // 离地高度(米)
    extrudedHeight: 300.0,            // 拉伸高度(创建立体效果)
    material: Cesium.Color.RED.withAlpha(0.5),
    outline: true,
    outlineColor: Cesium.Color.WHITE,
    fill: true,
  },
});

体积折线

体积折线是沿路径延伸的立体管状形状,可自定义横截面:

PolylineVolumeGraphics - Cesium Documentation

javascript 复制代码
// 定义横截面形状(星形)
function computeStarShape(outerRadius, innerRadius, points) {
  const shape = [];
  for (let i = 0; i < points * 2; i++) {
    const radius = i % 2 === 0 ? outerRadius : innerRadius;
    const angle = (i * Math.PI) / points;
    shape.push(new Cesium.Cartesian2(
      Math.cos(angle) * radius,
      Math.sin(angle) * radius
    ));
  }
  return shape;
}

// 添加体积折线
viewer.entities.add({
  name: "体积折线示例",
  polylineVolume: {
    positions: Cesium.Cartesian3.fromDegreesArrayHeights([
      113.31, 23.10, 200,
      113.32, 23.11, 300,
      113.33, 23.10, 200,
    ]),
    shape: computeStarShape(50, 25, 5),  // 星形横截面
    material: Cesium.Color.BLUE.withAlpha(0.5),
    outline: true,
    outlineColor: Cesium.Color.WHITE,
  },
});

矩形

RectangleGraphics - Cesium Documentation

矩形是由西、南、东、北坐标定义的矩形区域:

javascript 复制代码
// 添加矩形
viewer.entities.add({
  name: "矩形示例",
  rectangle: {
    coordinates: Cesium.Rectangle.fromDegrees(
      113.31, 23.10,  // 西、南
      113.33, 23.12   // 东、北
    ),
    height: 50.0,                     // 离地高度
    extrudedHeight: 150.0,            // 拉伸高度
    material: Cesium.Color.GREEN.withAlpha(0.5),
    outline: true,
    outlineColor: Cesium.Color.WHITE,
    fill: true,
  },
});

椭球体

EllipsoidGraphics - Cesium Documentation

椭球体是三维立体形状,可创建球形或椭球形:

javascript 复制代码
// 添加椭球体
viewer.entities.add({
  name: "椭球体示例",
  position: Cesium.Cartesian3.fromDegrees(113.32, 23.11, 200),
  ellipsoid: {
    radii: new Cesium.Cartesian3(100, 80, 60),  // X、Y、Z 方向半径
    material: Cesium.Color.YELLOW.withAlpha(0.5),
    outline: true,
    outlineColor: Cesium.Color.WHITE,
    fill: true,
  },
});

WallGraphics - Cesium Documentation

javascript 复制代码
viewer.entities.add({
  name: "Red wall at height",
  wall: {
    positions: Cesium.Cartesian3.fromDegreesArrayHeights([
      113.32, 23.11, 200.0, 120.32, 23.11, 200.0,
    ]),
    minimumHeights: [1000.0, 1000.0],
    material: Cesium.Color.RED,
  },
});

常用公共属性

属性 说明
material 材质/颜色,支持纯色、图片、条纹等
outline 是否显示轮廓线
outlineColor 轮廓线颜色
height 离地高度(米)
extrudedHeight 拉伸高度(创建立体效果)
fill 是否填充
相关推荐
电子云与长程纠缠2 小时前
Godot学习02 - 输入
java·学习·godot
峥嵘life2 小时前
Android16 EDLA【GTS】GtsPermissionTestCases存在fail项
android·学习
努力学习的小廉2 小时前
redis学习笔记(八)—— C++ 操作 Redis
redis·笔记·学习
星幻元宇VR2 小时前
VR消防安全学习机|沉浸式体验守护生命安全的新方式
科技·学习·安全·vr·虚拟现实
red_redemption2 小时前
自由学习记录(140)
学习
努力学习的小廉2 小时前
我爱学算法之——floodfill算法(上)
学习·算法
booksyhay2 小时前
XCP学习笔记(2)-指令详解
笔记·学习
菜鸡儿齐5 小时前
Unsafe方法学习
java·python·学习
留白_10 小时前
MySQL学习(7)——存储过程
学习