Cesium

Cesium

Cesium API

demo 仓库地址

一、开始

1.1 token

注册一个 Cesium Ion ,在 Access Tokens 的右侧的 Token 处,复制到 js 文件中,赋值到 token,并设置:

Cesium.Ion.defaultAccessToken = token;

1.2 创建 Cesium

使用 Cesium.Viewer() 创建一个 Cesium ,第一个参数是创建的 Cesium 容器( DOM )的 id 名,不需要加 #,第二个参数是配置项,用参数配置。

const viewer = new Cesium.Viewer('', {
    geocoder: false, // 是否创建右上角的查询按钮(右上第一个)
    homeButton: false, // 是否创建 home 按钮(右上第二个)
    sceneModePicker: false, // 是否创建右上角的切换地图的按钮(右上第三个)
    baseLayerPicker: false, // 是否创建右上角 BaseLayerPicker 小部件(右上第四个)
    navigationHelpButton: false, // 是否创建右上角的导航帮助按钮(右上第五个
    // vrButton: true, // 是否创建右下角的 VR 按钮,默认值为 true
    animation: false, // 是否创建左下角的动画小部件
    fullscreenButton: false, // 是否创建右下角全屏按钮
    timeline: false, // 是否创建最下方的时间线
    infoBox: false, // 点击实体是否展示详情
    selectionIndicator: false, // 点击实体是否显示选中样式
    // 左下方的 Cesium logo 使用 css 删除
    terrainProvider: Cesium.createWorldTerrain(), // 加载地球椭球体
});

更多配置

二、创建点、线、面实体

2.1 entities.add()

// 点实体
viewer.entities.add({
    position: position, // 格式为世界坐标的点位置
	point: {
        show: ture, // 点是否可见
        pixelSize: Number, // 点的大小
        color: color, // 点的颜色
        outlineClor: color, // 边框颜色
        outlineWidth: Number, // 轮廓宽度
    },
});
// 线实体
viewer.entities.add({
    polyline: {
        show: Boolean, // 线是否可见
        positions: positions, // 格式为世界坐标的线位置数组
        width: Number, // 线的宽度
        material: color, // 线的颜色
        clampToGround: Boolean, // 线是否固定在地面
    },
});
// 面实体
viewer.entities.add({
    polygon: {
        show: Boolean, // 面是否可见
        hierarchy: positions, // 格式为世界坐标的面位置数组
        height: Number, // 面相对于椭球表面的高度
        fill: Boolean, // 面是否有填充
        material: color, // 面的填充颜色
        outline: Boolean, // 面是否有边框
        outlinColor: color, // 边框的颜色
        outlineWidth: Number, // 边框的宽度,无论设置为多少宽度始终只会显示为 1
        perPositionHeight: Boolean, // 面是否使用每个位置的高度
    },
});

2.2 Cesium.TypeGraphices()

// 点实体
viewer.entities.add({
    position: position, // 格式为世界坐标的点位置
    point: new Cesium.PointGraphics({
        show: Boolean, // 点是否可见
        pixelSize: Number, // 点的大小
        color: color, // 点的颜色
        outlineClor: color, // 边框宽度
        outlineWidth: Boolean, // 轮廓颜色
    });
});
// 线实体
viewer.entities.add({
    golyline: new Cesium.PolylineGraphics({
        show: Boolean, // 线是否可见
        positions: positions, // 格式为 Cartesian3 的线位置数组
        width: Number, // 线的宽度
        material: color, // 线的颜色
        clampToGround: Boolean, // 线是否固定在地面
    });
});
// 面实体
viewer.entities.add({
    golygon: new Cesium.PolygonGraphics({
        show: Boolean, // 面是否可见
        hierarchy: positions, // 格式为 Cartesian3 的面位置数组
        height: Number, // 面相对于椭球表面的高度
        fill: Boolean, // 面是否有填充
        material: color, // 面的填充颜色
        outline: Boolean, // 面是否有边框
        outlinColor: color, // 边框的颜色
        outlineWidth: Number, // 边框的宽度,无论设置为多少宽度始终只会显示为 1
        perPositionHeight: Boolean, // 面是否使用每个位置的高度
    });
});

三、格式转换

Cesium中的坐标相互转换

3.1 格式类型

平面坐标系( Cartesian2

new Cesium.Cartesian2(x, y)

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

new Cesium.Cartesian3(x, y, z);

弧度

new Cesium.Cartographic(lng, lat, height);

经纬度

(lng, lat)

3.2 坐标转化

3.2.1 经纬度和世界坐标
// 经纬度转为世界坐标
Cesium.Cartesian3.fromDregrees(lng, lat, height);
// 世界坐标转为经纬度
const ellipsoid = viewer.scene.globe.ellipsoid;
const cartiesian3 = new Cesium.Cartesian3(x, y, z);
const cartographic = ellipsoid.cartesianToCartographic(cartesian3);
const lng = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;

封装为方法

// 世界坐标转为经纬度
// 参数可以是一个世界坐标,也可以是一组世界坐标数组
function toLatAndLng(position) {
    if (Array.isArray(position)) {
        return position.map(item => toLatAndLng(item));
    } else {
        const cartographic = ellipsoid.cartesianToCartographic(position);
        const lng = Cesium.Math.toDegrees(cartographic.longitude);
        const lat = Cesium.Math.toDegrees(cartographic.latitude);
        const height = cartographic.height;
        return [lng, lat, height];
    }
};
3.2.2 平面坐标和世界坐标
// 屏幕坐标转为世界坐标
const pick1 = new Cesium.Cartesian2(0, 0);
const cartesian = viewer.scene.globe.pick(viewer.camera.getPickRay(pick1), viewer.scene);
// 世界坐标转为屏幕坐标
Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, Cartesian3)
3.2.3 弧度和经纬度
// 弧度转为经纬度
Cesium.Math.toRadians(degrees);
// 经纬度转为弧度
Cesium.Math.toDregees(radians);

3.3 其他格式转化

// 返回指定经度和纬度的二维区域
new Cesium.Rectangle.fromDegrees(
	Number, // 最西的经度
	Number, // 最南端的纬度
	Number, // 最东的经度
	Number // 最北端的纬度
);
// 返回颜色
Cesium.Color.fromCssColorString(
	color // css 的颜色样式
).withAlpha(
	Number // 颜色的透明度,0 - 1
);

封装为方法

// 跳转的到一个区域,且最后得到的图形是整个范围的 1/3
function flyToRectangle(position, time) {
    const WE = position.east - position.west;
    const NS = position.north - position.south;
    viewer.camera.flyTo({
        destination: Cesium.Rectangle.fromDegrees(
        	position.west - WE,
         	position.south - NS,
        	position.east + WE,
            position.north + NS
        ),
        duration: time || 0.8,
    });
};

3.4 地球二三维切换

// 切换为三维
viewer.scene.morphTo3D({
    duration: Number // 切换花费的时间
});
// 切换为二维
viewer.scene.morphTo2D({
    duration: Number // 切换花费的时间
});

四、镜头跳转

4.1 flyTo()

// 跳转设置点或区域
viewer.camera.flyTo({
    // destination: position, 跳转到某一点时,格式为 Cartesian3 的位置
    destination: Rectangle, // 跳转到某一区域
    duration: Number, // 镜头飞行时长
});
// 跳转某一实体
viewer.flyTo(
    target, // 实体
    {
        duration: Number, // 镜头飞行时长
        maximumHeight: Number, // 镜头飞行的最大高度
        offset: new Cesium.HeadingPitchRangce(
            Number, // 航向角,格式为弧度
            Number, // 俯仰角,格式为弧度
            Number, // 据中心的距离
        ),
    },
);

4.2 zoomTo()

// 跳转某一实体,且可以设置航向角,俯仰角和据中心距离
viewer.zommTo(
	target, // 实体
    new Cesium.HeadingPitchRange(
        Number, // 航向角,格式为弧度
        Number, // 俯仰角,格式为弧度
        Number, // 据中心的距离
    ),
);

五、导入数据源

5.1 GeoJsonDataSource

// 导入格式为 GeoJSON 或 TopoJSON 的实体
viewer.dataSources.add(Cesium.GeoJsonDataSource.load(data, { // data 为需要加载的数据
    markerSize: Number, // 为每个点创建的地图图钉的默认大小
    stroke: Color, // 折线和多边形轮廓的默认颜色
    strokeWidth: Number, // 折线和多边形轮廓的默认宽度
    fill: Color, // 多边形内部的默认颜色
    clampToGround: Boolean, // 是否固定在地面
})).then(dataSourcre => {
    console.log(dataSourcre);
});

4.2 KmlDataSource

// 导入格式为 KML 的实体
viewer.dataSources.add(data, { // data 为需要加载的数据
    camera: camera, // 用于viewRefreshModes并将摄像机属性发送到网络链接的摄像机
    canvas: canvas, // 用于将查看器属性发送到网络链接的画布
    clampToGround: Boolean, // 是否固定在地面
}).then(dataSource => {
    console.log(dataSource);
});

六、事件

事件解析

6.1 事件类型

鼠标左键

事件类型 含义
LEFT_CLICK 单击
LEFT_DOUBLE_CLICK 双击
LEFT_DOWN 左键按下
LEFT_UP 左键弹起

鼠标中键

事件类型 含义
MIDDLE_CLICK 点击
MIDDLE_DOWN 中键按下
MIDDLE_UP 中键弹起

鼠标右键

事件类型 含义
RIGHT_CLICK 点击
RIGHT_DOWN 右键按下
RIGHT_UP 右键弹起

其他鼠标事件

事件类型 含义
MOUSE_MOVE 鼠标移动事件
WHEEL 鼠标滚轮事件

6.2 Cesium.ScreenSpaceEventHandler()

使用 Cesium.ScreenSpaceEventHandler() 获取需要注册点击事件的 Cesium

const handler = new Cesium.ScreenSpaceEventHandler(viewer);

6.3 Cesium.ScreenSpaceEventType()

使用 Cesium.ScreenSpaceEventType() 获取触发事件的条件,例如获取点击左键

const LEFT_CLICK = Cesium.ScreenSpaceEventType(LEFT_CLICK);

6.4 handler.setInputAction()

使用 handler.setInputAction() 监听触发的事件,第一个参数是触发事件调用的方法函数,第二个参数是触发事件的类型

handler.setInputAction(event => {
    console.log(event);
}, LEFT_CLICK);

event 中的位置格式是平面坐标

6.4 viewer.scene.dirllPick()

// 返回包含点的所有实体集合,是一个数组
viewer.scene.dirllPick(
	position, // 平面坐标
 	Number // 收集到指定个数的实体就停止获取,可选
);

配合点击事件

const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
handler.setInputAction(event => {
    const entities = viewer.scene.dirllPick(event.position);
    console.log(entities);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

6.5 viewer.selectedEntityChanged.addEventListener

// 点击左键时,若点击的实体产生变化才会调用
viewer.selectedEntityChanged.addEventListener(entity => {
    console.log(entity);
})

七、动态绘制点、线、面

7.1 动态绘制点

在鼠标移动事件中,第一次触发移动事件时,就创建一个点实体,以后触发移动事件时就先删除上一次触发移动事件创建的实体,再创建一个新的实体。

7.2 动态绘制线

动态绘制线与动态绘制点相似,但是,在绘制过程中, polyline 中的 positions 属性值需要使用 Cesium.CallbackProperty() 方法来获取。

viewer.entities.add({
    polyline: {
        positions: new Cesium.CallbackProperty(function() {
            return positions;
        }, false),
        material: Color,
        width: Number,
    }
});

7.3 动态绘制面

动态绘制面 demo

动态绘制面与动态绘制线相似,但是,在 polygon 中的 hierarchy 属性值除需要使用 Cesium.CallbackProperty() 方法来获取外,还需要使用 Cesium.PolygonHierarchy() 返回。

viewer.entities.add({
    polygon: {
        hierarchy: new Cesium.CallbackProoerty(function() {
            return new Cesium.PolyHierarchy(positions);
        }, false),
        material: Color,
    }
});

八、加载地图(高德)

8.1 引入地图资源

使用方法 Cesium.UrlTemplateImageryProvider() 引入地图资源

// Cesium 加载高德矢量地图
var layer = new Cesium.UrlTemplateImageryProvider({
    url: "http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
    minimumLevel: 4,
    maximumLevel: 18
});
// Cesium 加载高德影像
var imgLayer = new Cesium.UrlTemplateImageryProvider({
    url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
    minimumLevel: 3,
    maximumLevel: 18
});
// Cesium 加载注记要素
var annLayer = new Cesium.UrlTemplateImageryProvider({
    url: "http://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8",
    minimumLevel: 3,
    maximumLevel: 18
});

// Cesium 加载天地图
var dmap = new Cesium.UrlTemplateImageryProvider({
    url: "https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}",
    minimumLevel: 4,
    maximumLevel: 18 
});

8.2 加载地图资源

viewer.imageryLayers.addImageryProvider();

8.3 地图搜索

高德地图 API

九、计算长度、面积

@turf/turf

使用插件 turfCDN 引入

<script src="https://cdn.jsdelivr.net/npm/@turf/turf@5/turf.min.js">script>

import 引入

import turf as * from "@turf/turf";

9.1 根据长度计算长度

// positions 需要计算线状实体的位置信息,是一个数组,每个元素是经纬度
const polyline = turf.lineString(positions);
const length = turf.length(polyline);

9.2 根据点经纬度计算面积

// hierarchy 需要计算面状实体的位置信息,是一个数组,每个元素是经纬度,且第一个元素与最后一个元素要相同
const polygon = turf.polygon([hirerachy]);
const area = turf.area(polygon);

十、其他

// 开启抗锯齿
viewer.scene.postProcessStages.fxaa.enabled = true;
// 取消默认的左键双击事件
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

你可能感兴趣的:(javascript,开发语言,ecmascript)