【Cesium】学习记录0x01(cesium的基础使用和一些面片理解)

416 阅读4分钟
theme: mk-cute
highlight: atom-one-light
---
# 创建viewer实例

```js
const viewer = new Cesium.Viewer("cesiumContainer");

image.png

创建一个Cesium App


<body>
    <div id="cesiumContainer"></div>
    <script>
        Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIwYjM3YmViOC05MzVkLTQ3ZDEtODU1ZS1hOWI0YmZjMGRjM2QiLCJpZCI6OTE3NzgsImlhdCI6MTY1MTIyNjE4NX0.E90WFKiWipKEiwSBBH3mhw9C3W7ezVMhvriTNeKueZY';
        const viewer=new Cesium.Viewer("cesiumContainer",{
                //关闭动画小组件(左下角仪表盘)
                animation:false,
                //设置以何种方式进行初始化
                //包括:
                //MORPHING	        数字	在模式之间变形,例如,3D 到 2D。
                // COLUMBUS_VIEW	数字	哥伦布视图模式。一个 2.5D 透视图,其中地图平放,其上方绘制了非零高度的对象。
                // SCENE2D	        数字	二维模式。使用正交投影自上而下查看地图。
                // SCENE3D	        数字	3D模式。地球的传统 3D 透视图。
                sceneMode : Cesium.SceneMode.SCENE3D,
                //球体表面提供地形
                terrainProvider : Cesium.createWorldTerrain(),
                //基础图层选择,如交通图、卫星图等
                baseLayerPicker : true,
                //底图数据展示
                //图层放大到最大显示的街景图
                imageryProvider : new Cesium.OpenStreetMapImageryProvider({
                    url : 'https://a.tile.openstreetmap.org/'
                }),
                //场景周围的天空盒,用于绘制星星。天空盒是使用真赤道平均春分 (TEME) 轴定义的。
                //这仅在 3D 中受支持。变形为 2D 或哥伦布视图时,天空盒会淡出。天空盒的大小不能超过Scene#maximumCubeMapSize。
                skyBox : new Cesium.SkyBox({
                    sources : {
                    positiveX : 'stars/TychoSkymapII.t3_08192x04096_80_px.jpg',
                    negativeX : 'stars/TychoSkymapII.t3_08192x04096_80_mx.jpg',
                    positiveY : 'stars/TychoSkymapII.t3_08192x04096_80_py.jpg',
                    negativeY : 'stars/TychoSkymapII.t3_08192x04096_80_my.jpg',
                    positiveZ : 'stars/TychoSkymapII.t3_08192x04096_80_pz.jpg',
                    negativeZ : 'stars/TychoSkymapII.t3_08192x04096_80_mz.jpg'
                    }
                }),
                // 定义椭球体转换成哥伦布2.5D图像时如何转换
                mapProjection : new Cesium.WebMercatorProjection()
});
    </script>
</body>

cesium中重要的一些容器

        //cesium中三维与地形的基本容器
        var scene = viewer.scene;
        //canvas
        var canvas = viewer.canvas;
        //时钟
        var clock = viewer.clock;
        //相机
        var camera = viewer.scene.camera;
        //平面矢量数据容器
        var entities = viewer.entities;
        
        //加快时钟的运行
        clock.multiplier = 0.1 * 60 * 60;
        //阳光照射区域高亮
        scene.globe.enableLighting = true;

设置镜头的位置与方向

        //设置镜头位置与方向
        camera.setView( {
            //镜头的经纬度、高度。镜头默认情况下,在指定经纬高度俯视(pitch=-90)地球
            position : Cesium.Cartesian3.fromDegrees( 116.3, 39.9, 100000000 ),//北京100000公里上空
            //下面的几个方向正好反映默认值
            heading : Cesium.Math.toRadians( 0 ),
            pitch : Cesium.Math.toRadians( 90 ),
            roll : Cesium.Math.toRadians( 0 )
        } );

移动相机位置


        setTimeout( function()
        {
            camera.flyTo( {
                destination : Cesium.Cartesian3.fromDegrees( 120.55, 28.5, 6000000 ),
                orientation : {
                    heading : Cesium.Math.toRadians( 0 ),//镜头旋转
                    pitch : Cesium.Math.toRadians( -90 ),//竖直方向旋转
                    roll : Cesium.Math.toRadians( 0 )//水平方向旋转
                },
                duration : 1,//动画持续时间
                complete : function()//飞行完毕后执行的动作
                {
                    // addEntities();

                }
            } );
        }, 1000 );
        

效果:

image.png

Viewer对象的属性解析

  animation: false, //是否创建动画小器件,左下角仪表
  baseLayerPicker: false,//是否显示图层选择器,右上角按钮
  fullscreenButton: false,//是否显示全屏按钮,右下角按钮
  geocoder: false,//是否显示geocoder小器件,右上角查询按钮
  homeButton: true,//是否显示Home按钮,右上角按钮
  infoBox : false,//是否显示信息框
  sceneModePicker: false,//是否显示3D/2D选择器 ,右上角按钮
  selectionIndicator : false,//是否显示选取指示器组件,绿色选中框
  timeline: false,//是否显示时间轴,底部
  navigationHelpButton: false,//是否显示帮助按钮,右上角按钮
  imageryProvider:.... //底图数据提供

Scene对象的属性解析

介绍:Cesium 虚拟场景中所有 3D 图形对象和状态的容器。一般不直接创建场景;相反,它是由CesiumWidget间接创建的

坐标系

Cesium中的几种坐标和相互转换

1、平面坐标系(Cartesian2)

new Cesium.Cartesian2(x, y)

2、笛卡尔空间直角坐标系-世界坐标(Cartesian3)

new Cesium.Cartesian3(x, y, z)

3、弧度(Cartographic)

new Cesium.Cartographic(longitude, latitude, height)   

注:这里的经纬度是用弧度表示的,经纬度其实就是角度。弧度即角度对应弧长是半径的倍数。
角度转弧度: π / 180 × 角度 
弧度变角度: 180 / π × 弧度 

4、经纬度(longitude,latitude)

地理坐标系,坐标原点在椭球的质心。

经度:参考椭球面上某点的大地子午面与本初子午面间的两面角。东正西负。

纬度:参考椭球面上某点的法线与赤道平面的夹角。北正南负。

坐标转换

1.经纬度转换为世界坐标

第一种方式:直接转换:
Cesium.Cartesian3.fromDegrees(longitude, latitude, height, ellipsoid, result) 

第二种方式:先转换成弧度再转换
var ellipsoid = viewer.scene.globe.ellipsoid;
var cartographic = Cesium.Cartographic.fromDegrees(lng,lat,alt);
var cartesian3 = ellipsoid.cartographicToCartesian(cartographic);

2.世界坐标转换为经纬度

var ellipsoid = viewer.scene.globe.ellipsoid;
var cartesian3 = new Cesium.cartesian3(x,y,z);
var cartographic = ellipsoid.cartesianToCartographic(cartesian3);
var lat = Cesium.Math.toDegrees(cartograhphic.latitude);
var lng = Cesium.Math.toDegrees(cartograhpinc.longitude);
var alt = cartographic.height;

3.弧度和经纬度

经纬度转弧度:
Cesium.CesiumMath.toRadians(degrees) 
弧度转经纬度:
Cesium.CesiumMath.toDegrees(radians) 

4.屏幕坐标和世界坐标相互转换

屏幕转世界坐标:
var pick1= new Cesium.Cartesian2(0,0);
var cartesian = viewer.scene.globe.pick(viewer.camera.getPickRay(pick1),viewer.scene);    
注意这里屏幕坐标一定要在球上,否则生成出的cartesian对象是undefined

世界坐标转屏幕坐标
Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, Cartesian3);
结果是Cartesian2对象,取出X,Y即为屏幕坐标。

5.Cartesian2

Cesium.Cartesian2.fromCartesian3(cartesian, result)→ Cartesian2

6.Cartesian3

I:经纬度坐标(WGS84)→ Cartesian3
Cesium.Cartesian3.fromDegrees(longitude, latitude, height, ellipsoid, result) → Cartesian3

II:弧度坐标→ Cartesian3
Cesium.Cartesian3.fromRadians(longitude, latitude, height, ellipsoid, result) → Cartesian3

7.Cartographic

I:Cartesian3→ Cartographic
Cesium.Cartographic.fromCartesian(cartesian, ellipsoid, result) → Cartographic

II:经纬度坐标(WGS84)→ Cartographic
Cesium.Cartographic.fromDegrees(longitude, latitude, height, result) → Cartographic   

另外,经纬度坐标和弧度坐标也可以通过Cesium.Math来转换
Cesium.CesiumMath.toDegrees(radians) → Number
Cesium.CesiumMath.toRadians(degrees) → Number        

详细内容可以看这里

以下内容均为官方demo中的一些案例

Camera初步

          
        canvas.setAttribute("tabindex", "0"); 

        canvas.onclick = function () {
        canvas.focus();
        };

        //椭球
        const ellipsoid = scene.globe.ellipsoid;

        //关闭默认动作
        // scene.screenSpaceCameraController.enableRotate = false;
        scene.screenSpaceCameraController.enableTranslate = false;
        scene.screenSpaceCameraController.enableZoom = false;
        scene.screenSpaceCameraController.enableTilt = false;
        scene.screenSpaceCameraController.enableLook = false;

        let startMousePosition;
        let mousePosition;

        const flags = {
        looking: false,
        moveForward: false,
        moveBackward: false,
        moveUp: false,
        moveDown: false,
        moveLeft: false,
        moveRight: false,
        };

        //处理canvas相关动作
        //处理用户输入事件。可以添加自定义功能以在用户输入时执行。
        const handler = new Cesium.ScreenSpaceEventHandler(canvas);

        //设置要在输入事件上执行的功能。
        //第一个参数,设置事件发生时的执行的函数
        //第二个参数,设置屏幕空间事件类型

        //鼠标左键按下
        handler.setInputAction(function (movement) {
            flags.looking = true;
            mousePosition = startMousePosition = Cesium.Cartesian3.clone(
                movement.position
            );

        }, Cesium.ScreenSpaceEventType.LEFT_DOWN);

        //鼠标移动事件,相对于屏幕的位置
        handler.setInputAction(function (movement) {
             mousePosition = movement.endPosition;
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

        //鼠标左键抬起事件,相对与屏幕的位置
        handler.setInputAction(function (position) {
            flags.looking = false;
        }, Cesium.ScreenSpaceEventType.LEFT_UP);

        function getFlagForKeyCode(keyCode) {
            switch (keyCode) {
                case "W".charCodeAt(0):
                return "moveForward";
                case "S".charCodeAt(0):
                return "moveBackward";
                case "Q".charCodeAt(0):
                return "moveUp";
                case "E".charCodeAt(0):
                return "moveDown";
                case "D".charCodeAt(0):
                return "moveRight";
                case "A".charCodeAt(0):
                return "moveLeft";
                default:
                return undefined;
            }
        }

        document.addEventListener(
        "keydown",
        function (e) {
            const flagName = getFlagForKeyCode(e.keyCode);
            if (typeof flagName !== "undefined") {
            flags[flagName] = true;
            }
        },
        false
        );

        document.addEventListener(
        "keyup",
        function (e) {
            const flagName = getFlagForKeyCode(e.keyCode);
            if (typeof flagName !== "undefined") {
            flags[flagName] = false;
            }
        },
        false
        );

        //为视图的时间帧添加事件
        viewer.clock.onTick.addEventListener(function (clock) {
            const camera = viewer.camera;

            if (flags.looking) {
                const width = canvas.clientWidth;
                const height = canvas.clientHeight;

                // Coordinate (0.0, 0.0) will be where the mouse was clicked.
                const x = (mousePosition.x - startMousePosition.x) / width;
                const y = -(mousePosition.y - startMousePosition.y) / height;

                const lookFactor = 0.05;
                camera.lookRight(x * lookFactor);
                camera.lookUp(y * lookFactor);
            }

            //根据高度调整相机移动速度
            const cameraHeight = ellipsoid.cartesianToCartographic(
                camera.position
            ).height;
            const moveRate = cameraHeight / 1000.0;

            if (flags.moveForward) {
                camera.moveForward(moveRate);
            }
            if (flags.moveBackward) {
                camera.moveBackward(moveRate);
            }
            if (flags.moveUp) {
                camera.moveUp(moveRate);
            }
            if (flags.moveDown) {
                camera.moveDown(moveRate);
            }
            if (flags.moveLeft) {
                camera.moveLeft(moveRate);
            }
            if (flags.moveRight) {
                camera.moveRight(moveRate);
            }
        });         

Imegery layers(图片层)

image.png

image.png

官方案例放大失真

        //imagery layer 
        //主要作用,在globe上显示来自单个图像提供者的平铺图像
        const layer=scene.imageryLayers;

        //平铺图像提供者
        //要在Globe上添加新的图像必须提供图像提供者
        //图像图层

        layers.addImageryProvider(
        new Cesium.SingleTileImageryProvider({
            url: "./Assets/Images/ion-credit.png",
            rectangle: Cesium.Rectangle.fromDegrees(120.55, 28.5, 128, 30.25),
        })
        );