Cesium学习文档

Cesium

开始

  1. 创建Vue项目

  2. 安装Cesium:npm install cesium

  3. 将node_modules中的cesium目录下的Build/Cesium中4个目录拷贝到public中

  4. 组件中编写代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    <script setup>
    import * as Cesium from "cesium";
    import "cesium/Build/Cesium/Widgets/widgets.css";
    import { onMounted } from "vue";

    // 设置cesium token
    Cesium.Ion.defaultAccessToken ="你的token";

    // 设置cesium静态资源目录
    window.CESIUM_BASE_URL = "lib/cesium";

    onMounted(() => {
    let viewer = new Cesium.Viewer(cesiumContainer.value, {
    infoBox: false
    });
    });
    </script>

    <template>
    <div id="cesiumContainer" ref="cesiumContainer"></div>
    </template>

    <style scoped>
    #cesiumContainer {
    width: 100vw;
    height: 100vh;
    }
    </style>

    <style>
    * {
    margin: 0;
    padding: 0;
    }
    </style>

初始化地球

  • 设置cesium默认视角

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(
    // 西边的经度
    89.5,
    // 南边的维度
    20.4,
    // 东边的经度
    110.4,
    // 北边的维度
    61.2
    );
  • 显示和隐藏各种图标按钮

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    let viewer = new Cesium.Viewer("cesiumContainer", {
    // 是否显示信息窗口
    infoBox: false,
    // 是否显示查询按钮
    geocoder: false,
    // 是否显示home按钮
    homeButton: false,
    // 控制查看器的显示模式
    sceneModePicker: false,
    // 是否显示图层显示器
    baseLayerPicker: false,
    // 是否显示帮助按钮
    navigationHelpButton: false,
    // 是否播放动画
    animation: false,
    // 是否显示时间轴
    timeline: false,
    // 是否显示全屏按钮
    fullscreenButton: false,
    // 设置天空盒子
    skyBox: new Cesium.SkyBox({
    sources: {
    positiveX: "./texture/sky/px.jpg",
    negativeX: "./texture/sky/nx.jpg",
    positiveY: "./texture/sky/ny.jpg",
    negativeY: "./texture/sky/py.jpg",
    positiveZ: "./texture/sky/pz.jpg",
    negativeZ: "./texture/sky/nz.jpg"
    }
    }),
    // 设置地形
    terrain: Cesium.Terrain.fromWorldTerrain({
    requestVertexNormals: true,
    requestWaterMask: true
    }),
    });

    // 隐藏logo
    viewer.cesiumWidget.creditContainer.style.display = "none";

坐标系及其转换

  • 在cesium中可以将坐标系分为三类

    1. 屏幕坐标系统,二维的笛卡尔坐标系, Cartesian2 类型
    2. 地理坐标系统,WGS-84坐标系, Cartographic 类型,经度,纬度,高度
    3. 笛卡尔空间直角坐标系, Cartesian3 类型
  • 角度转弧度 Cesium.Math.toRadians()

    1
    2
    let radians = Cesium.Math.toRadians(90);
    console.log(radians); // Math.PI / 2
  • 弧度转角度 Cesium.Math.toDegrees()

    1
    2
    let degree = Cesium.Math.toDegrees(2 * Math.PI);
    console.log(degree); // 360
  • 将经纬度转换为笛卡尔坐标 Cesium.Cartesian3.fromDegrees()

    1
    2
    let cartesian3 = Cesium.Cartesian3.fromDegrees(89.5, 20.4, 100);
    console.log(cartesian3); // Cartesian3 {x: 52190.26201691618, y: 5980411.674413431, z: 2209290.583298988}
  • 将笛卡尔坐标转换为经纬度 Cesium.Cartographic.fromCartesian

    1
    2
    let cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
    console.log(cartographic); // Cartographic {longitude: 1.562069680534925, latitude: 0.3560471674068433, height: 99.99999999942615}

相机

  • 设置相机位置 viewer.camera.setView ,设置相机飞行 viewer.camera.flyTo

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    let position = Cesium.Cartesian3.fromDegrees(116.387428, 39.90923, 100);
    viewer.camera.setView({
    // 指定相机的位置
    destination: position,
    // 指定相机视角
    orientation: {
    // 指定相机的朝向,偏航角
    heading: Cesium.Math.toRadians(180),
    // 指定相机的俯仰角,0度是竖直向上,-90度是向下
    pitch: Cesium.Math.toRadians(-90),
    // 指定相机的翻滚角,翻滚角
    roll: 0
    }
    });
  • 相机的动态交互

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    // 通过按键移动相机
    document.addEventListener("keydown", (e) => {
    // 获取相机离地面的高度
    let height = viewer.camera.positionCartographic.height;
    let moveRate = height / 100;
    if (e.key === "w") {
    // 设置相机向前移动
    viewer.camera.moveForward(moveRate);
    } else if (e.key === "s") {
    // 设置相机向后移动
    viewer.camera.moveBackward(moveRate);
    } else if (e.key === "a") {
    // 设置相机向左移动
    viewer.camera.moveLeft(moveRate);
    } else if (e.key === "d") {
    // 设置相机向右移动
    viewer.camera.moveRight(moveRate);
    } else if (e.key === "q") {
    // 设置相机向左旋转
    viewer.camera.lookLeft(Cesium.Math.toRadians(0.1));
    } else if (e.key === "e") {
    // 设置相机向右旋转
    viewer.camera.lookRight(Cesium.Math.toRadians(0.1));
    } else if (e.key === "r") {
    // 设置相机向上旋转
    viewer.camera.lookUp(Cesium.Math.toRadians(0.1));
    } else if (e.key === "f") {
    // 设置相机向下旋转
    viewer.camera.lookDown(Cesium.Math.toRadians(0.1));
    } else if (e.key === "g") {
    // 向左逆时针翻滚
    viewer.camera.twistLeft(Cesium.Math.toRadians(0.1));
    } else if (e.key === "h") {
    // 向右顺时针翻滚
    viewer.camera.twistRight(Cesium.Math.toRadians(0.1));
    }
    });

添加物体

  • 添加3d建筑

    1
    2
    const buildingTileset = await Cesium.createOsmBuildingsAsync();
    viewer.scene.primitives.add(buildingTileset);
  • 添加点

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    let position = Cesium.Cartesian3.fromDegrees(116.387428, 39.90923, 2000);
    viewer.entities.add({
    // 位置
    position,
    // 点
    point: {
    // 点的大小
    pixelSize: 10,
    // 点的颜色
    color: Cesium.Color.RED,
    // 外轮廓颜色
    outlineColor: Cesium.Color.WHITE,
    // 外轮廓的大小
    outlineWidth: 4
    }
    });
  • 添加文字标签和广告牌

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    let position = Cesium.Cartesian3.fromDegrees(116.387428, 39.90923, 2000);
    let label = viewer.entities.add({
    position,
    label: {
    text: "广州塔",
    font: "24px sans-serif",
    fillColor: Cesium.Color.WHITE,
    outlineColor: Cesium.Color.BLACK,
    outlineWidth: 4,
    // FILL填充文字,OUTLINE勾勒标签,FILL_AND_OUTLINE填充文字和勾勒标签
    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
    // 设置文字的偏移量
    pixelOffset: new Cesium.Cartesian2(0, -24),
    // 设置文字的水平显示位置,LEFT/RIGHT/CENTER
    horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
    // 设置文字的垂直显示位置
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM
    },
    billboard: {
    image: "img/广州塔.png",
    width: 50,
    // 设置广告牌的水平显示位置
    horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
    // 设置广告牌的垂直显示位置
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM
    }
    });
  • 添加自定义实体

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    const wyoming = viewer.entities.add({
    polygon: {
    // Cartesian3数组
    hierarchy: Cesium.Cartesian3.fromDegreesArray([
    -109.080842, 45.002073, -105.91517, 45.002073, -104.058488, 44.996596,
    -104.053011, 43.002989, -104.053011, 41.003906, -105.728954, 40.998429,
    -107.919731, 41.003906, -109.04798, 40.998429, -111.047063, 40.998429,
    -111.047063, 42.000709, -111.047063, 44.476286, -111.05254, 45.002073,
    ]),
    height: 0,
    material: Cesium.Color.RED.withAlpha(0.5),
    outline: true,
    outlineColor: Cesium.Color.BLACK,
    },
    });

    viewer.zoomTo(wyoming);

promitive

  • 基本使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    // 1.创建几何体
    let rectGeometry = new Cesium.RectangleGeometry({
    rectangle: Cesium.Rectangle.fromDegrees(
    // 西南东北
    115, 20, 135, 30
    ),
    // 距离地球表面的高度
    height: 0,
    vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
    });

    // 2.创建几何体实例
    let instance = new Cesium.GeometryInstance({
    id: "redRect",
    geometry: rectGeometry,
    attributes: {
    color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED.withAlpha(0.5))
    }
    });

    // 1.创建几何体
    let rectGeometry2 = new Cesium.RectangleGeometry({
    rectangle: Cesium.Rectangle.fromDegrees(
    // 西南东北
    140, 20, 160, 30
    ),
    // 距离地球表面的高度
    height: 0,
    vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
    });

    // 2.创建几何体实例
    let instance2 = new Cesium.GeometryInstance({
    id: "blueRect",
    geometry: rectGeometry2,
    attributes: {
    color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.BLUE.withAlpha(0.5))
    }
    });

    // 3.设置外观
    let appearance = new Cesium.PerInstanceColorAppearance({
    flat: true
    });

    // 4.创建图元
    let primitive = new Cesium.Primitive({
    geometryInstances: [instance, instance2],
    appearance
    });

    // 5.添加到viewer
    viewer.scene.primitives.add(primitive);

    // 动态修改图元颜色
    setInterval(() => {
    let attributes = primitive.getGeometryInstanceAttributes("blueRect");
    attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(
    // Cesium.Color.YELLOW.withAlpha(.5)
    Cesium.Color.fromRandom({
    alpha: .5
    })
    );
    }, 2000);
  • MaterialProperty

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    // 棋盘纹理
    // let material = new Cesium.CheckerboardMaterialProperty({
    // evenColor: Cesium.Color.RED,
    // oddColor: Cesium.Color.YELLOW,
    // repeat: new Cesium.Cartesian2(4, 4)
    // });

    // 条纹纹理
    // let material = new Cesium.StripeMaterialProperty({
    // evenColor: Cesium.Color.WHITE,
    // oddColor: Cesium.Color.BLACK,
    // repeat: 32,
    // });

    // 网格纹理
    let material = new Cesium.GridMaterialProperty({
    color: Cesium.Color.YELLOW,
    cellAlpha: 0.2,
    lineCount: new Cesium.Cartesian2(8, 8),
    lineThickness: new Cesium.Cartesian2(2.0, 2.0),
    });

    // 使用entity创建矩形
    let rectangle = viewer.entities.add({
    id: "entityRect",
    rectangle: {
    coordinates: Cesium.Rectangle.fromDegrees(90, 20, 110, 30),
    // material: Cesium.Color.RED.withAlpha(.5)
    material
    }
    });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
window.getcameraPosInfo = () => {
// 获取 相机姿态信息
const head = viewer.scene.camera.heading;
const pitch = viewer.scene.camera.pitch;
const roll = viewer.scene.camera.roll;
const info = { 'head': head, 'pitch': pitch, 'roll': roll }
// 获取位置 wgs84的地心坐标系,x,y坐标值以弧度来表示
const position = viewer.scene.camera.positionCartographic; //with longitude and latitude expressed in radians and height in meters.
//以下方式也可以获取相机位置只是返回的坐标系不一样
// const position = viewer.scene.camera.position //cartesian3 空间直角坐标系
// const ellipsoid = scene.globe.ellipsoid;
// const position =ellipsoid.cartesianToCartographic(viewer.scene.camera.position)//
// 弧度转经纬度
const longitude = Cesium.Math.toDegrees(position.longitude).toFixed(6);
const latitude = Cesium.Math.toDegrees(position.latitude).toFixed(6);
const height = position.height;
return { lng: longitude, lat: latitude, h: height, mat: info }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cesiumData.viewer.screenSpaceEventHandler.setInputAction((click) => {
// 获取点击位置的屏幕坐标
const pickedPosition = cesiumData.viewer.scene.pickPosition(click.position);

if (Cesium.defined(pickedPosition)) {
// 将屏幕坐标转换为地理坐标(经纬度)
const cartographic = Cesium.Cartographic.fromCartesian(pickedPosition);
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
const latitude = Cesium.Math.toDegrees(cartographic.latitude);

// 打印经纬度到控制台
console.log(`Longitude: ${longitude}, Latitude: ${latitude}`);
} else {
console.log('无法获取经纬度,点击位置可能不在地表上');
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);