在React中使用Cesium实现添加地图标签
官网申请地图token 用于地图、地形的加载。
了解Cesium
Cesium是一个三维地球和地图可视化开源JavaScript���,由AGI公司的计算机图形开发小组于2011年研发。其名称来源于化学元素铯,铯是制造原子钟的关键元素,研发小组通过命名强调Cesium产品精益求精,专注时间数据可视化。Cesium是一个跨平台、跨浏览器的展示三维地球和地图的JavaScript库,使用WebGL来进行硬件加速图形,使用时不需要任何插件支持。它是基于Apache2.0许可的开源程序,可以免费用于商业和非商业用途,Cesium在国内外都有广泛的研究和应用,特别是在地理信息领域,许多大学和研究机构都在使用Cesium进行地理数据的可视化和分析2。其应用场景包括但不限于地理信息系统(GIS)应用程序、航空航天应用程序、虚拟现实(VR)和增强现实(AR)应用程序以及3D可视化应用程序等。 检查浏览器是否支持WebGL 学习Cesium 要知道的几个网站
GIS基本知识了解
- GIS 全名 叫 地理信息系统(Geographic Information System或 Geo-Information system,GIS),主要是空间相关的技术,通过地图的形式展现空间位置和空间数据。
- 坐标系分为:火星坐标系 (GCJ-02) ,百度坐标系 (BD-09), 百度坐标系 (BD-09) ,国标2000坐标系 (CGCS2000)。国标2000坐标系与WGS84坐标系偏差不大,因为CGCS2000坐标系与WGS84坐标系的原点、尺度、定向及定向演变的定义都是相同的,参考椭球的参数略有不同而已。相同的坐标点,在CGCS2000与WGS84下,经度是相同的,只在纬度上存有0.11mm上下的区别,可以忽略掉。
- 在线坐标转换: 坐标转换
在React中使用Cesium
学习cesium所用所用到的相关知识是相当枯燥的,不如直接写几个demo,先把地球加载出来学习来才够劲。基本的使用cesium网上案例很多,只要把库下载到本地然后参照官方的api初始化一下就可以了。 但是可能是因为生态原因,在工程中想要使用cesium或是因为版本问题,或是因为打包问题,总是很难把项目跑起来。Cesium是一个很复杂的库, 要支持多种使用方式,所以和传统的组件库开箱即用不一样,需要手动在打包流程中进行配置大家遇到的问题基本都是需要手动修改一下webpack对于cesium的编译配置才能够运行成功,官方的教程案例:配置cesium,直接跳到“Add CesiumJS to a webpack app“这个章节。 我这里来分享拿React来使用Cesium的demo。github传送门 react-cesium-demo 我这里使用的是Craco脚��架来初始化的React项目,更加方便一点 直接使用 yarn add craco-cesium cesium
符合来修改webpackage配置,然后
plugins: [
{
plugin: require('craco-cesium')(),
},
],
接下来就可以丝滑的在React中写cesium了,首先我们初始化地球到页面上:
import React, { useEffect, useRef } from 'react';
import styles from './index.module.less';
import {
Viewer,
Ion,
UrlTemplateImageryProvider,
BoundingSphere,
Cartesian3,
} from 'cesium';
import * as Cesium from 'cesium';
/** https://ion.cesium.com/tokens 去创建token */
const CESIUM_TOKEN = ``;
const CesiumDemo: React.FC = () => {
Ion.defaultAccessToken = CESIUM_TOKEN;
const csmViewerRef = useRef<null | Viewer>(null);
const viewerContainerRef = useRef(null);
const init = () => {
if (viewerContainerRef.current && !csmViewerRef.current) {
csmViewerRef.current = new Viewer('csm-viewer-container', {
baseLayerPicker: false, // 如果设置为false,将不会创建右上角图层按钮。
geocoder: false, // 如果设置为false,将不会创建右上角查询(放大镜)按钮。
navigationHelpButton: false, // 如果设置为false,则不会创建右上角帮助(问号)按钮。
homeButton: false, // 如果设置为false,将不会创建右上角主页(房子)按钮。
sceneModePicker: false, // 如果设置为false,将不会创建右上角投影方式控件(显示二三维切换按钮)。
animation: false, // 如果设置为false,将不会创建左下角动画小部件。
timeline: false, // 如果设置为false,则不会创建正下方时间轴小部件。
fullscreenButton: false, // 如果设置为false,将不会创建右下角全屏按钮。
scene3DOnly: true, // 为 true 时,每个几何实例将仅以3D渲染以节省GPU内存。
shouldAnimate: false, // 默认true ,否则为 false 。此选项优先于设置 Viewer#clockViewModel 。
// ps. Viewer#clockViewModel 是用于控制当前时间的时钟视图模型。我们这里用不到时钟,就把shouldAnimate设为false
infoBox: false, // 是否显示点击要素之后显示的信息
sceneMode: 3, // 初始场景模式 1 2D模式 2 2D循环模式 3 3D模式 Cesium.SceneMode
requestRenderMode: false, // 启用请求渲染模式,不需要渲染,节约资源吧
fullscreenElement: document.body, // 全屏时渲染的HTML元素 暂时没发现用处,虽然我关闭了全屏按钮,但是键盘按F11 浏览器也还是会进入全屏
// imageryProvider: new UrlTemplateImageryProvider({
// url: 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
// }),
});
}
const viewer = csmViewerRef.current;
if (!viewer) return;
console.log(viewer);
};
useEffect(() => {
init();
}, []);
return (
<div className={styles.wrapper}>
<div
style={{ width: '1000px', height: '1000px' }}
className="csm-viewer-container"
id="csm-viewer-container"
ref={viewerContainerRef}
></div>
</div>
);
};
export default CesiumDemo;
得到了一个地球 加载地图,并且飞行到苏州的人工智能产业园,相关api可以翻阅中文文档 加载地图
const init = () => {
//...
const viewer = csmViewerRef.current;
if (!viewer) return;
viewer.imageryLayers.addImageryProvider(
new UrlTemplateImageryProvider({
//高德影像标注地图
url: 'http://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8',
})
);
// 设置初始位置 Cesium.Cartesian3.fromDegrees(longitude, latitude, height, ellipsoid, result)
const boundingSphere = new BoundingSphere(
Cartesian3.fromDegrees(120.775997, 31.292397, 100), //苏州人工智能产业园
15000
);
// 定位到初始位置
viewer.camera.flyToBoundingSphere(boundingSphere, {
// 定位到初始位置的过渡时间,设置成0,就没有过渡,类似一个过场的动画时长
duration: 2,
});
console.log(viewer.entities);
};
在地图上为坐标添加标记
const pointInfo = [
{
id: '392f7fbb-ae25-4eef-ac43-58fd91148d1f',
latitude: 31.292397,
longitude: 120.775997,
psName: '人工智能产业园',
}
];
const addMarker = () => {
// 自定义label颜色
const _textColor = 'rgb(11, 255, 244)';
const viewer = csmViewerRef.current!;
// 清除上一次加载的点位
viewer.entities.removeAll();
pointInfo.forEach((pointObj) => {
viewer.entities.add({
name: pointObj.psName,
id: pointObj.id,
position: Cesium.Cartesian3.fromDegrees(
pointObj.longitude * 1,
pointObj.latitude * 1
),
// 点
point: {
pixelSize: 5,
color: Cesium.Color.RED,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
},
// 文字标签
label: {
// show: false,
text: pointObj.psName,
font: '12px monospace',
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
// fillColor: Cesium.Color.LIME,
fillColor: Cesium.Color.fromCssColorString(_textColor),
outlineWidth: 4,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 垂直方向以底部来计算标签的位置
pixelOffset: new Cesium.Cartesian2(0, -20), // 偏移量
},
// 图标
billboard: {
image: ICON,
width: 18,
height: 24,
},
});
});
};
加载实体模型
viewer.entities.add({
name: 'Blue box',
position: Cesium.Cartesian3.fromDegrees(120.55538, 31.87532, 100.0),
box: {
// new Cesium.Cartesian3(长, width, height)
dimensions: new Cesium.Cartesian3(400.0, 1000.0, 1500.0),
material: Cesium.Color.BLUE, // 配置颜色
// material: Cesium.Color.RED.withAlpha(0.5), // 配置颜色透明度
// fill: false, // 配置 是否填满
outline: true, // 配置 是否显示外边框线
outlineColor: Cesium.Color.YELLOW, // 配置 设置外边框线颜色
},
});
viewer.zoomTo(viewer.entities); // 定位到实体
实现效果 以上是在React中使用cesium,实现一些简单效果的案例。
转载自:https://juejin.cn/post/7365771381676802082